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)
|
||||
return;
|
||||
|
||||
DWORD renderWid = view_rect.right - view_rect.left;
|
||||
DWORD renderHt = view_rect.bottom - view_rect.top;
|
||||
DWORD renderWid = RECT_XSIZE(view_rect);
|
||||
DWORD renderHt = RECT_YSIZE(view_rect);
|
||||
|
||||
// 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.]
|
||||
@ -3927,6 +3927,7 @@ texture_to_pixel_buffer(TextureContext *tc, PixelBuffer *pb,
|
||||
void DXGraphicsStateGuardian::
|
||||
copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
||||
|
||||
RECT SrcCopyRect;
|
||||
nassertv(pb != NULL && dr != NULL);
|
||||
|
||||
int xo, yo, w, h;
|
||||
@ -3941,30 +3942,80 @@ copy_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr) {
|
||||
IDirect3DSurface8 *pD3DSurf;
|
||||
HRESULT hr;
|
||||
|
||||
RECT WindRect;
|
||||
GetWindowRect(scrn.hWnd,&WindRect);
|
||||
|
||||
// just handling front and backbuf for now, not textures yet
|
||||
if(_cur_read_pixel_buffer & RenderBuffer::T_back) {
|
||||
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)) {
|
||||
dxgsg_cat.error() << "GetBackBuffer failed, hr = " << D3DERRORSTRING(hr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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 {
|
||||
dxgsg_cat.error() << "copy_pixel_buffer: unhandled current_read_pixel_buffer type\n";
|
||||
}
|
||||
|
||||
if(FAILED(hr)) {
|
||||
dxgsg_cat.error() << "copy_pixel_buffer: " << ((_cur_read_pixel_buffer & RenderBuffer::T_back) ? "GetBackBuffer" : "GetFrontBuffer")
|
||||
<< " failed, hr = " << D3DERRORSTRING(hr);
|
||||
if((RECT_XSIZE(SrcCopyRect)>w) || (RECT_YSIZE(SrcCopyRect)>h)) {
|
||||
dxgsg_cat.error() << "copy_pixel_buffer: pixel buffer size does not match selected screen RenderBuffer size!\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(void) ConvertD3DSurftoPixBuf(pD3DSurf,pb);
|
||||
(void) ConvertD3DSurftoPixBuf(SrcCopyRect,pD3DSurf,pb);
|
||||
|
||||
ULONG refcnt;
|
||||
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.BackBufferHeight = viewrect.right-viewrect.left;
|
||||
scrn.PresParams.BackBufferWidth = RECT_XSIZE(viewrect);
|
||||
scrn.PresParams.BackBufferHeight = RECT_YSIZE(viewrect);
|
||||
HRESULT hr=scrn.pD3DDevice->Reset(&scrn.PresParams);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
@ -6133,9 +6184,10 @@ bool DXGraphicsStateGuardian::CheckCooperativeLevel(bool bDoReactivateWindow) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DXGraphicsStateGuardian::adjust_view_rect(int x, int 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.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;
|
||||
|
||||
// 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
|
||||
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;
|
||||
DWORD dwNumComponents=pixbuf->get_num_components();
|
||||
|
||||
@ -728,67 +729,33 @@ HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DWORD dwXWindowOffset,dwYWindowOffset;
|
||||
DWORD dwCopyWidth,dwCopyHeight;
|
||||
|
||||
D3DLOCKED_RECT LockedRect;
|
||||
D3DSURFACE_DESC SurfDesc;
|
||||
|
||||
hr = pD3DSurf8->GetDesc(&SurfDesc);
|
||||
|
||||
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;
|
||||
}
|
||||
dwXWindowOffset=SrcRect.left,dwYWindowOffset=SrcRect.top;
|
||||
dwCopyWidth=RECT_XSIZE(SrcRect);
|
||||
dwCopyHeight=RECT_YSIZE(SrcRect);
|
||||
|
||||
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)
|
||||
// or scanlines will be too long
|
||||
|
||||
if(!((dwCopyWidth==pixbuf->get_xsize()) && (dwCopyHeight<=(DWORD)pixbuf->get_ysize()))) {
|
||||
pD3DSurf8->UnlockRect();
|
||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size does not match display surface!\n";
|
||||
dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf size too small to hold display surface!\n";
|
||||
assert(0);
|
||||
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
|
||||
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)||
|
||||
|
@ -74,7 +74,7 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
extern HRESULT ConvertD3DSurftoPixBuf(IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf);
|
||||
extern HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -152,6 +152,8 @@ typedef enum {
|
||||
|
||||
#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 RECT_XSIZE(REC) (REC.right-REC.left)
|
||||
#define RECT_YSIZE(REC) (REC.bottom-REC.top)
|
||||
|
||||
typedef struct {
|
||||
LPDIRECT3DDEVICE8 pD3DDevice;
|
||||
|
Loading…
x
Reference in New Issue
Block a user