mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
fix scrngrab
This commit is contained in:
parent
9a7e4b319c
commit
e6835c614b
@ -276,8 +276,8 @@ void DXGraphicsStateGuardian::SetFPSMeterPosition(RECT &view_rect) {
|
|||||||
if(_fpsmeter_verts==NULL)
|
if(_fpsmeter_verts==NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DWORD renderWid = view_rect.right - view_rect.left;
|
DWORD renderWid = RECT_XSIZE(view_rect);
|
||||||
DWORD renderHt = view_rect.bottom - view_rect.top;
|
DWORD renderHt = RECT_YSIZE(view_rect);
|
||||||
|
|
||||||
// adjust these to match fontsize (these are hacks for default font, probably should get char width from win32)
|
// adjust these to match fontsize (these are hacks for default font, probably should get char width from win32)
|
||||||
#define FPSMETER_NUMFONTLETTERS 11 // need 11 letters [0-9.]
|
#define FPSMETER_NUMFONTLETTERS 11 // need 11 letters [0-9.]
|
||||||
@ -3927,6 +3927,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb,
|
|||||||
void DXGraphicsStateGuardian::
|
void DXGraphicsStateGuardian::
|
||||||
copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
||||||
|
|
||||||
|
RECT SrcCopyRect;
|
||||||
nassertv(pb != NULL && dr != NULL);
|
nassertv(pb != NULL && dr != NULL);
|
||||||
|
|
||||||
int xo, yo, w, h;
|
int xo, yo, w, h;
|
||||||
@ -3941,30 +3942,80 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
|||||||
IDirect3DSurface8 *pD3DSurf;
|
IDirect3DSurface8 *pD3DSurf;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
RECT WindRect;
|
||||||
|
GetWindowRect(scrn.hWnd,&WindRect);
|
||||||
|
|
||||||
// just handling front and backbuf for now, not textures yet
|
// just handling front and backbuf for now, not textures yet
|
||||||
if(_cur_read_pixel_buffer & RenderBuffer::T_back) {
|
if(_cur_read_pixel_buffer & RenderBuffer::T_back) {
|
||||||
hr=scrn.pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf);
|
hr=scrn.pD3DDevice->GetBackBuffer(0,D3DBACKBUFFER_TYPE_MONO,&pD3DSurf);
|
||||||
} else if(_cur_read_pixel_buffer & RenderBuffer::T_front) {
|
|
||||||
// must create a X8R8G8B8 sysmem surface for GetFrontBuffer to copy to
|
|
||||||
|
|
||||||
hr=scrn.pD3DDevice->CreateImageSurface(w,h,D3DFMT_A8R8G8B8,&pD3DSurf);
|
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
dxgsg_cat.error() << "CreateImageSurface failed in copy_pixel_buffer(), hr = " << D3DERRORSTRING(hr);
|
dxgsg_cat.error() << "GetBackBuffer failed, hr = " << D3DERRORSTRING(hr);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr=scrn.pD3DDevice->GetFrontBuffer(pD3DSurf);
|
D3DSURFACE_DESC SurfDesc;
|
||||||
|
hr = pD3DSurf->GetDesc(&SurfDesc);
|
||||||
|
|
||||||
|
SrcCopyRect.top=SrcCopyRect.left=0;
|
||||||
|
SrcCopyRect.right=SurfDesc.Width;
|
||||||
|
SrcCopyRect.bottom=SurfDesc.Height;
|
||||||
|
|
||||||
|
// note if you try to grab the backbuffer and full-screen anti-aliasing is on,
|
||||||
|
// the backbuffer might be larger than the window size. for screenshots its safer to get the front buffer.
|
||||||
|
|
||||||
|
} else if(_cur_read_pixel_buffer & RenderBuffer::T_front) {
|
||||||
|
// must create a A8R8G8B8 sysmem surface for GetFrontBuffer to copy to
|
||||||
|
|
||||||
|
DWORD TmpSurfXsize,TmpSurfYsize;
|
||||||
|
|
||||||
|
if(scrn.PresParams.Windowed) {
|
||||||
|
// GetFrontBuffer retrieves the entire desktop for a monitor, so need space for that
|
||||||
|
|
||||||
|
MONITORINFO minfo;
|
||||||
|
minfo.cbSize = sizeof(MONITORINFO);
|
||||||
|
GetMonitorInfo(scrn.hMon, &minfo); // have to use GetMonitorInfo, since this gsg may not be for primary monitor
|
||||||
|
|
||||||
|
TmpSurfXsize=RECT_XSIZE(minfo.rcMonitor);
|
||||||
|
TmpSurfYsize=RECT_YSIZE(minfo.rcMonitor);
|
||||||
|
|
||||||
|
// set SrcCopyRect to client area of window in scrn coords
|
||||||
|
GetClientRect( scrn.hWnd, &SrcCopyRect);
|
||||||
|
ClientToScreen( scrn.hWnd, (POINT*)&SrcCopyRect.left );
|
||||||
|
ClientToScreen( scrn.hWnd, (POINT*)&SrcCopyRect.right );
|
||||||
|
} else {
|
||||||
|
TmpSurfXsize=RECT_XSIZE(WindRect);
|
||||||
|
TmpSurfYsize=RECT_YSIZE(WindRect);
|
||||||
|
|
||||||
|
SrcCopyRect.top=SrcCopyRect.left=0;
|
||||||
|
SrcCopyRect.right=TmpSurfXsize;
|
||||||
|
SrcCopyRect.bottom=TmpSurfYsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr=scrn.pD3DDevice->CreateImageSurface(TmpSurfXsize,TmpSurfYsize,D3DFMT_A8R8G8B8,&pD3DSurf);
|
||||||
|
if(FAILED(hr)) {
|
||||||
|
dxgsg_cat.error() << "CreateImageSurface failed in copy_pixel_buffer(), hr = " << D3DERRORSTRING(hr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
hr=scrn.pD3DDevice->GetFrontBuffer(pD3DSurf);
|
||||||
|
|
||||||
|
if(hr==D3DERR_DEVICELOST) {
|
||||||
|
// dont necessary want to exit in this case
|
||||||
|
pD3DSurf->Release();
|
||||||
|
dxgsg_cat.error() << "copy_pixel_buffer failed: device lost\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dxgsg_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
|
dxgsg_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(FAILED(hr)) {
|
if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) {
|
||||||
dxgsg_cat.error() << "copy_pixel_buffer: " << ((_cur_read_pixel_buffer & RenderBuffer::T_back) ? "GetBackBuffer" : "GetFrontBuffer")
|
dxgsg_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n";
|
||||||
<< " failed, hr = " << D3DERRORSTRING(hr);
|
exit(1);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ConvertD3DSurftoPixBuf(pD3DSurf,pb);
|
(void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb);
|
||||||
|
|
||||||
ULONG refcnt;
|
ULONG refcnt;
|
||||||
RELEASE(pD3DSurf,dxgsg,"pD3DSurf",RELEASE_ONCE);
|
RELEASE(pD3DSurf,dxgsg,"pD3DSurf",RELEASE_ONCE);
|
||||||
@ -5797,8 +5848,8 @@ dx_resize_window(HWND mwindow, RECT viewrect) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
scrn.PresParams.BackBufferWidth = viewrect.bottom-viewrect.top;
|
scrn.PresParams.BackBufferWidth = RECT_XSIZE(viewrect);
|
||||||
scrn.PresParams.BackBufferHeight = viewrect.right-viewrect.left;
|
scrn.PresParams.BackBufferHeight = RECT_YSIZE(viewrect);
|
||||||
HRESULT hr=scrn.pD3DDevice->Reset(&scrn.PresParams);
|
HRESULT hr=scrn.pD3DDevice->Reset(&scrn.PresParams);
|
||||||
|
|
||||||
if(FAILED(hr)) {
|
if(FAILED(hr)) {
|
||||||
@ -6133,9 +6184,10 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void DXGraphicsStateGuardian::adjust_view_rect(int x, int y) {
|
void DXGraphicsStateGuardian::adjust_view_rect(int x, int y) {
|
||||||
if (scrn.view_rect.left != x || scrn.view_rect.top != y) {
|
if (scrn.view_rect.left != x || scrn.view_rect.top != y) {
|
||||||
scrn.view_rect.right = x + scrn.view_rect.right - scrn.view_rect.left;
|
|
||||||
|
scrn.view_rect.right = x + RECT_XSIZE(scrn.view_rect);
|
||||||
scrn.view_rect.left = x;
|
scrn.view_rect.left = x;
|
||||||
scrn.view_rect.bottom = y + scrn.view_rect.bottom - scrn.view_rect.top;
|
scrn.view_rect.bottom = y + RECT_YSIZE(scrn.view_rect);
|
||||||
scrn.view_rect.top = y;
|
scrn.view_rect.top = y;
|
||||||
|
|
||||||
// set_clipper(clip_rect);
|
// set_clipper(clip_rect);
|
||||||
|
@ -712,7 +712,8 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer
|
// still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer
|
||||||
HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf) {
|
HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf) {
|
||||||
|
// copies SrcRect in pD3DSurf to upper left of pixbuf
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD dwNumComponents=pixbuf->get_num_components();
|
DWORD dwNumComponents=pixbuf->get_num_components();
|
||||||
|
|
||||||
@ -728,67 +729,33 @@ HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD dwXWindowOffset,dwYWindowOffset;
|
||||||
|
DWORD dwCopyWidth,dwCopyHeight;
|
||||||
|
|
||||||
D3DLOCKED_RECT LockedRect;
|
D3DLOCKED_RECT LockedRect;
|
||||||
D3DSURFACE_DESC SurfDesc;
|
D3DSURFACE_DESC SurfDesc;
|
||||||
|
|
||||||
hr = pD3DSurf8->GetDesc(&SurfDesc);
|
hr = pD3DSurf8->GetDesc(&SurfDesc);
|
||||||
|
|
||||||
hr = pD3DSurf8->LockRect(&LockedRect,(CONST RECT*)NULL,(D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE /* | D3DLOCK_NOSYSLOCK */));
|
dwXWindowOffset=SrcRect.left,dwYWindowOffset=SrcRect.top;
|
||||||
if(FAILED(hr)) {
|
dwCopyWidth=RECT_XSIZE(SrcRect);
|
||||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf LockRect() failed! hr = " << D3DERRORSTRING(hr);
|
dwCopyHeight=RECT_YSIZE(SrcRect);
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD dwXWindowOffset=0,dwYWindowOffset=0;
|
|
||||||
DWORD dwCopyWidth=SurfDesc.Width,dwCopyHeight=SurfDesc.Height;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
bugbug: need to test scrngrab for windowed case. do I need to do the clientrect stuff?
|
|
||||||
|
|
||||||
// get window offset so we know where to start grabbing pixels. note for
|
|
||||||
// fullscreen primary no clipper will be attached, that 'error' should be ignored
|
|
||||||
LPDIRECTDRAWCLIPPER pDDClipper;
|
|
||||||
hr = pDDSurf->GetClipper(&pDDClipper);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
if(FAILED(hr) && !((hr == DDERR_NOCLIPPERATTACHED) && dx_full_screen)) {
|
|
||||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf GetClipper failed! hr = " << ConvD3DErrorToString(hr) << "\n";
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(hr==S_OK) {
|
|
||||||
HWND hWin;
|
|
||||||
|
|
||||||
if(FAILED(hr = pDDClipper->GetHWnd(&hWin))) {
|
|
||||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf GetHwnd failed! hr = " << ConvD3DErrorToString(hr) << "\n";
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RECT view_rect;
|
|
||||||
GetClientRect( hWin, &view_rect );
|
|
||||||
ClientToScreen( hWin, (POINT*)&view_rect.left );
|
|
||||||
ClientToScreen( hWin, (POINT*)&view_rect.right );
|
|
||||||
|
|
||||||
dwXWindowOffset=view_rect.left;
|
|
||||||
dwYWindowOffset=view_rect.top;
|
|
||||||
dwCopyWidth=view_rect.right-view_rect.left;
|
|
||||||
dwCopyHeight=view_rect.bottom-view_rect.top;
|
|
||||||
|
|
||||||
pDDClipper->Release(); // dec ref cnt
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
//make sure there's enough space in the pixbuf, its size must match (especially xsize)
|
//make sure there's enough space in the pixbuf, its size must match (especially xsize)
|
||||||
// or scanlines will be too long
|
// or scanlines will be too long
|
||||||
|
|
||||||
if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) {
|
if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) {
|
||||||
pD3DSurf8->UnlockRect();
|
dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size too small to hold display surface!\n";
|
||||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size does not match display surface!\n";
|
|
||||||
assert(0);
|
assert(0);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = pD3DSurf8->LockRect(&LockedRect,(CONST RECT*)NULL,(D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE /* | D3DLOCK_NOSYSLOCK */));
|
||||||
|
if(FAILED(hr)) {
|
||||||
|
dxgsg_cat.error() << "ConvertDDSurftoPixBuf LockRect() failed! hr = " << D3DERRORSTRING(hr);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
// ones not listed not handled yet
|
// ones not listed not handled yet
|
||||||
assert((SurfDesc.Format==D3DFMT_A8R8G8B8)||(SurfDesc.Format==D3DFMT_X8R8G8B8)||(SurfDesc.Format==D3DFMT_R8G8B8)||
|
assert((SurfDesc.Format==D3DFMT_A8R8G8B8)||(SurfDesc.Format==D3DFMT_X8R8G8B8)||(SurfDesc.Format==D3DFMT_R8G8B8)||
|
||||||
(SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)||
|
(SurfDesc.Format==D3DFMT_R5G6B5)||(SurfDesc.Format==D3DFMT_X1R5G5B5)||(SurfDesc.Format==D3DFMT_A1R5G5B5)||
|
||||||
|
@ -74,7 +74,7 @@ private:
|
|||||||
static TypeHandle _type_handle;
|
static TypeHandle _type_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf);
|
extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -152,6 +152,8 @@ typedef enum {
|
|||||||
|
|
||||||
#define IS_16BPP_FORMAT(FMT) (((FMT)>=D3DFMT_R5G6B5)&&((FMT)<=D3DFMT_A1R5G5B5))
|
#define IS_16BPP_FORMAT(FMT) (((FMT)>=D3DFMT_R5G6B5)&&((FMT)<=D3DFMT_A1R5G5B5))
|
||||||
#define IS_STENCIL_FORMAT(FMT) (((FMT)==D3DFMT_D24S8) || ((FMT)==D3DFMT_D15S1) || ((FMT)==D3DFMT_D24X4S4))
|
#define IS_STENCIL_FORMAT(FMT) (((FMT)==D3DFMT_D24S8) || ((FMT)==D3DFMT_D15S1) || ((FMT)==D3DFMT_D24X4S4))
|
||||||
|
#define RECT_XSIZE(REC) (REC.right-REC.left)
|
||||||
|
#define RECT_YSIZE(REC) (REC.bottom-REC.top)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LPDIRECT3DDEVICE8 pD3DDevice;
|
LPDIRECT3DDEVICE8 pD3DDevice;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user