diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index f3acdda96f..3d4d9fd52a 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -143,31 +143,11 @@ void GraphicsOutput:: setup_copy_texture(const string &name) { MutexHolder holder(_lock); - _texture = new Texture(); + _texture = new Texture(true); _texture->set_name(name); _texture->set_wrapu(Texture::WM_clamp); _texture->set_wrapv(Texture::WM_clamp); - // We should match the texture format up with the framebuffer - // format. Easier said than done! - if (_gsg != (GraphicsStateGuardian *)NULL) { - int mode = _gsg->get_properties().get_frame_buffer_mode(); - PixelBuffer *pb = _texture->_pbuffer; - - if (mode & FrameBufferProperties::FM_alpha) { - pb->set_format(PixelBuffer::F_rgba8); - pb->set_num_components(4); - pb->set_component_width(1); - pb->set_image_type(PixelBuffer::T_unsigned_byte); - - } else { - pb->set_format(PixelBuffer::F_rgb8); - pb->set_num_components(3); - pb->set_component_width(1); - pb->set_image_type(PixelBuffer::T_unsigned_byte); - } - } - _copy_texture = true; } diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 6aab27cbbd..d1d3f38a8a 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -3151,8 +3151,8 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { dr->get_region_pixels(xo, yo, w, h); PixelBuffer *pb = tex->_pbuffer; - pb->set_xsize(w-xo); - pb->set_ysize(h-yo); + pb->set_xsize(w); + pb->set_ysize(h); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { @@ -3170,6 +3170,7 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { hr = _pD3DDevice->GetRenderTarget(&pCurRenderTarget); if(FAILED(hr)) { dxgsg8_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr); + SAFE_RELEASE(pTexSurfaceLev0); return; } @@ -3181,10 +3182,10 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { SrcRect.bottom = yo+h; // now copy from fb to tex - hr = _pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,NULL); + hr = _pD3DDevice->CopyRects(pCurRenderTarget,&SrcRect,1,pTexSurfaceLev0,0); if(FAILED(hr)) { - dxgsg8_cat.error() << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr); - return; + dxgsg8_cat.error() + << "CopyRects failed in copy_texture" << D3DERRORSTRING(hr); } SAFE_RELEASE(pCurRenderTarget); diff --git a/panda/src/dxgsg8/dxTextureContext8.cxx b/panda/src/dxgsg8/dxTextureContext8.cxx index cd86802790..803cb993fb 100644 --- a/panda/src/dxgsg8/dxTextureContext8.cxx +++ b/panda/src/dxgsg8/dxTextureContext8.cxx @@ -43,25 +43,6 @@ static const DWORD g_LowByteMask = 0x000000FF; #define GET_GREEN_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 8) & g_LowByteMask)) #define GET_ALPHA_BYTE(PIXEL_DWORD) ((BYTE)(((DWORD)PIXEL_DWORD) >> 24)) // unsigned >> shifts in 0's, so dont need to mask off upper bits -#ifdef DO_CUSTOM_CONVERSIONS -typedef enum { - None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_X555, - Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24, - Conv24to16_X555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, - ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_X555,ConvLum8to16_0565,ConvLum8to16_A8L8, - ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8,ConvAlpha8to16_A8L8 -} ConversionType; - -#ifndef NDEBUG -char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_X555", - "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24","Conv24to16_X555","Conv24to16_0565", - "ConvLum16to16_1555","ConvLum16to16_4444","ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", - "ConvLum8to16_X555","ConvLum8to16_0565","ConvLum8to16_A8L8", - "ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8","ConvAlpha8to16_A8L8" -}; -#endif -#endif - char *PandaFilterNameStrs[] = {"FT_nearest","FT_linear","FT_nearest_mipmap_nearest","FT_linear_mipmap_nearest", "FT_nearest_mipmap_linear", "FT_linear_mipmap_linear" }; @@ -208,509 +189,6 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { return 8; } -/* // This is superseded by D3DXLoadSurfaceFromMemory(), but keep this stuff around in case its needed - -#ifdef DO_CUSTOM_CONVERSIONS -HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { - HRESULT hr; - DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); - - if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) { - dxgsg_cat.error() << "ConvertPixBuftoDDSurf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n"; - exit(1); - } - - if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { - dxgsg_cat.error() << "CreateTexture failed: _surface->Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n"; - return hr; - } - - //pbuf contains raw ARGB in PixelBuffer byteorder - - DWORD lPitch = ddsd.lPitch; - BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; - DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight; - - switch(ConvNeeded) { - case Conv32to32: - case Conv32to32_NoAlpha: { - -#ifdef PANDA_BGRA_ORDER - if(ConvNeeded==Conv32to32) { - memcpy(pDDSurfBytes,(BYTE*) pbuf,dwOrigWidth*dwOrigHeight*sizeof(DWORD)); - } else { - DWORD *pSrcWord = (DWORD *) pbuf; - DWORD *pDstWord; - - // need to set all pixels alpha to 0xFF - for(DWORD y=0; y>16) & 0x00008000) | dwAlphaMaskOn; // just copy high bit - g = GET_GREEN_BYTE(dwPixel) >> 3; - b = GET_BLUE_BYTE(dwPixel) >> 3; - r = GET_RED_BYTE(dwPixel) >> 3; - - // truncates 8 bit values to 5 bit (or 1 for alpha) - - *pDstWord = (abit | (r << 10)| (g << 5) | b); - } - } - break; - } - - case Conv32to16_0565: { // could merge this w/above case, but whatever - DWORD *pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - // for some reason, bits are 'in-order' when converting to 16bit - - for(DWORD y=0; y> 2; - b = GET_BLUE_BYTE(dwPixel) >> 3; - r = GET_RED_BYTE(dwPixel) >> 3; - *pDstWord = ((r << 11)| (g << 5) | b); - } - } - break; - } - - case Conv32to16_4444: { - DWORD *pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB - assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0f00); // assumes ARGB - - for(DWORD y=0; y> 4; - g = GET_GREEN_BYTE(dwPixel) >> 4; - b = GET_BLUE_BYTE(dwPixel) >> 4; - r = GET_RED_BYTE(dwPixel) >> 4; - - *pDstWord = (a << 12) | (r << 8)| (g << 4) | b; - } - } - break; - } - - case Conv32to24: { - - DWORD *pSrcWord = (DWORD *) pbuf; - BYTE *pDstWord; - - for(DWORD y=0; y> 3; - r = *(pSrcWord+2) >> 3; - #else - r = *pSrcWord >> 3; - b = *(pSrcWord+2) >> 3; - #endif - g = *(pSrcWord+1) >> 3; - - *pDstWord = 0x8000 | (r << 10)| (g << 5) | b; - } - } - break; - } - - case Conv24to16_0565: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - - for(DWORD y=0; y> 3; - g = *(pSrcWord+1) >> 2; - r = *(pSrcWord+2) >> 3; - #else - r = *pSrcWord >> 3; - g = *(pSrcWord+1) >> 2; - b = *(pSrcWord+2) >> 3; - #endif - // code truncates 8 bit values to 5 bit - *pDstWord = (r << 11)| (g << 5) | b; - } - } - break; - } - - case Conv24to32: { - BYTE *pSrcWord = (BYTE *) pbuf; - DWORD *pDstWord; - - for(DWORD y=0; y> 8; - lum = dwPixel & 0xFF; - *pDstWord = (a<<24) | lum | (lum << 8) | (lum << 16); - } - } - break; - } - - case ConvLum16to16_4444: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB - - for(DWORD y=0; y>8) >> 4; - lum = (BYTE)(dwPixel & 0x000000ff) >> 4; - - *pDstWord = (a << 12) | lum | (lum << 4)| (lum << 8); - } - } - break; - } - - case ConvLum16to16_1555: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000); // assumes ARGB - - for(DWORD y=0; y> 3; - - *pDstWord = (dwPixel & 0x8000) | lum | (lum << 5) | (lum << 10); - } - } - break; - } - - case ConvLum16to16: { - // All bytes are in same order? - CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2); - break; - } - - case ConvLum8to16_0565: - case ConvLum8to16_X555: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; - DWORD FarShift,OrVal,MiddleRoundShift; - - if(ConvNeeded==ConvLum8to16_X555) { - FarShift=10; OrVal=0x8000; // turn on alpha bit, just in case - MiddleRoundShift = 3; - assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); - } else { - FarShift=11; OrVal=0x0; - MiddleRoundShift = 2; - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - } - - for(DWORD y=0; y> 3; - GrnVal = (BYTE) dwPixel >> MiddleRoundShift; - - // code truncates 8 bit values to 5 bit (set alpha=1 for opaque) - - *pDstWord = ((r << FarShift)| (GrnVal << 5) | r) | OrVal; - } - } - break; - } - - case ConvLum8to8: { - CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight); - break; - } - - case ConvLum8to32: { - - // this is kind of a waste of space, but we trade it for lum resolution - BYTE *pSrcWord = (BYTE *) pbuf; - DWORD *pDstWord; - - for(DWORD y=0; y>4); - *pDstWord = (a << 12) | 0x0FFF; // OR alpha with full white - } - } - break; - } - - default: - dxgsg_cat.error() << "CreateTexture failed! unhandled texture conversion type: "<< ConvNeeded <<" \n"; - pDDSurf->Unlock(NULL); - return E_INVALIDARG; - } - - pDDSurf->Unlock(NULL); - - return S_OK; -} -#endif -*/ - // still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelBuffer *pixbuf) { // copies SrcRect in pD3DSurf to upper left of pixbuf @@ -769,8 +247,9 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface8 *pD3DSurf8,PixelB // writes out last line in DDSurf first in PixelBuf, so Y line order precedes inversely if(dxgsg8_cat.is_debug()) { - dxgsg8_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " - << dwNumComponents << "-channel panda PixelBuffer\n"; + dxgsg8_cat.debug() + << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " + << dwNumComponents << "-channel panda PixelBuffer\n"; } DWORD *pDstWord = (DWORD *) pbuf; @@ -1025,7 +504,6 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { _PixBufD3DFmt=D3DFMT_UNKNOWN; -#ifndef DO_CUSTOM_CONVERSIONS // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy switch(cNumColorChannels) { @@ -1049,7 +527,6 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { // make sure we handled all the possible cases assert(_PixBufD3DFmt!=D3DFMT_UNKNOWN); -#endif DWORD TargetWidth=dwOrigWidth; DWORD TargetHeight=dwOrigHeight; @@ -1119,13 +596,7 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { // I could possibly replace some of this logic with D3DXCheckTextureRequirements(), but // it wouldnt handle all my specialized low-memory cases perfectly -#ifdef DO_CUSTOM_CONVERSIONS - ConversionType ConvNeeded; - -#define CONVTYPE_STMT ConvNeeded=CONV -#else #define CONVTYPE_STMT -#endif #define CHECK_FOR_FMT(FMT,CONV) \ if(scrn.SupportedTexFmtsMask & FMT##_FLAG) { \ @@ -1309,6 +780,37 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { /////////////////////////////////////////////////////////// found_matching_format: + // We found a suitable format that matches the pbuffer's format. + + if (_texture->get_match_framebuffer_format()) { + // Instead of creating a texture with the found format, we will + // need to make one that exactly matches the framebuffer's + // format. Look up what that format is. + IDirect3DSurface8 *pCurRenderTarget; + hr = scrn.pD3DDevice->GetRenderTarget(&pCurRenderTarget); + if(FAILED(hr)) { + dxgsg8_cat.error() << "GetRenderTgt failed in CreateTexture: " << D3DERRORSTRING(hr); + } else { + D3DSURFACE_DESC SurfDesc; + hr = pCurRenderTarget->GetDesc(&SurfDesc); + if (FAILED(hr)) { + dxgsg8_cat.error() + << "GetDesc failed in CreateTexture: " << D3DERRORSTRING(hr); + } else { + if (TargetPixFmt != SurfDesc.Format) { + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() + << "Chose format " << D3DFormatStr(SurfDesc.Format) + << " instead of " << D3DFormatStr(TargetPixFmt) + << " for texture to match framebuffer.\n"; + } + TargetPixFmt = SurfDesc.Format; + } + } + SAFE_RELEASE(pCurRenderTarget); + } + } + // validate magfilter setting // degrade filtering if no HW support @@ -1417,17 +919,9 @@ IDirect3DTexture8 *DXTextureContext8::CreateTexture(DXScreenData &scrn) { goto error_exit; } -#ifdef DO_CUSTOM_CONVERSIONS - _PixBufConversionType=ConvNeeded; -#endif - -#ifdef _DEBUG -#ifdef DO_CUSTOM_CONVERSIONS - dxgsg8_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting " << ConvNameStrs[ConvNeeded] << " \n"; -#else - dxgsg8_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting panda equivalent of " << D3DFormatStr(_PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl; -#endif -#endif + if (dxgsg8_cat.is_debug()) { + dxgsg8_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting panda equivalent of " << D3DFormatStr(_PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl; + } hr = FillDDSurfTexturePixels(); if(FAILED(hr)) { diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index edfd7284d5..8423290d92 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3148,8 +3148,8 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { dr->get_region_pixels(xo, yo, w, h); PixelBuffer *pb = tex->_pbuffer; - pb->set_xsize(w-xo); - pb->set_ysize(h-yo); + pb->set_xsize(w); + pb->set_ysize(h); TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); if (tc == (TextureContext *)NULL) { @@ -3167,6 +3167,7 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { hr = _pD3DDevice->GetRenderTarget(0, &pCurRenderTarget); if(FAILED(hr)) { dxgsg9_cat.error() << "GetRenderTgt failed in copy_texture" << D3DERRORSTRING(hr); + SAFE_RELEASE(pTexSurfaceLev0); return; } @@ -3178,15 +3179,15 @@ copy_texture(Texture *tex, const DisplayRegion *dr) { SrcRect.bottom = yo+h; // now copy from fb to tex - //hr = _pD3DDevice->UpdateSurface(pCurRenderTarget,&SrcRect,pTexSurfaceLev0,NULL); + //hr = _pD3DDevice->UpdateSurface(pCurRenderTarget,&SrcRect,pTexSurfaceLev0,0); // the following call does what we want. Interesting though, why Dx9 took out the // functionality of copying from VRAM to VRAM and put it in D3DX library. Perhaps // to promote D3DX!? hr = D3DXLoadSurfaceFromSurface(pTexSurfaceLev0, NULL, NULL, pCurRenderTarget, NULL, &SrcRect, D3DX_FILTER_NONE, 0); if(FAILED(hr)) { - dxgsg9_cat.error() << "UpdateSurface failed in copy_texture" << D3DERRORSTRING(hr); - return; + dxgsg9_cat.error() + << "UpdateSurface failed in copy_texture" << D3DERRORSTRING(hr); } SAFE_RELEASE(pCurRenderTarget); diff --git a/panda/src/dxgsg9/dxTextureContext9.cxx b/panda/src/dxgsg9/dxTextureContext9.cxx index 8edef8eae9..30c9a86607 100755 --- a/panda/src/dxgsg9/dxTextureContext9.cxx +++ b/panda/src/dxgsg9/dxTextureContext9.cxx @@ -43,25 +43,6 @@ static const DWORD g_LowByteMask = 0x000000FF; #define GET_GREEN_BYTE(PIXEL_DWORD) ((BYTE)((PIXEL_DWORD >> 8) & g_LowByteMask)) #define GET_ALPHA_BYTE(PIXEL_DWORD) ((BYTE)(((DWORD)PIXEL_DWORD) >> 24)) // unsigned >> shifts in 0's, so dont need to mask off upper bits -#ifdef DO_CUSTOM_CONVERSIONS -typedef enum { - None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_X555, - Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24, - Conv24to16_X555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, - ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_X555,ConvLum8to16_0565,ConvLum8to16_A8L8, - ConvAlpha8to16_4444,ConvAlpha8to32,ConvAlpha8to8,ConvAlpha8to16_A8L8 -} ConversionType; - -#ifndef NDEBUG -char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_X555", - "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24","Conv24to16_X555","Conv24to16_0565", - "ConvLum16to16_1555","ConvLum16to16_4444","ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", - "ConvLum8to16_X555","ConvLum8to16_0565","ConvLum8to16_A8L8", - "ConvAlpha8to16_4444","ConvAlpha8to32","ConvAlpha8to8","ConvAlpha8to16_A8L8" -}; -#endif -#endif - char *PandaFilterNameStrs[] = {"FT_nearest","FT_linear","FT_nearest_mipmap_nearest","FT_linear_mipmap_nearest", "FT_nearest_mipmap_linear", "FT_linear_mipmap_linear" }; @@ -208,509 +189,6 @@ get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { return 8; } -/* // This is superseded by D3DXLoadSurfaceFromMemory(), but keep this stuff around in case its needed - -#ifdef DO_CUSTOM_CONVERSIONS -HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { - HRESULT hr; - DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); - - if(IsBadWritePtr(pDDSurf,sizeof(DWORD))) { - dxgsg_cat.error() << "ConvertPixBuftoDDSurf failed: bad pDDSurf ptr value (" << ((void*)pDDSurf) << ")\n"; - exit(1); - } - - if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { - dxgsg_cat.error() << "CreateTexture failed: _surface->Lock() failed on texture! hr = " << ConvD3DErrorToString(hr) << "\n"; - return hr; - } - - //pbuf contains raw ARGB in PixelBuffer byteorder - - DWORD lPitch = ddsd.lPitch; - BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; - DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight; - - switch(ConvNeeded) { - case Conv32to32: - case Conv32to32_NoAlpha: { - -#ifdef PANDA_BGRA_ORDER - if(ConvNeeded==Conv32to32) { - memcpy(pDDSurfBytes,(BYTE*) pbuf,dwOrigWidth*dwOrigHeight*sizeof(DWORD)); - } else { - DWORD *pSrcWord = (DWORD *) pbuf; - DWORD *pDstWord; - - // need to set all pixels alpha to 0xFF - for(DWORD y=0; y>16) & 0x00008000) | dwAlphaMaskOn; // just copy high bit - g = GET_GREEN_BYTE(dwPixel) >> 3; - b = GET_BLUE_BYTE(dwPixel) >> 3; - r = GET_RED_BYTE(dwPixel) >> 3; - - // truncates 8 bit values to 5 bit (or 1 for alpha) - - *pDstWord = (abit | (r << 10)| (g << 5) | b); - } - } - break; - } - - case Conv32to16_0565: { // could merge this w/above case, but whatever - DWORD *pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - // for some reason, bits are 'in-order' when converting to 16bit - - for(DWORD y=0; y> 2; - b = GET_BLUE_BYTE(dwPixel) >> 3; - r = GET_RED_BYTE(dwPixel) >> 3; - *pDstWord = ((r << 11)| (g << 5) | b); - } - } - break; - } - - case Conv32to16_4444: { - DWORD *pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB - assert(ddsd.ddpfPixelFormat.dwRBitMask==0x0f00); // assumes ARGB - - for(DWORD y=0; y> 4; - g = GET_GREEN_BYTE(dwPixel) >> 4; - b = GET_BLUE_BYTE(dwPixel) >> 4; - r = GET_RED_BYTE(dwPixel) >> 4; - - *pDstWord = (a << 12) | (r << 8)| (g << 4) | b; - } - } - break; - } - - case Conv32to24: { - - DWORD *pSrcWord = (DWORD *) pbuf; - BYTE *pDstWord; - - for(DWORD y=0; y> 3; - r = *(pSrcWord+2) >> 3; - #else - r = *pSrcWord >> 3; - b = *(pSrcWord+2) >> 3; - #endif - g = *(pSrcWord+1) >> 3; - - *pDstWord = 0x8000 | (r << 10)| (g << 5) | b; - } - } - break; - } - - case Conv24to16_0565: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - - for(DWORD y=0; y> 3; - g = *(pSrcWord+1) >> 2; - r = *(pSrcWord+2) >> 3; - #else - r = *pSrcWord >> 3; - g = *(pSrcWord+1) >> 2; - b = *(pSrcWord+2) >> 3; - #endif - // code truncates 8 bit values to 5 bit - *pDstWord = (r << 11)| (g << 5) | b; - } - } - break; - } - - case Conv24to32: { - BYTE *pSrcWord = (BYTE *) pbuf; - DWORD *pDstWord; - - for(DWORD y=0; y> 8; - lum = dwPixel & 0xFF; - *pDstWord = (a<<24) | lum | (lum << 8) | (lum << 16); - } - } - break; - } - - case ConvLum16to16_4444: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB - - for(DWORD y=0; y>8) >> 4; - lum = (BYTE)(dwPixel & 0x000000ff) >> 4; - - *pDstWord = (a << 12) | lum | (lum << 4)| (lum << 8); - } - } - break; - } - - case ConvLum16to16_1555: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000); // assumes ARGB - - for(DWORD y=0; y> 3; - - *pDstWord = (dwPixel & 0x8000) | lum | (lum << 5) | (lum << 10); - } - } - break; - } - - case ConvLum16to16: { - // All bytes are in same order? - CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2); - break; - } - - case ConvLum8to16_0565: - case ConvLum8to16_X555: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; - DWORD FarShift,OrVal,MiddleRoundShift; - - if(ConvNeeded==ConvLum8to16_X555) { - FarShift=10; OrVal=0x8000; // turn on alpha bit, just in case - MiddleRoundShift = 3; - assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); - } else { - FarShift=11; OrVal=0x0; - MiddleRoundShift = 2; - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - } - - for(DWORD y=0; y> 3; - GrnVal = (BYTE) dwPixel >> MiddleRoundShift; - - // code truncates 8 bit values to 5 bit (set alpha=1 for opaque) - - *pDstWord = ((r << FarShift)| (GrnVal << 5) | r) | OrVal; - } - } - break; - } - - case ConvLum8to8: { - CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight); - break; - } - - case ConvLum8to32: { - - // this is kind of a waste of space, but we trade it for lum resolution - BYTE *pSrcWord = (BYTE *) pbuf; - DWORD *pDstWord; - - for(DWORD y=0; y>4); - *pDstWord = (a << 12) | 0x0FFF; // OR alpha with full white - } - } - break; - } - - default: - dxgsg_cat.error() << "CreateTexture failed! unhandled texture conversion type: "<< ConvNeeded <<" \n"; - pDDSurf->Unlock(NULL); - return E_INVALIDARG; - } - - pDDSurf->Unlock(NULL); - - return S_OK; -} -#endif -*/ - // still need custom conversion since d3d/d3dx has no way to convert arbitrary fmt to ARGB in-memory user buffer HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelBuffer *pixbuf) { // copies SrcRect in pD3DSurf to upper left of pixbuf @@ -769,8 +247,9 @@ HRESULT ConvertD3DSurftoPixBuf(RECT &SrcRect,IDirect3DSurface9 *pD3DSurf9,PixelB // writes out last line in DDSurf first in PixelBuf, so Y line order precedes inversely if(dxgsg9_cat.is_debug()) { - dxgsg9_cat.debug() << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " - << dwNumComponents << "-channel panda PixelBuffer\n"; + dxgsg9_cat.debug() + << "ConvertD3DSurftoPixBuf converting " << D3DFormatStr(SurfDesc.Format) << "bpp DDSurf to " + << dwNumComponents << "-channel panda PixelBuffer\n"; } DWORD *pDstWord = (DWORD *) pbuf; @@ -1025,7 +504,6 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { _PixBufD3DFmt=D3DFMT_UNKNOWN; -#ifndef DO_CUSTOM_CONVERSIONS // figure out what 'D3DFMT' the PixelBuffer is in, so D3DXLoadSurfFromMem knows how to perform copy switch(cNumColorChannels) { @@ -1049,7 +527,6 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { // make sure we handled all the possible cases assert(_PixBufD3DFmt!=D3DFMT_UNKNOWN); -#endif DWORD TargetWidth=dwOrigWidth; DWORD TargetHeight=dwOrigHeight; @@ -1119,13 +596,7 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { // I could possibly replace some of this logic with D3DXCheckTextureRequirements(), but // it wouldnt handle all my specialized low-memory cases perfectly -#ifdef DO_CUSTOM_CONVERSIONS - ConversionType ConvNeeded; - -#define CONVTYPE_STMT ConvNeeded=CONV -#else #define CONVTYPE_STMT -#endif #define CHECK_FOR_FMT(FMT,CONV) \ if(scrn.SupportedTexFmtsMask & FMT##_FLAG) { \ @@ -1309,6 +780,37 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { /////////////////////////////////////////////////////////// found_matching_format: + // We found a suitable format that matches the pbuffer's format. + + if (_texture->get_match_framebuffer_format()) { + // Instead of creating a texture with the found format, we will + // need to make one that exactly matches the framebuffer's + // format. Look up what that format is. + IDirect3DSurface9 *pCurRenderTarget; + hr = scrn.pD3DDevice->GetRenderTarget(0, &pCurRenderTarget); + if(FAILED(hr)) { + dxgsg9_cat.error() << "GetRenderTgt failed in CreateTexture: " << D3DERRORSTRING(hr); + } else { + D3DSURFACE_DESC SurfDesc; + hr = pCurRenderTarget->GetDesc(&SurfDesc); + if (FAILED(hr)) { + dxgsg9_cat.error() + << "GetDesc failed in CreateTexture: " << D3DERRORSTRING(hr); + } else { + if (TargetPixFmt != SurfDesc.Format) { + if (dxgsg9_cat.is_debug()) { + dxgsg9_cat.debug() + << "Chose format " << D3DFormatStr(SurfDesc.Format) + << " instead of " << D3DFormatStr(TargetPixFmt) + << " for texture to match framebuffer.\n"; + } + TargetPixFmt = SurfDesc.Format; + } + } + SAFE_RELEASE(pCurRenderTarget); + } + } + // validate magfilter setting // degrade filtering if no HW support @@ -1417,17 +919,9 @@ IDirect3DTexture9 *DXTextureContext9::CreateTexture(DXScreenData &scrn) { goto error_exit; } -#ifdef DO_CUSTOM_CONVERSIONS - _PixBufConversionType=ConvNeeded; -#endif - -#ifdef _DEBUG -#ifdef DO_CUSTOM_CONVERSIONS - dxgsg9_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting " << ConvNameStrs[ConvNeeded] << " \n"; -#else - dxgsg9_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting panda equivalent of " << D3DFormatStr(_PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl; -#endif -#endif + if (dxgsg9_cat.is_debug()) { + dxgsg9_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converting panda equivalent of " << D3DFormatStr(_PixBufD3DFmt) << " => " << D3DFormatStr(TargetPixFmt) << endl; + } hr = FillDDSurfTexturePixels(); if(FAILED(hr)) { diff --git a/panda/src/gobj/pixelBuffer.cxx b/panda/src/gobj/pixelBuffer.cxx index 2ed2262b7d..93c163ba23 100644 --- a/panda/src/gobj/pixelBuffer.cxx +++ b/panda/src/gobj/pixelBuffer.cxx @@ -30,8 +30,7 @@ TypeHandle PixelBuffer::_type_handle; // Description: //////////////////////////////////////////////////////////////////// PixelBuffer:: -PixelBuffer(void) : ImageBuffer() -{ +PixelBuffer() { _xsize = 0; _ysize = 0; _format = F_rgb; @@ -49,38 +48,19 @@ PixelBuffer(void) : ImageBuffer() // Description: //////////////////////////////////////////////////////////////////// PixelBuffer:: -PixelBuffer(int xsize, int ysize, int components, int component_width, - Type type, Format format) : - ImageBuffer() -{ +PixelBuffer(int xsize, int ysize, int components, int component_width, + Type type, Format format, bool allocate_ram) { _xsize = xsize; _ysize = ysize; _num_components = components; _component_width = component_width; _type = type; _format = format; - _image = PTA_uchar::empty_array((unsigned int)(_xsize * _ysize * _num_components * _component_width)); - _loaded = true; -} -//////////////////////////////////////////////////////////////////// -// Function: PixelBuffer::Constructor -// Access: Public -// Description: create a pixel buffer with specified format but do not alloc CPU RAM for it -//////////////////////////////////////////////////////////////////// -PixelBuffer:: -PixelBuffer(int xsize, int ysize, int components, int component_width, Type type, Format format, - bool bAllocateRAM) : ImageBuffer() -{ - _xsize = xsize; - _ysize = ysize; - _num_components = components; - _component_width = component_width; - _type = type; - _format = format; - if(bAllocateRAM) - _image = PTA_uchar::empty_array((unsigned int)(_xsize * _ysize * _num_components * _component_width)); - else _image = PTA_uchar(); + if (allocate_ram) { + int num_pixels = _xsize * _ysize * _num_components * _component_width; + _image = PTA_uchar::empty_array((size_t)num_pixels); + } _loaded = false; } @@ -399,7 +379,12 @@ copy(const PixelBuffer *pb) { _num_components = pb->_num_components; _component_width = pb->_component_width; _format = pb->_format; - _image = PTA_uchar::empty_array(0); - if (!pb->_image.empty()) + + if (!pb->_image.is_null()) { + _image = PTA_uchar::empty_array(0); _image.v() = pb->_image.v(); + } else { + _image = PTA_uchar(); + } + } diff --git a/panda/src/gobj/pixelBuffer.h b/panda/src/gobj/pixelBuffer.h index 0804ded40f..8b6feb4830 100644 --- a/panda/src/gobj/pixelBuffer.h +++ b/panda/src/gobj/pixelBuffer.h @@ -80,11 +80,9 @@ public: }; PixelBuffer(void); - PixelBuffer(int xsize, int ysize, int components, - int component_width, Type type, Format format); PixelBuffer(int xsize, int ysize, int components, int component_width, Type type, Format format, - bool bAllocateRAM); + bool allocate_ram = true); PixelBuffer(const PixelBuffer ©); void operator = (const PixelBuffer ©); diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index 241ae1e1c7..5046fbe604 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -104,6 +104,21 @@ uses_mipmaps() const { return is_mipmap(get_minfilter()); } +//////////////////////////////////////////////////////////////////// +// Function: Texture::get_match_framebuffer_format +// Access: Published +// Description: Returns true if the Texture was created with a +// special flag that indicates to the GSG that the +// Texture's format should be chosen to exactly match +// the framebuffer's format, presumably because the +// application intends to copy image data from the +// framebuffer into the Texture (or vice-versa). +//////////////////////////////////////////////////////////////////// +INLINE bool Texture:: +get_match_framebuffer_format() const { + return _match_framebuffer_format; +} + //////////////////////////////////////////////////////////////////// // Function: Texture::has_ram_image // Access: Public diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 86ad0d4db0..67c5b90e2d 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -132,7 +132,7 @@ consider_downgrade(PNMImage &pnmimage, int num_channels, // Description: //////////////////////////////////////////////////////////////////// Texture:: -Texture() : ImageBuffer() { +Texture(bool match_framebuffer_format) { _magfilter = FT_linear; _minfilter = FT_linear; _wrapu = WM_repeat; @@ -140,12 +140,24 @@ Texture() : ImageBuffer() { _anisotropic_degree = 1; _keep_ram_image = false; _pbuffer = new PixelBuffer; - // _has_requested_size = false; _all_dirty_flags = 0; _border_color.set(0.0f, 0.0f, 0.0f, 1.0f); _border_width = 0; -} + _match_framebuffer_format = match_framebuffer_format; + if (_match_framebuffer_format) { + // If this flag is true, it indicates to the GSG that the texture + // will be created in a format consistent with the framebuffer + // (presumably to allow copying from the framebuffer), regardless + // of the pbuffer format. + + // Make up a default format for the pbuffer. + _pbuffer->set_format(PixelBuffer::F_rgba8); + _pbuffer->set_num_components(4); + _pbuffer->set_component_width(1); + _pbuffer->set_image_type(PixelBuffer::T_unsigned_byte); + } +} //////////////////////////////////////////////////////////////////// // Function: Texture::Constructor @@ -154,19 +166,20 @@ Texture() : ImageBuffer() { //////////////////////////////////////////////////////////////////// Texture:: Texture(int xsize, int ysize, int components, int component_width, - PixelBuffer::Type type, - PixelBuffer::Format format, bool bAllocateRAM) : ImageBuffer() { + PixelBuffer::Type type, PixelBuffer::Format format, + bool allocate_ram) { _magfilter = FT_linear; _minfilter = FT_linear; _wrapu = WM_repeat; _wrapv = WM_repeat; _anisotropic_degree = 1; - _keep_ram_image = bAllocateRAM; - _pbuffer = new PixelBuffer(xsize,ysize,components,component_width,type,format,bAllocateRAM); - // _has_requested_size = false; + _keep_ram_image = allocate_ram; + _pbuffer = new PixelBuffer(xsize, ysize, components, component_width, + type, format, allocate_ram); _all_dirty_flags = 0; _border_color.set(0.0f, 0.0f, 0.0f, 1.0f); _border_width = 0; + _match_framebuffer_format = false; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index e968e3b1f4..e52ad16d3f 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -75,9 +75,10 @@ PUBLISHED: }; PUBLISHED: - Texture(); - Texture(int xsize, int ysize, int components, int component_width, PixelBuffer::Type type, PixelBuffer::Format format, - bool bAllocateRAM); + Texture(bool match_framebuffer_format = false); + Texture(int xsize, int ysize, int components, int component_width, + PixelBuffer::Type type, PixelBuffer::Format format, + bool allocate_ram); ~Texture(); bool read(const Filename &fullpath, int primary_file_num_channels = 0); @@ -105,6 +106,8 @@ PUBLISHED: INLINE int get_border_width() const; INLINE bool uses_mipmaps() const; + INLINE bool get_match_framebuffer_format() const; + void prepare(PreparedGraphicsObjects *prepared_objects); public: @@ -148,6 +151,7 @@ private: bool _keep_ram_image; Colorf _border_color; int _border_width; + bool _match_framebuffer_format; // A Texture keeps a list (actually, a map) of all the // PreparedGraphicsObjects tables that it has been prepared into. @@ -167,17 +171,6 @@ public: // pixel buffer when needed. Know what you are doing! PT(PixelBuffer) _pbuffer; -/* - // If you request a region from the framebuffer that is not a power of 2, - // we need to grab a larger region that is a power of 2 that contains the - // requested region and set the pixel buffer size accordingly. We store - // the size you requested in the members below. - bool _has_requested_size; - int _requested_w; - int _requested_h; -*/ - - // Datagram stuff public: static void register_with_read_factory(void);