diff --git a/panda/src/dxgsg/dxTextureContext.cxx b/panda/src/dxgsg/dxTextureContext.cxx index df41e76297..5381992327 100644 --- a/panda/src/dxgsg/dxTextureContext.cxx +++ b/panda/src/dxgsg/dxTextureContext.cxx @@ -21,19 +21,20 @@ //#define FORCE_16bpp_1555 -typedef enum {None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_0555, - Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24, - Conv24to16_0555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, - ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_0555,ConvLum8to16_0565 +typedef enum { + None,Conv32to32,Conv32to32_NoAlpha,Conv32to24,Conv32to16_0555, + Conv32to16_1555,Conv32to16_0565,Conv32to16_4444,Conv24to32,Conv24to24, + Conv24to16_0555,Conv24to16_0565,ConvLum16to16_1555,ConvLum16to16_4444, + ConvLum16to32,ConvLum16to16,ConvLum8to8,ConvLum8to24,ConvLum8to32,ConvLum8to16_0555,ConvLum8to16_0565 } ConversionType; #ifdef _DEBUG char *ConvNameStrs[] = {"None","Conv32to32","Conv32to32_NoAlpha","Conv32to24","Conv32to16_0555", - "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24", - "Conv24to16_0555","Conv24to16_0565","ConvLum16to16_1555","ConvLum16to16_4444", - "ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", - "ConvLum8to16_0555","ConvLum8to16_0565" - }; + "Conv32to16_1555","Conv32to16_0565","Conv32to16_4444","Conv24to32","Conv24to24", + "Conv24to16_0555","Conv24to16_0565","ConvLum16to16_1555","ConvLum16to16_4444", + "ConvLum16to32","ConvLum16to16","ConvLum8to8","ConvLum8to24","ConvLum8to32", + "ConvLum8to16_0555","ConvLum8to16_0565" +}; #endif TypeHandle DXTextureContext::_type_handle; @@ -42,46 +43,46 @@ TypeHandle DXTextureContext::_type_handle; #ifdef _DEBUG static void DebugPrintPixFmt(DDPIXELFORMAT* pddpf) { - static int iddpfnum=0; - ostream *dbgout = &dxgsg_cat.debug(); - - *dbgout << "DDPF[" << iddpfnum << "]: RGBBitCount:" << pddpf->dwRGBBitCount - << " Flags:" << (void *)pddpf->dwFlags ; + static int iddpfnum=0; + ostream *dbgout = &dxgsg_cat.debug(); - if(pddpf->dwFlags & DDPF_RGB) { - *dbgout << " RGBmask:" << (void *) (pddpf->dwRBitMask | pddpf->dwGBitMask | pddpf->dwBBitMask); - *dbgout << " Rmask:" << (void *) (pddpf->dwRBitMask); - } + *dbgout << "DDPF[" << iddpfnum << "]: RGBBitCount:" << pddpf->dwRGBBitCount + << " Flags:" << (void *)pddpf->dwFlags ; - if(pddpf->dwFlags & DDPF_ALPHAPIXELS) { - *dbgout << " Amask:" << (void *) pddpf->dwRGBAlphaBitMask; - } + if(pddpf->dwFlags & DDPF_RGB) { + *dbgout << " RGBmask:" << (void *) (pddpf->dwRBitMask | pddpf->dwGBitMask | pddpf->dwBBitMask); + *dbgout << " Rmask:" << (void *) (pddpf->dwRBitMask); + } - if(pddpf->dwFlags & DDPF_LUMINANCE) { - *dbgout << " Lummask:" << (void *) pddpf->dwLuminanceBitMask; - } + if(pddpf->dwFlags & DDPF_ALPHAPIXELS) { + *dbgout << " Amask:" << (void *) pddpf->dwRGBAlphaBitMask; + } - *dbgout << endl; + if(pddpf->dwFlags & DDPF_LUMINANCE) { + *dbgout << " Lummask:" << (void *) pddpf->dwLuminanceBitMask; + } - iddpfnum++; + *dbgout << endl; + + iddpfnum++; } void PrintLastError(char *msgbuf) { - DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; - if(msgbuf==NULL) { - LPVOID lpMsgBuf; - dwFlags|=FORMAT_MESSAGE_ALLOCATE_BUFFER; - FormatMessage( dwFlags, - NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf,0,NULL ); - MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); - LocalFree(lpMsgBuf); - } else { - FormatMessage( dwFlags, - NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) msgbuf,500,NULL ); - } + if(msgbuf==NULL) { + LPVOID lpMsgBuf; + dwFlags|=FORMAT_MESSAGE_ALLOCATE_BUFFER; + FormatMessage( dwFlags, + NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf,0,NULL ); + MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION ); + LocalFree(lpMsgBuf); + } else { + FormatMessage( dwFlags, + NULL,GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) msgbuf,500,NULL ); + } } #endif @@ -112,10 +113,10 @@ enum Format { }; enum Type { - T_unsigned_byte, // 1 byte per channel - T_unsigned_short, // 2 byte per channel - T_unsigned_byte_332, // RGB in 1 byte - T_float, // 1 channel stored as float + T_unsigned_byte, // 1 byte per channel + T_unsigned_short, // 2 byte per channel + T_unsigned_byte_332, // RGB in 1 byte + T_float, // 1 channel stored as float }; */ @@ -127,487 +128,789 @@ enum Format { // Note: PixelBuffer's format indicates REQUESTED final format, // not the stored format, which is indicated by pixelbuffer type //////////////////////////////////////////////////////////////////// + unsigned int DXTextureContext:: get_bits_per_pixel(PixelBuffer::Format format, int *alphbits) { - *alphbits = 0; // assume no alpha bits - switch (format) { - case PixelBuffer::F_alpha: - *alphbits = 8; - return 8; - case PixelBuffer::F_color_index: - case PixelBuffer::F_red: - case PixelBuffer::F_green: - case PixelBuffer::F_blue: - case PixelBuffer::F_rgb332: - case PixelBuffer::F_luminance_alphamask: - *alphbits = 1; - return 16; - case PixelBuffer::F_luminance_alpha: - *alphbits = 8; - return 16; - case PixelBuffer::F_luminance: - return 8; - case PixelBuffer::F_rgba4: - *alphbits = 4; - return 16; - case PixelBuffer::F_rgba5: - *alphbits = 1; - return 16; - case PixelBuffer::F_depth_component: - case PixelBuffer::F_rgb5: - return 16; - case PixelBuffer::F_rgb8: - case PixelBuffer::F_rgb: - return 24; - case PixelBuffer::F_rgba8: - case PixelBuffer::F_rgba: - *alphbits = 8; - return 32; - case PixelBuffer::F_rgbm: - *alphbits = 1; - return 32; - case PixelBuffer::F_rgb12: - return 36; - case PixelBuffer::F_rgba12: - *alphbits = 12; - return 48; - } -return 8; + *alphbits = 0; // assume no alpha bits + switch(format) { + case PixelBuffer::F_alpha: + *alphbits = 8; + return 8; + case PixelBuffer::F_color_index: + case PixelBuffer::F_red: + case PixelBuffer::F_green: + case PixelBuffer::F_blue: + case PixelBuffer::F_rgb332: + case PixelBuffer::F_luminance_alphamask: + *alphbits = 1; + return 16; + case PixelBuffer::F_luminance_alpha: + *alphbits = 8; + return 16; + case PixelBuffer::F_luminance: + return 8; + case PixelBuffer::F_rgba4: + *alphbits = 4; + return 16; + case PixelBuffer::F_rgba5: + *alphbits = 1; + return 16; + case PixelBuffer::F_depth_component: + case PixelBuffer::F_rgb5: + return 16; + case PixelBuffer::F_rgb8: + case PixelBuffer::F_rgb: + return 24; + case PixelBuffer::F_rgba8: + case PixelBuffer::F_rgba: + *alphbits = 8; + return 32; + case PixelBuffer::F_rgbm: + *alphbits = 1; + return 32; + case PixelBuffer::F_rgb12: + return 36; + case PixelBuffer::F_rgba12: + *alphbits = 12; + return 48; + } + return 8; } HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { - HRESULT hr; - DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); + HRESULT hr; + DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); - 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; - } + 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 + //pbuf contains raw ARGB in PixelBuffer byteorder - DWORD lPitch = ddsd.lPitch; - BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; - BYTE r,g,b,a; - DWORD x,y,dwPixel; - DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight; + DWORD lPitch = ddsd.lPitch; + BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; + DWORD dwOrigWidth=ddsd.dwWidth,dwOrigHeight=ddsd.dwHeight; - switch(ConvNeeded) { - case Conv32to32: - case Conv32to32_NoAlpha: { + switch(ConvNeeded) { + case Conv32to32: + case Conv32to32_NoAlpha: { - DWORD *pSrcWord = (DWORD *) pbuf; - DWORD *pDstWord; - DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to32_NoAlpha) ? 0x00FFFFFF : 0xFFFFFFFF; + DWORD *pSrcWord = (DWORD *) pbuf; + DWORD *pDstWord; + DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to32_NoAlpha) ? 0x00FFFFFF : 0xFFFFFFFF; - for( y=0; y>24)); // unsigned >>, no need to & - b = (BYTE)((dwPixel>>16)&0x000000ff); - g = (BYTE)((dwPixel>> 8)&0x000000ff); - r = (BYTE)((dwPixel )&0x000000ff); + BYTE r,g,b,a; + a = (BYTE)((dwPixel>>24)); // unsigned >>, no need to & + b = (BYTE)((dwPixel>>16)&0x000000ff); + g = (BYTE)((dwPixel>> 8)&0x000000ff); + r = (BYTE)((dwPixel )&0x000000ff); - *pDstWord = (a << 24) | (r << 16)| (g << 8) | b; + *pDstWord = (a << 24) | (r << 16)| (g << 8) | b; #else - // simpler: just swap r & b - b = (BYTE)((dwPixel>>16)&0x000000ff); - r = (BYTE)((dwPixel )&0x000000ff); - *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) & dwAlphaMaskOff; + BYTE r,b; + // simpler: just swap r & b + b = (BYTE)((dwPixel>>16)&0x000000ff); + r = (BYTE)((dwPixel )&0x000000ff); + *pDstWord = ((dwPixel & 0xff00ff00) | (r<<16) | b) & dwAlphaMaskOff; #endif - } - } - break; - } + } + } + break; + } - case Conv32to16_1555: - case Conv32to16_0555: { - DWORD abit,*pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; - DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to16_0555) ? 0x7FFF : 0xFFFF; + case Conv32to16_1555: + case Conv32to16_0555: { + DWORD *pSrcWord = (DWORD *) pbuf; + WORD *pDstWord; + DWORD dwAlphaMaskOff = (ConvNeeded==Conv32to16_0555) ? 0x7FFF : 0xFFFF; - assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); - // for some reason, bits are 'in-order' when converting to 16bit + assert(ddsd.ddpfPixelFormat.dwRBitMask==0x7C00); + // for some reason, bits are 'in-order' when converting to 16bit - // just handle 1/15 alpha/rgb - for( y=0; y>16) & 0x00008000); // just copy high bit + abit = ((dwPixel>>16) & 0x00008000); // just copy high bit - // just look at most-signf-bit for alpha. (alternately, could - // convert any non-zero alpha to full transparent) + // just look at most-signf-bit for alpha. (alternately, could + // convert any non-zero alpha to full transparent) - b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 3; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 3; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; + b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 3; + g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 3; + r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; - // code truncates 8 bit values to 5 bit (or 1 for alpha) + // code truncates 8 bit values to 5 bit (or 1 for alpha) - *pDstWord = (abit | (r << 10)| (g << 5) | b) & dwAlphaMaskOff; - } - } - break; - } + *pDstWord = (abit | (r << 10)| (g << 5) | b) & dwAlphaMaskOff; + } + } + break; + } - case Conv32to16_0565: { // could merge this w/above case, but whatever - DWORD *pSrcWord = (DWORD *) pbuf; - WORD *pDstWord; + 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 + assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); + // for some reason, bits are 'in-order' when converting to 16bit - // just handle 1/15 alpha/rgb - for( y=0; y>16) & 0x000000ff) >> 3; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 2; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; + b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 3; + g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 2; + r = (BYTE)((dwPixel ) & 0x000000ff) >> 3; - // code truncates 8 bit values to 5 bit (or 1 for alpha) + // code truncates 8 bit values to 5 bit (or 1 for alpha) - *pDstWord = ((r << 11)| (g << 5) | b); - } - } - break; - } + *pDstWord = ((r << 11)| (g << 5) | b); + } + } + break; + } - case Conv32to24: { + case Conv32to24: { - DWORD *pSrcWord = (DWORD *) pbuf; - BYTE *pDstWord; + DWORD *pSrcWord = (DWORD *) pbuf; + BYTE *pDstWord; - for( y=0; y>16) & 0x000000ff); - g = (BYTE)((dwPixel>> 8) & 0x000000ff); - r = (BYTE)((dwPixel ) & 0x000000ff); + b = (BYTE)((dwPixel>>16) & 0x000000ff); + g = (BYTE)((dwPixel>> 8) & 0x000000ff); + r = (BYTE)((dwPixel ) & 0x000000ff); - *pDstWord = r; - *(pDstWord+1) = g; - *(pDstWord+2) = b; - } - } - break; - } + *pDstWord = r; + *(pDstWord+1) = g; + *(pDstWord+2) = 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( y=0; y>24)) >> 4; - b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 4; - g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 4; - r = (BYTE)((dwPixel ) & 0x000000ff) >> 4; + for(DWORD x=0; x>24)) >> 4; + b = (BYTE)((dwPixel>>16) & 0x000000ff) >> 4; + g = (BYTE)((dwPixel>> 8) & 0x000000ff) >> 4; + r = (BYTE)((dwPixel ) & 0x000000ff) >> 4; - case Conv24to24: { + *pDstWord = (a << 12) | (r << 8)| (g << 4) | b; + } + } + break; + } - BYTE *pSrcWord = (BYTE *) pbuf; - BYTE *pDstWord; - for( y=0; y> 3; - g = *(pSrcWord+1) >> 3; - b = *(pSrcWord+2) >> 3; + for(DWORD y=0; y> 3; + g = *(pSrcWord+1) >> 3; + b = *(pSrcWord+2) >> 3; - case Conv24to16_0565: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; + // code truncates 8 bit values to 5 bit, leaves high bit as 0 - assert(ddsd.ddpfPixelFormat.dwRBitMask==0xF800); - // for some reason, bits are 'in-order' when converting to 16bit + *pDstWord = (r << 10)| (g << 5) | b; + } + } + break; + } - for( y=0; y> 3; - g = *(pSrcWord+1) >> 2; - b = *(pSrcWord+2) >> 3; + for(DWORD y=0; y> 3; + g = *(pSrcWord+1) >> 2; + b = *(pSrcWord+2) >> 3; - case Conv24to32: { + // code truncates 8 bit values to 5 bit, leaves high bit as 0 - BYTE *pSrcWord = (BYTE *) pbuf; - DWORD *pDstWord; + *pDstWord = (r << 11)| (g << 5) | b; + } + } + break; + } - for( y=0; y> 8; - r = dwPixel & 0xFF; - - *pDstWord = (a<<24)| (r << 16)| (r << 8) | r; - } - } - break; - } + // bugbug? swapping doesnt work I dont understand why must + // swap bytes for 32-bit RGBA (herc) but not here in 24bit, + // where they seem to be in correct order in pixelbuffer - case ConvLum16to16_4444: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; + r = *pSrcWord; + g = *(pSrcWord+1); + b = *(pSrcWord+2); - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB + *pDstWord = 0xFF000000 | (r << 16)| (g << 8) | b; + } + } + break; + } + + case ConvLum16to32: { - for( y=0; y> 8; + r = dwPixel & 0xFF; - a = (BYTE)(dwPixel>>8) >> 4; - r = (BYTE)(dwPixel & 0x000000ff) >> 4; + *pDstWord = (a<<24)| (r << 16)| (r << 8) | r; + } + } + break; + } - *pDstWord = (a << 12) | (r << 8)| (r << 4) | r; - } - } - break; - } - - case ConvLum16to16_1555: { - WORD *pSrcWord = (WORD *) pbuf; - WORD *pDstWord; - - assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0x8000); // assumes ARGB - - for( y=0; y> 3; - - *pDstWord = (dwPixel & 0x8000) | (r << 10)| (r << 5) | r; - } - } - break; - } - - case ConvLum16to16: { - // AL bytes are in same order - CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2); - break; - } - - case ConvLum8to16_0565: - case ConvLum8to16_0555: { - BYTE *pSrcWord = (BYTE *) pbuf; - WORD *pDstWord; - DWORD FarShift,OrVal,MiddleRoundShift,GrnVal; - - if(ConvNeeded==ConvLum8to16_0555) { - 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( 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( y=0; yUnlock(NULL); - return E_INVALIDARG; - } - - pDDSurf->Unlock(NULL); - - return S_OK; + case ConvLum16to16_4444: { + WORD *pSrcWord = (WORD *) pbuf; + WORD *pDstWord; + + assert(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask==0xf000); // assumes ARGB + + for(DWORD y=0; y>8) >> 4; + r = (BYTE)(dwPixel & 0x000000ff) >> 4; + + *pDstWord = (a << 12) | (r << 8)| (r << 4) | r; + } + } + 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) | (r << 10)| (r << 5) | r; + } + } + break; + } + + case ConvLum16to16: { + // AL bytes are in same order + CopyMemory(pDDSurfBytes,pbuf,dwOrigWidth*dwOrigHeight*2); + break; + } + + case ConvLum8to16_0565: + case ConvLum8to16_0555: { + BYTE *pSrcWord = (BYTE *) pbuf; + WORD *pDstWord; + DWORD FarShift,OrVal,MiddleRoundShift; + + if(ConvNeeded==ConvLum8to16_0555) { + 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; yUnlock(NULL); + return E_INVALIDARG; + } + + pDDSurf->Unlock(NULL); + + return S_OK; } +HRESULT ConvertDDSurftoPixBuf(PixelBuffer *pixbuf,LPDIRECTDRAWSURFACE7 pDDSurf) { + HRESULT hr; + DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd); + + DWORD dwNumComponents=pixbuf->get_num_components(); + + assert(pixbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now + assert(pixbuf->get_image_type()==PixelBuffer::T_unsigned_byte); // cant handle anything else now + assert((dwNumComponents==3) || (dwNumComponents==4)); // cant handle anything else now + + BYTE *pbuf=pixbuf->_image.p(); + + if(FAILED( hr = pDDSurf->Lock( NULL, &ddsd, DDLOCK_NOSYSLOCK | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ))) { + dxgsg_cat.error() << "ConvertDDSurftoPixBuf Lock() failed! hr = " << ConvD3DErrorToString(hr) << "\n"; + return hr; + } + + DWORD dwXWindowOffset=0,dwYWindowOffset=0; + DWORD dwCopyWidth=ddsd.dwWidth,dwCopyHeight=ddsd.dwHeight; + + // get window offset so we know where to start grabbing pixels + 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<=pixbuf->get_ysize()))) { + pDDSurf->Unlock(NULL); + assert(0); + dxgsg_cat.error() << "ConvertDDSurftoPixBuf, PixBuf incorrect size to hold display surface!\n"; + return E_FAIL; + } + + // others not handled yet + assert((ddsd.ddpfPixelFormat.dwRGBBitCount==32)||(ddsd.ddpfPixelFormat.dwRGBBitCount==16)||(ddsd.ddpfPixelFormat.dwRGBBitCount==24)); + + //pbuf contains raw ARGB in PixelBuffer byteorder + + DWORD lPitch = ddsd.lPitch; + BYTE* pDDSurfBytes = (BYTE*)ddsd.lpSurface; + + if(dwNumComponents==4) { + DWORD *pDstWord = (DWORD *) pbuf; + switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { + + case 32: { + DWORD *pSrcWord; + + pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y>16)&0x000000ff); + g = (BYTE)((dwPixel>> 8)&0x000000ff); + b = (BYTE)((dwPixel )&0x000000ff); + + *pDstWord = (dwPixel & 0xff00ff00) | (r<<16) | b; + } + } + break; + } + + case 24: { + BYTE *pSrcByte; + + pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y> greenshift; + r = (dwPixel & redmask) >> redshift; + + *pDstWord = 0xFF000000 | (b << 16) | (g << 8) | r; + } + } + } + break; + } + } else { // convert to 24bpp pixbuf + BYTE *pDstWord = (BYTE *) pbuf; + switch(ddsd.ddpfPixelFormat.dwRGBBitCount) { + + case 32: { + DWORD *pSrcWord; + + pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y>16)&0x000000ff); + g = (BYTE)((dwPixel>> 8)&0x000000ff); + b = (BYTE)((dwPixel )&0x000000ff); + + *pDstWord++ = r; + *pDstWord++ = g; + *pDstWord++ = b; + } + } + break; + } + + case 24: { + BYTE *pSrcByte,*pDstByte; + + pDDSurfBytes+=ddsd.lPitch*(dwYWindowOffset+dwCopyHeight-1); + for(DWORD y=0; y> greenshift; + r = (dwPixel & redmask) >> redshift; + + *pDstWord++ = r; + *pDstWord++ = g; + *pDstWord++ = b; + } + } + } + break; + } + } + + + pDDSurf->Unlock(NULL); + + return S_OK; +} //----------------------------------------------------------------------------- // Name: CreateTextureFromBitmap() @@ -617,839 +920,840 @@ HRESULT ConvertPixBuftoDDSurf(ConversionType ConvNeeded,BYTE *pbuf,LPDIRECTDRAWS //----------------------------------------------------------------------------- LPDIRECTDRAWSURFACE7 DXTextureContext:: CreateTexture( HDC PrimaryDC, LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, LPDDPIXELFORMAT pTexPixFmts) { - HRESULT hr; - int i; - PixelBuffer *pbuf = _texture->_pbuffer; - int cNumAlphaBits; // number of alpha bits in texture pixfmt + HRESULT hr; + int i; + PixelBuffer *pbuf = _texture->_pbuffer; + int cNumAlphaBits; // number of alpha bits in texture pixfmt - DDPIXELFORMAT *pDesiredPixFmt; - LPDIRECTDRAWSURFACE7 pddsRender; - LPDIRECTDRAW7 pDD = NULL; + DDPIXELFORMAT *pDesiredPixFmt; + LPDIRECTDRAWSURFACE7 pddsRender; + LPDIRECTDRAW7 pDD = NULL; - DDPIXELFORMAT TexFmtsArr[MAX_DX_TEXPIXFMTS]; + DDPIXELFORMAT TexFmtsArr[MAX_DX_TEXPIXFMTS]; - ConversionType ConvNeeded; + ConversionType ConvNeeded; - // make local copy of array so I can muck with it during searches for this texture fmt - memcpy(TexFmtsArr,pTexPixFmts,cNumTexPixFmts*sizeof(DDPIXELFORMAT)); - pTexPixFmts=TexFmtsArr; - - // bpp indicates requested fmt, not pixbuf fmt - DWORD bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); - PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); - DWORD cNumColorChannels = pbuf->get_num_components(); + // make local copy of array so I can muck with it during searches for this texture fmt + memcpy(TexFmtsArr,pTexPixFmts,cNumTexPixFmts*sizeof(DDPIXELFORMAT)); + pTexPixFmts=TexFmtsArr; - assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now - assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now + // bpp indicates requested fmt, not pixbuf fmt + DWORD bpp = get_bits_per_pixel(pbuf->get_format(), &cNumAlphaBits); + PixelBuffer::Type pixbuf_type = pbuf->get_image_type(); + DWORD cNumColorChannels = pbuf->get_num_components(); - if((pixbuf_type != PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) { - dxgsg_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n"; - return NULL; - } - - DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); - DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); + assert(pbuf->get_component_width()==sizeof(BYTE)); // cant handle anything else now + assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now - // Get the device caps so we can check if the device has any constraints - // when using textures - D3DDEVICEDESC7 devDesc; - if( FAILED( pd3dDevice->GetCaps( &devDesc ) ) ) { - goto error_exit; - } + if((pixbuf_type != PixelBuffer::T_unsigned_byte) || (pbuf->get_component_width()!=1)) { + dxgsg_cat.error() << "CreateTexture failed, havent handled non 8-bit channel pixelbuffer types yet! \n"; + return NULL; + } - // Setup the new surface desc for the texture. Note how we are using the - // texture manage attribute, so Direct3D does alot of dirty work for us - DDSURFACEDESC2 ddsd; - ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); - ddsd.dwSize = sizeof(DDSURFACEDESC2); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH - | DDSD_PIXELFORMAT ; + DWORD dwOrigWidth = (DWORD)pbuf->get_xsize(); + DWORD dwOrigHeight = (DWORD)pbuf->get_ysize(); - ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); + // Get the device caps so we can check if the device has any constraints + // when using textures + D3DDEVICEDESC7 devDesc; + if(FAILED( pd3dDevice->GetCaps( &devDesc ) )) { + goto error_exit; + } - // setup ddpf to match against avail fmts + // Setup the new surface desc for the texture. Note how we are using the + // texture manage attribute, so Direct3D does alot of dirty work for us + DDSURFACEDESC2 ddsd; + ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); + ddsd.dwSize = sizeof(DDSURFACEDESC2); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH + | DDSD_PIXELFORMAT ; - ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - - if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| - (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || - (pbuf->get_format() == PixelBuffer::F_luminance)) { - ddsd.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE; - } + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); - ddsd.ddpfPixelFormat.dwRGBBitCount = bpp; + // setup ddpf to match against avail fmts - if (cNumAlphaBits) { - if (bpp == 8 && cNumAlphaBits == 8) // handle special case: Alpha only buffer - { - ddsd.dwFlags |= DDPF_ALPHA; - ddsd.dwAlphaBitDepth = 8; - ddsd.ddpfPixelFormat.dwAlphaBitDepth = 8; - ddsd.ddpfPixelFormat.dwFlags = DDPF_ALPHA; - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff; - } - else { - ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS; - if (cNumAlphaBits == 8) - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; - else if (cNumAlphaBits == 4) - ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xf000; - } - } + ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; - ddsd.dwWidth = dwOrigWidth; - ddsd.dwHeight = dwOrigHeight; + if((pbuf->get_format() == PixelBuffer::F_luminance_alpha)|| + (pbuf->get_format() == PixelBuffer::F_luminance_alphamask) || + (pbuf->get_format() == PixelBuffer::F_luminance)) { + ddsd.ddpfPixelFormat.dwFlags = DDPF_LUMINANCE; + } - #define ISPOW2(X) (((X) & ((X)-1))==0) + ddsd.ddpfPixelFormat.dwRGBBitCount = bpp; - if(!ISPOW2(ddsd.dwWidth) || !ISPOW2(ddsd.dwHeight)) { - dxgsg_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "!!!!! \n"; - #ifdef _DEBUG - exit(1); // want to catch badtexsize errors - #else - goto error_exit; - #endif - } + if(cNumAlphaBits) { + if(bpp == 8 && cNumAlphaBits == 8) { // handle special case: Alpha only buffer + ddsd.dwFlags |= DDPF_ALPHA; + ddsd.dwAlphaBitDepth = 8; + ddsd.ddpfPixelFormat.dwAlphaBitDepth = 8; + ddsd.ddpfPixelFormat.dwFlags = DDPF_ALPHA; + ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff; + } else { + ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS; + if(cNumAlphaBits == 8) + ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000; + else if(cNumAlphaBits == 4) + ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xf000; + } + } - BOOL bShrinkOriginal; + ddsd.dwWidth = dwOrigWidth; + ddsd.dwHeight = dwOrigHeight; - bShrinkOriginal=FALSE; - if((dwOrigWidth>devDesc.dwMaxTextureWidth)||(dwOrigHeight>devDesc.dwMaxTextureHeight)) { - #ifdef _DEBUG - dxgsg_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << devDesc.dwMaxTextureWidth << "," << devDesc.dwMaxTextureHeight << ") !!\n" - << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< devDesc.dwMaxTextureWidth << "," << devDesc.dwMaxTextureHeight << ") !\n"; - #endif - - if(dwOrigWidth>devDesc.dwMaxTextureWidth) - ddsd.dwWidth=devDesc.dwMaxTextureWidth; - if(dwOrigHeight>devDesc.dwMaxTextureHeight) - ddsd.dwHeight=devDesc.dwMaxTextureHeight; - bShrinkOriginal=TRUE; - } +#define ISPOW2(X) (((X) & ((X)-1))==0) -#if 0 - // checks for SQUARE reqmt - //riva128 seems to handle non-sq fine. is it wasting mem to do this? do I care or should I shrink to be sure we save mem? - if( (ddsd.dwWidth != ddsd.dwHeight) && (devDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )) { + if(!ISPOW2(ddsd.dwWidth) || !ISPOW2(ddsd.dwHeight)) { + dxgsg_cat.error() << "ERROR: texture dimensions are not a power of 2 for " << _tex->get_name() << "!!!!! \n"; +#ifdef _DEBUG + exit(1); // want to catch badtexsize errors +#else + goto error_exit; +#endif + } - // assume pow2 textures. sum exponents, divide by 2 rounding down to get sq size - int i,width_exp,height_exp; - for(i=ddsd.dwWidth,width_exp=0;i>1;width_exp++,i>>=1); - for(i=ddsd.dwHeight,height_exp=0;i>1;height_exp++,i>>=1); - ddsd.dwHeight = ddsd.dwWidth = 1<<((width_exp+height_exp)>>1); - bShrinkOriginal=TRUE; + BOOL bShrinkOriginal; - #ifdef _DEBUG - dxgsg_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< ddsd.dwWidth<<"," << ddsd.dwHeight << ") to meet HW square texture reqmt\n"; - #endif - - } + bShrinkOriginal=FALSE; + if((dwOrigWidth>devDesc.dwMaxTextureWidth)||(dwOrigHeight>devDesc.dwMaxTextureHeight)) { +#ifdef _DEBUG + dxgsg_cat.error() << "WARNING: " <<_tex->get_name() << ": Image size exceeds max texture dimensions of (" << devDesc.dwMaxTextureWidth << "," << devDesc.dwMaxTextureHeight << ") !!\n" + << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< devDesc.dwMaxTextureWidth << "," << devDesc.dwMaxTextureHeight << ") !\n"; #endif - if(bShrinkOriginal) { - // need 2 add checks for errors - PNMImage pnmi_src; - PNMImage *pnmi = new PNMImage(ddsd.dwWidth, ddsd.dwHeight, cNumColorChannels); - pbuf->store(pnmi_src); - pnmi->quick_filter_from(pnmi_src,0,0); + if(dwOrigWidth>devDesc.dwMaxTextureWidth) + ddsd.dwWidth=devDesc.dwMaxTextureWidth; + if(dwOrigHeight>devDesc.dwMaxTextureHeight) + ddsd.dwHeight=devDesc.dwMaxTextureHeight; + bShrinkOriginal=TRUE; + } - pbuf->load(*pnmi); // violates device independence of pixbufs +#if 0 + // checks for SQUARE reqmt + //riva128 seems to handle non-sq fine. is it wasting mem to do this? do I care or should I shrink to be sure we save mem? + if((ddsd.dwWidth != ddsd.dwHeight) && (devDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )) { - dwOrigWidth = (DWORD)pbuf->get_xsize(); - dwOrigHeight = (DWORD)pbuf->get_ysize(); - delete pnmi; - } + // assume pow2 textures. sum exponents, divide by 2 rounding down to get sq size + int i,width_exp,height_exp; + for(i=ddsd.dwWidth,width_exp=0;i>1;width_exp++,i>>=1); + for(i=ddsd.dwHeight,height_exp=0;i>1;height_exp++,i>>=1); + ddsd.dwHeight = ddsd.dwWidth = 1<<((width_exp+height_exp)>>1); + bShrinkOriginal=TRUE; + +#ifdef _DEBUG + dxgsg_cat.debug() << "Scaling "<< _tex->get_name() << " ("<< dwOrigWidth<<"," < ("<< ddsd.dwWidth<<"," << ddsd.dwHeight << ") to meet HW square texture reqmt\n"; +#endif + + } +#endif + + if(bShrinkOriginal) { + // need 2 add checks for errors + PNMImage pnmi_src; + PNMImage *pnmi = new PNMImage(ddsd.dwWidth, ddsd.dwHeight, cNumColorChannels); + pbuf->store(pnmi_src); + pnmi->quick_filter_from(pnmi_src,0,0); + + pbuf->load(*pnmi); // violates device independence of pixbufs + + dwOrigWidth = (DWORD)pbuf->get_xsize(); + dwOrigHeight = (DWORD)pbuf->get_ysize(); + delete pnmi; + } #if 0 //#ifdef _DEBUG // use dxcapsviewer - { static BOOL bPrinted=FALSE; - if(!bPrinted) { - dxgsg_cat.debug() << "Gfx card supported TexFmts:\n"; - for(i=0;idwFlags & (DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) ) || - ( pCurPixFmt->dwFourCC != 0 ) || - ((cNumAlphaBits==0) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS))) { - - // Make sure to skip any FourCC formats, bump formats - // they are not handled by this code yet + // Mark formats I dont want to deal with + for(i=0,pCurPixFmt=pTexPixFmts;idwFlags & (DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) ) || + ( pCurPixFmt->dwFourCC != 0 ) || + ((cNumAlphaBits==0) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS))) { - // note: I'm screening out alpha if no alpha requested, so - // search fails if 32-rgba avail, but not 32-bit rgb - // I could recode for that case too, hopefully this case will not pop up + // Make sure to skip any FourCC formats, bump formats + // they are not handled by this code yet - pCurPixFmt->dwRGBBitCount+=1; // incr so it wont be an exact match anymore - } - } + // note: I'm screening out alpha if no alpha requested, so + // search fails if 32-rgba avail, but not 32-bit rgb + // I could recode for that case too, hopefully this case will not pop up - assert(((cNumColorChannels==4)||(cNumColorChannels==2))==(cNumAlphaBits>0)); + pCurPixFmt->dwRGBBitCount+=1; // incr so it wont be an exact match anymore + } + } - // handle each bitdepth separately + assert(((cNumColorChannels==4)||(cNumColorChannels==2))==(cNumAlphaBits>0)); - switch(bpp) { // bpp is REQUESTED bpp, not what exists in the pixbuf array + // handle each bitdepth separately - case 32: + switch(bpp) { // bpp is REQUESTED bpp, not what exists in the pixbuf array + + case 32: #ifdef _DEBUG - if(!dx_force_16bpptextures) + if(!dx_force_16bpptextures) #endif - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && - (((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)!=0)==(cNumAlphaBits!=0))) { - // we should have a match - assert(pCurPixFmt->dwRGBAlphaBitMask==0xFF000000); - ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32); - goto found_matching_format; - break; - } - } + for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && + (((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)!=0)==(cNumAlphaBits!=0))) { + // we should have a match + assert(pCurPixFmt->dwRGBAlphaBitMask==0xFF000000); + ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32); + goto found_matching_format; + break; + } + } - if(cNumAlphaBits>0) { - // no 32-bit fmt, look for 16 bit w/alpha (1-15) + if(cNumAlphaBits>0) { + // no 32-bit fmt, look for 16 bit w/alpha (1-15) - // 32 bit RGBA was requested, but only 16 bit alpha fmts are avail - // by default, convert to 4-4-4-4 which has 4-bit alpha for blurry edges - // if we know tex only needs 1 bit alpha (i.e. for a mask), use 1555 instead + // 32 bit RGBA was requested, but only 16 bit alpha fmts are avail + // by default, convert to 4-4-4-4 which has 4-bit alpha for blurry edges + // if we know tex only needs 1 bit alpha (i.e. for a mask), use 1555 instead - ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555; - DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; - // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion - // this should be true on most cards. + ConversionType ConvTo1=Conv32to16_4444,ConvTo2=Conv32to16_1555; + DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; + // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion + // this should be true on most cards. - #ifndef FORCE_16bpp_1555 - if(cNumAlphaBits==1) - #endif - { - ConvTo1=Conv32to16_1555; - dwAlphaMask1=0x8000; - } - - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { - ConvNeeded=ConvTo1; - goto found_matching_format; - } - } +#ifndef FORCE_16bpp_1555 + if(cNumAlphaBits==1) +#endif + { + ConvTo1=Conv32to16_1555; + dwAlphaMask1=0x8000; + } - #ifdef FORCE_16bpp_1555 - break; - #endif + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) + && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { + ConvNeeded=ConvTo1; + goto found_matching_format; + } + } - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { - ConvNeeded=ConvTo2; - goto found_matching_format; - } - } +#ifdef FORCE_16bpp_1555 + break; +#endif - // at this point, bail. dont worry about converting to non-alpha formats yet, - // I think this will be a very rare case - szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!\n"; - } + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) + && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { + ConvNeeded=ConvTo2; + goto found_matching_format; + } + } - break; + // at this point, bail. dont worry about converting to non-alpha formats yet, + // I think this will be a very rare case + szErrorMsg = "CreateTexture failed: couldn't find compatible Tex DDPIXELFORMAT! no available 16 or 32-bit alpha formats!\n"; + } - case 24: + break; - assert(cNumAlphaBits==0); // dont know how to handle non-zero alpha for 24bit total + case 24: + + assert(cNumAlphaBits==0); // dont know how to handle non-zero alpha for 24bit total #ifdef _DEBUG - if(!dx_force_16bpptextures) + if(!dx_force_16bpptextures) #endif - for(i=0,pCurPixFmt=pTexPixFmts;idwFlags & DDPF_RGB)&&(pCurPixFmt->dwRGBBitCount==24)) { - ConvNeeded=((cNumColorChannels==3) ? Conv24to24 : Conv32to24); - goto found_matching_format; - } - } + for(i=0,pCurPixFmt=pTexPixFmts;idwFlags & DDPF_RGB)&&(pCurPixFmt->dwRGBBitCount==24)) { + ConvNeeded=((cNumColorChannels==3) ? Conv24to24 : Conv32to24); + goto found_matching_format; + } + } #ifdef _DEBUG - if(!dx_force_16bpptextures) + if(!dx_force_16bpptextures) #endif - // no 24-bit fmt. look for 32 bit fmt (note: this is memory-hogging choice - // instead I could look for memory-conserving 16-bit fmt). - // check mask to ensure ARGB, not RGBA (which I am not handling here) - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB) - && ((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0xFFFFFF) - ) { - // I'm allowing alpha formats here. will set alpha to opaque - ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32_NoAlpha); - goto found_matching_format; - } - } - // no 24-bit or 32 fmt. look for 16 bit fmt - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i16 conversion, should be true on most cards. - if((pCurPixFmt->dwFlags & DDPF_RGB) && (pCurPixFmt->dwRGBBitCount==16) - && !(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { // no alpha fmts - // if numchan==4,this means user has requested we throw away the input alpha channel - if(pCurPixFmt->dwGBitMask==0x7E0) { - // assumes GBitMask is the biggest one, if we have 16 bit 3-channel - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); - } else { - assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); - } - goto found_matching_format; - } - } + // no 24-bit fmt. look for 32 bit fmt (note: this is memory-hogging choice + // instead I could look for memory-conserving 16-bit fmt). + // check mask to ensure ARGB, not RGBA (which I am not handling here) + for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB) + && ((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0xFFFFFF) + ) { + // I'm allowing alpha formats here. will set alpha to opaque + ConvNeeded=((cNumColorChannels==3) ? Conv24to32 : Conv32to32_NoAlpha); + goto found_matching_format; + } + } - // at this point, bail. - break; + // no 24-bit or 32 fmt. look for 16 bit fmt + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];i16 conversion, should be true on most cards. + if((pCurPixFmt->dwFlags & DDPF_RGB) && (pCurPixFmt->dwRGBBitCount==16) + && !(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { // no alpha fmts + // if numchan==4,this means user has requested we throw away the input alpha channel + if(pCurPixFmt->dwGBitMask==0x7E0) { + // assumes GBitMask is the biggest one, if we have 16 bit 3-channel + ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); + } else { + assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); + ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); + } + goto found_matching_format; + } + } - case 16: + // at this point, bail. + break; - if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { - // look for native lum fmt - #ifdef _DEBUG - if(!dx_force_16bpptextures) - #endif - { + case 16: - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && - (pCurPixFmt->dwFlags & DDPF_LUMINANCE)) { - ConvNeeded=ConvLum16to16; - goto found_matching_format; - } - } - - // else look for 32bpp ARGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && - (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum16to32; - goto found_matching_format; - } - } - } - - // find compatible 16bpp fmt - ConversionType ConvTo1=ConvLum16to16_4444,ConvTo2=ConvLum16to16_1555; - DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; - // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion - // this should be true on most cards. - - #ifndef FORCE_16bpp_1555 - if(cNumAlphaBits==1) - #endif - { - ConvTo1=ConvLum16to16_1555; - dwAlphaMask1=0x8000; - } - - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { - ConvNeeded=ConvTo1; - goto found_matching_format; - } - } - - #ifdef FORCE_16bpp_1555 - break; - #endif - - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) - && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { - ConvNeeded=ConvTo2; - goto found_matching_format; - } - } - - } else - - // look for compatible 16bit fmts, if none then give up - // (dont worry about other bitdepths for 16 bit) - - for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==16)&&(pCurPixFmt->dwFlags & DDPF_RGB)) { - switch(cNumAlphaBits) { - case 0: - if(!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { - // if numchan==4,this means user has requested we throw away the input alpha channel - if(pCurPixFmt->dwGBitMask==0x7E0) { - // assumes GBitMask is the biggest one, if we have 16 bit 3-channel - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); - } else { - assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); - ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); - } - goto found_matching_format; - } - break; - case 1: - if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& - (pCurPixFmt->dwRGBAlphaBitMask==0x8000)) { - ConvNeeded=Conv32to16_1555; - goto found_matching_format; - } - break; - case 4: - if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& - (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) { - ConvNeeded=Conv32to16_4444; - goto found_matching_format; - } - break; - } - } - } - - break; - - case 8: - if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { - // look for native lum fmt - - assert(cNumAlphaBits==0); // dont handle those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too - #ifdef _DEBUG - if(!dx_force_16bpptextures) - #endif - { - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==8) && (pCurPixFmt->dwFlags & DDPF_LUMINANCE) && - (pCurPixFmt->dwLuminanceBitMask==0xFF)) { - ConvNeeded=ConvLum8to8; - goto found_matching_format; - } - } - - // else look for 24bpp RGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==24) && (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum8to24; - goto found_matching_format; - } - } - - // else look for 32bpp RGB - for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB)) { - ConvNeeded=ConvLum8to32; - goto found_matching_format; - } - } - } - - // find compatible 16bpp fmt, just look for any 565, then 0555 - DWORD dwMasks[2] = {0xF800, 0x7C00 }; - - for (DWORD modenum=0;modenum<2;modenum++) - for(i=0,pCurPixFmt=&pTexPixFmts[0];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_RGB) - && (!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) - && (pCurPixFmt->dwRBitMask==dwMasks[modenum]) ) { - ConvNeeded=ConvLum8to16_0565; - goto found_matching_format; - } - } - } - break; - - default: - szErrorMsg = "CreateTexture failed: unhandled pixel bitdepth in DX loader"; - } - - // if we've gotten here, haven't found a match - - dxgsg_cat.error() << szErrorMsg << "; requested tex bitdepth: " << bpp << "\n"; - goto error_exit; - - /////////////////////////////////////////////////////////// - - found_matching_format: - - ddsd.ddpfPixelFormat = *pCurPixFmt; - - // Get the device's render target, so we can then use the render target to - // get a ptr to a DDraw object. We need the DirectDraw interface for - // creating surfaces. - - pd3dDevice->GetRenderTarget( &pddsRender ); - pddsRender->GetDDInterface( (VOID**)&pDD ); - pddsRender->Release(); - - ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE; - - ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE // Turn on texture management - | DDSCAPS2_HINTSTATIC; // BUGBUG: is this ok for ALL textures? - - // validate magfilter setting - // degrade filtering if no HW support - - Texture::FilterType ft; - - ft =_tex->get_magfilter(); - if((ft!=Texture::FT_linear) && ft!=Texture::FT_nearest) { - if(ft==Texture::FT_nearest_mipmap_nearest) - ft=Texture::FT_nearest; - else ft=Texture::FT_linear; - } - - if((ft==Texture::FT_linear) && !(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) - ft=Texture::FT_nearest; - _tex->set_magfilter(ft); - - BOOL bDoMipMaps; - - // figure out if we are mipmapping this texture - ft =_tex->get_minfilter(); - bDoMipMaps=FALSE; - - if(!dx_ignore_mipmaps) { // set if no HW mipmap capable - #ifdef _DEBUG - bDoMipMaps=dx_mipmap_everything; - #endif - switch(ft) { - case Texture::FT_nearest_mipmap_nearest: - case Texture::FT_linear_mipmap_nearest: - case Texture::FT_nearest_mipmap_linear: // pick nearest in each, interpolate linearly b/w them - case Texture::FT_linear_mipmap_linear: - bDoMipMaps=TRUE; - } - } else if((ft==Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types - (ft==Texture::FT_nearest_mipmap_linear)) { - ft=Texture::FT_nearest; - } else if((ft==Texture::FT_linear_mipmap_nearest) || - (ft==Texture::FT_linear_mipmap_linear)) { - ft=Texture::FT_linear; - } - - assert((devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST)!=0); - - switch(ft) { - case Texture::FT_nearest_mipmap_linear: - if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPNEAREST)) - ft=Texture::FT_nearest_mipmap_nearest; - break; - case Texture::FT_linear_mipmap_nearest: - if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR)) - ft=Texture::FT_nearest_mipmap_nearest; - break; - case Texture::FT_linear_mipmap_linear: - if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR)) { - if(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR) - ft=Texture::FT_linear_mipmap_nearest; - else ft=Texture::FT_nearest_mipmap_nearest; // if you cant do linear in a level, you probably cant do linear b/w levels, so just do nearest-all - } - break; - case Texture::FT_linear: - if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) - ft=Texture::FT_nearest; - break; - } - - _tex->set_minfilter(ft); - - int aniso_degree; - - aniso_degree=1; - if(devDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANISOTROPY) { - aniso_degree=_tex->get_anisotropic_degree(); - if((aniso_degree>devDesc.dwMaxAnisotropy) + if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { + // look for native lum fmt #ifdef _DEBUG - || dx_force_anisotropic_filtering + if(!dx_force_16bpptextures) #endif - ) - aniso_degree=devDesc.dwMaxAnisotropy; - } - _tex->set_anisotropic_degree(aniso_degree); - #ifdef _DEBUG - dxgsg_cat.spam() << "CreateTexture: setting aniso degree for "<< _tex->get_name() << " to: " << aniso_degree << endl; - #endif + { - if(bDoMipMaps) { - // We dont specify mipmapcount, so CreateSurface will auto-create surfs - // for all mipmaps down to 1x1 (if driver supports deep-mipmaps, otherwise Nx1) - ddsd.ddsCaps.dwCaps |= (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX); - dxgsg_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl; - } + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && + (pCurPixFmt->dwFlags & DDPF_LUMINANCE)) { + ConvNeeded=ConvLum16to16; + goto found_matching_format; + } + } - if(devDesc.dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { - // must assign a texture to a specific stage - // for now I'm just going to use stage 0 for all - ddsd.dwTextureStage=0; - ddsd.dwFlags |= DDSD_TEXTURESTAGE; - } + // else look for 32bpp ARGB + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) && + (pCurPixFmt->dwFlags & DDPF_RGB)) { + ConvNeeded=ConvLum16to32; + goto found_matching_format; + } + } + } - PRINTVIDMEM(pDD,&ddsd.ddsCaps,"texture surf (includes AGP mem)"); + // find compatible 16bpp fmt + ConversionType ConvTo1=ConvLum16to16_4444,ConvTo2=ConvLum16to16_1555; + DWORD dwAlphaMask1=0xF000,dwAlphaMask2=0x8000; + // assume ALPHAMASK is x8000 and RGBMASK is x7fff to simplify 32->16 conversion + // this should be true on most cards. - // Create a new surface for the texture - if( FAILED( hr = pDD->CreateSurface( &ddsd, &_surface, NULL ) ) ) - { - dxgsg_cat.error() << "CreateTexture failed: pDD->CreateSurface() failed! hr = " << ConvD3DErrorToString(hr) << "\n"; - goto error_exit; - } +#ifndef FORCE_16bpp_1555 + if(cNumAlphaBits==1) +#endif + { + ConvTo1=ConvLum16to16_1555; + dwAlphaMask1=0x8000; + } + + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) + && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask1)) { + ConvNeeded=ConvTo1; + goto found_matching_format; + } + } + +#ifdef FORCE_16bpp_1555 + break; +#endif + + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS) + && (pCurPixFmt->dwRGBAlphaBitMask==dwAlphaMask2)) { + ConvNeeded=ConvTo2; + goto found_matching_format; + } + } + + } else + + // look for compatible 16bit fmts, if none then give up + // (dont worry about other bitdepths for 16 bit) + + for(i=0,pCurPixFmt=pTexPixFmts;idwRGBBitCount==16)&&(pCurPixFmt->dwFlags & DDPF_RGB)) { + switch(cNumAlphaBits) { + case 0: + if(!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) { + // if numchan==4,this means user has requested we throw away the input alpha channel + if(pCurPixFmt->dwGBitMask==0x7E0) { + // assumes GBitMask is the biggest one, if we have 16 bit 3-channel + ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0565 : Conv32to16_0565); + } else { + assert((pCurPixFmt->dwRBitMask|pCurPixFmt->dwGBitMask|pCurPixFmt->dwBBitMask)==0x7FFF); + ConvNeeded=((cNumColorChannels==3) ? Conv24to16_0555 : Conv32to16_0555); + } + goto found_matching_format; + } + break; + case 1: + if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& + (pCurPixFmt->dwRGBAlphaBitMask==0x8000)) { + ConvNeeded=Conv32to16_1555; + goto found_matching_format; + } + break; + case 4: + if((pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)&& + (pCurPixFmt->dwRGBAlphaBitMask==0xF000)) { + ConvNeeded=Conv32to16_4444; + goto found_matching_format; + } + break; + } + } + } + + break; + + case 8: + if(ddsd.ddpfPixelFormat.dwFlags & DDPF_LUMINANCE) { + // look for native lum fmt + + assert(cNumAlphaBits==0); // dont handle those other 8bit lum fmts like 4-4, since 16 8-8 is usually supported too +#ifdef _DEBUG + if(!dx_force_16bpptextures) +#endif + { + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==8) && (pCurPixFmt->dwFlags & DDPF_LUMINANCE) && + (pCurPixFmt->dwLuminanceBitMask==0xFF)) { + ConvNeeded=ConvLum8to8; + goto found_matching_format; + } + } + + // else look for 24bpp RGB + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==24) && (pCurPixFmt->dwFlags & DDPF_RGB)) { + ConvNeeded=ConvLum8to24; + goto found_matching_format; + } + } + + // else look for 32bpp RGB + for(i=0,pCurPixFmt=&pTexPixFmts[cNumTexPixFmts-1];idwRGBBitCount==32) && (pCurPixFmt->dwFlags & DDPF_RGB)) { + ConvNeeded=ConvLum8to32; + goto found_matching_format; + } + } + } + + // find compatible 16bpp fmt, just look for any 565, then 0555 + DWORD dwMasks[2] = {0xF800, 0x7C00}; + + for(DWORD modenum=0;modenum<2;modenum++) + for(i=0,pCurPixFmt=&pTexPixFmts[0];idwRGBBitCount==16) && (pCurPixFmt->dwFlags & DDPF_RGB) + && (!(pCurPixFmt->dwFlags & DDPF_ALPHAPIXELS)) + && (pCurPixFmt->dwRBitMask==dwMasks[modenum])) { + ConvNeeded=ConvLum8to16_0565; + goto found_matching_format; + } + } + } + break; + + default: + szErrorMsg = "CreateTexture failed: unhandled pixel bitdepth in DX loader"; + } + + // if we've gotten here, haven't found a match + + dxgsg_cat.error() << szErrorMsg << "; requested tex bitdepth: " << bpp << "\n"; + goto error_exit; + + /////////////////////////////////////////////////////////// + + found_matching_format: + + ddsd.ddpfPixelFormat = *pCurPixFmt; + + // Get the device's render target, so we can then use the render target to + // get a ptr to a DDraw object. We need the DirectDraw interface for + // creating surfaces. + + pd3dDevice->GetRenderTarget( &pddsRender ); + pddsRender->GetDDInterface( (VOID**)&pDD ); + pddsRender->Release(); + + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE; + + ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE // Turn on texture management + | DDSCAPS2_HINTSTATIC; // BUGBUG: is this ok for ALL textures? + + // validate magfilter setting + // degrade filtering if no HW support + + Texture::FilterType ft; + + ft =_tex->get_magfilter(); + if((ft!=Texture::FT_linear) && ft!=Texture::FT_nearest) { + if(ft==Texture::FT_nearest_mipmap_nearest) + ft=Texture::FT_nearest; + else ft=Texture::FT_linear; + } + + if((ft==Texture::FT_linear) && !(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) + ft=Texture::FT_nearest; + _tex->set_magfilter(ft); + + BOOL bDoMipMaps; + + // figure out if we are mipmapping this texture + ft =_tex->get_minfilter(); + bDoMipMaps=FALSE; + + if(!dx_ignore_mipmaps) { // set if no HW mipmap capable +#ifdef _DEBUG + bDoMipMaps=dx_mipmap_everything; +#endif + switch(ft) { + case Texture::FT_nearest_mipmap_nearest: + case Texture::FT_linear_mipmap_nearest: + case Texture::FT_nearest_mipmap_linear: // pick nearest in each, interpolate linearly b/w them + case Texture::FT_linear_mipmap_linear: + bDoMipMaps=TRUE; + } + } else if((ft==Texture::FT_nearest_mipmap_nearest) || // cvt to no-mipmap filter types + (ft==Texture::FT_nearest_mipmap_linear)) { + ft=Texture::FT_nearest; + } else if((ft==Texture::FT_linear_mipmap_nearest) || + (ft==Texture::FT_linear_mipmap_linear)) { + ft=Texture::FT_linear; + } + + assert((devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_NEAREST)!=0); + + switch(ft) { + case Texture::FT_nearest_mipmap_linear: + if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPNEAREST)) + ft=Texture::FT_nearest_mipmap_nearest; + break; + case Texture::FT_linear_mipmap_nearest: + if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR)) + ft=Texture::FT_nearest_mipmap_nearest; + break; + case Texture::FT_linear_mipmap_linear: + if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR)) { + if(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR) + ft=Texture::FT_linear_mipmap_nearest; + else ft=Texture::FT_nearest_mipmap_nearest; // if you cant do linear in a level, you probably cant do linear b/w levels, so just do nearest-all + } + break; + case Texture::FT_linear: + if(!(devDesc.dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR)) + ft=Texture::FT_nearest; + break; + } + + _tex->set_minfilter(ft); + + int aniso_degree; + + aniso_degree=1; + if(devDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ANISOTROPY) { + aniso_degree=_tex->get_anisotropic_degree(); + if((aniso_degree>devDesc.dwMaxAnisotropy) +#ifdef _DEBUG + || dx_force_anisotropic_filtering +#endif + ) + aniso_degree=devDesc.dwMaxAnisotropy; + } + _tex->set_anisotropic_degree(aniso_degree); +#ifdef _DEBUG + dxgsg_cat.spam() << "CreateTexture: setting aniso degree for "<< _tex->get_name() << " to: " << aniso_degree << endl; +#endif + + if(bDoMipMaps) { + // We dont specify mipmapcount, so CreateSurface will auto-create surfs + // for all mipmaps down to 1x1 (if driver supports deep-mipmaps, otherwise Nx1) + ddsd.ddsCaps.dwCaps |= (DDSCAPS_MIPMAP | DDSCAPS_COMPLEX); + dxgsg_cat.debug() << "CreateTexture: generating mipmaps for "<< _tex->get_name() << endl; + } + + if(devDesc.dwDevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { + // must assign a texture to a specific stage + // for now I'm just going to use stage 0 for all + ddsd.dwTextureStage=0; + ddsd.dwFlags |= DDSD_TEXTURESTAGE; + } + + PRINTVIDMEM(pDD,&ddsd.ddsCaps,"texture surf (includes AGP mem)"); + + // Create a new surface for the texture + if(FAILED( hr = pDD->CreateSurface( &ddsd, &_surface, NULL ) )) { + dxgsg_cat.error() << "CreateTexture failed: pDD->CreateSurface() failed! hr = " << ConvD3DErrorToString(hr) << "\n"; + goto error_exit; + } #ifdef _DEBUG - dxgsg_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converted " << ConvNameStrs[ConvNeeded] << " \n"; + dxgsg_cat.debug() << "CreateTexture: "<< _tex->get_name() <<" converted " << ConvNameStrs[ConvNeeded] << " \n"; #endif - hr = ConvertPixBuftoDDSurf(ConvNeeded,pbuf->_image.p(),_surface); - if(FAILED(hr)) { - goto error_exit; - } + hr = ConvertPixBuftoDDSurf(ConvNeeded,pbuf->_image.p(),_surface); + if(FAILED(hr)) { + goto error_exit; + } - _surface->GetSurfaceDesc(&ddsd); + _surface->GetSurfaceDesc(&ddsd); - if(bDoMipMaps) { - DWORD i,oldcurxsize,oldcurysize,curxsize,curysize,cMipMapCount=ddsd.dwMipMapCount; - assert(ddsd.dwMipMapCount<20); + if(bDoMipMaps) { + DWORD i,oldcurxsize,oldcurysize,curxsize,curysize,cMipMapCount=ddsd.dwMipMapCount; + assert(ddsd.dwMipMapCount<20); - curxsize=ddsd.dwWidth; curysize=ddsd.dwHeight; + curxsize=ddsd.dwWidth; curysize=ddsd.dwHeight; - assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now - - // all mipmap sublevels require 1/3 of total original space. alloc 1/2 for safety - BYTE *pMipMapPixBufSpace = new BYTE[((curxsize*curysize*cNumColorChannels)/2)+1024]; + assert(pixbuf_type==PixelBuffer::T_unsigned_byte); // cant handle anything else now - LPDIRECTDRAWSURFACE7 pCurDDSurf=_surface; - pCurDDSurf->AddRef(); // so final release doesnt release the surface + // all mipmap sublevels require 1/3 of total original space. alloc 1/2 for safety + BYTE *pMipMapPixBufSpace = new BYTE[((curxsize*curysize*cNumColorChannels)/2)+1024]; - BYTE *pDstWord = pMipMapPixBufSpace; - BYTE *pLastMipLevelStart = (BYTE *) pbuf->_image.p(); + LPDIRECTDRAWSURFACE7 pCurDDSurf=_surface; + pCurDDSurf->AddRef(); // so final release doesnt release the surface + + BYTE *pDstWord = pMipMapPixBufSpace; + BYTE *pLastMipLevelStart = (BYTE *) pbuf->_image.p(); // clock_t start1,finish1; // start1=clock(); - for(i=1;i>1,1); - curxsize = max(curxsize>>1,1); + for(i=1;i>1,1); + curxsize = max(curxsize>>1,1); - assert(!((oldcurxsize==1)&&(oldcurysize==1))); + assert(!((oldcurxsize==1)&&(oldcurysize==1))); - BYTE *pSrcWord; - BYTE *pSrcLineStart=pLastMipLevelStart; + BYTE *pSrcWord; + BYTE *pSrcLineStart=pLastMipLevelStart; - // inc img start to DWORD boundary - while(((DWORD)pDstWord) & 0x11) - pDstWord++; + // inc img start to DWORD boundary + while(((DWORD)pDstWord) & 0x11) + pDstWord++; - pLastMipLevelStart = pDstWord; + pLastMipLevelStart = pDstWord; - DWORD x,y,cPixelSize=cNumColorChannels; - DWORD src_row_bytelength=oldcurxsize*cPixelSize; - DWORD two_src_row_bytelength=2*src_row_bytelength; + DWORD x,y,cPixelSize=cNumColorChannels; + DWORD src_row_bytelength=oldcurxsize*cPixelSize; + DWORD two_src_row_bytelength=2*src_row_bytelength; - DWORD DivShift=2; - if((oldcurxsize==1)||(oldcurysize==1)) - DivShift = 1; - DWORD x_srcptr_inc = ((oldcurxsize==1)? cPixelSize: (2*cPixelSize)); + DWORD DivShift=2; + if((oldcurxsize==1)||(oldcurysize==1)) + DivShift = 1; + DWORD x_srcptr_inc = ((oldcurxsize==1)? cPixelSize: (2*cPixelSize)); - // box-filter shrink down, avg 4 pixels at a time - for( y=0; y1) // handle 1x[X], [X]x1 cases - colr += *(pSrcWord+cPixelSize+c); - if(oldcurysize>1) { - colr += *(pSrcWord+src_row_bytelength+c); - if(oldcurxsize>1) - colr += *(pSrcWord+src_row_bytelength+cPixelSize+c); - } + for(int c=0;c1) // handle 1x[X], [X]x1 cases + colr += *(pSrcWord+cPixelSize+c); + if(oldcurysize>1) { + colr += *(pSrcWord+src_row_bytelength+c); + if(oldcurxsize>1) + colr += *(pSrcWord+src_row_bytelength+cPixelSize+c); + } - colr >>= DivShift; + colr >>= DivShift; - *(pDstWord+c)=(BYTE)colr; - } - } - } + *(pDstWord+c)=(BYTE)colr; + } + } + } - // now copy pixbuf to final DD surf + // now copy pixbuf to final DD surf - DDSCAPS2 ddsCaps; - LPDIRECTDRAWSURFACE7 pMipLevel_DDSurf; - ZeroMemory(&ddsCaps,sizeof(DDSCAPS2)); - ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; - ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; + DDSCAPS2 ddsCaps; + LPDIRECTDRAWSURFACE7 pMipLevel_DDSurf; + ZeroMemory(&ddsCaps,sizeof(DDSCAPS2)); + ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; - hr = pCurDDSurf->GetAttachedSurface(&ddsCaps, &pMipLevel_DDSurf); - if (FAILED(hr)) { - dxgsg_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n"; - pCurDDSurf->Release(); - goto error_exit; - } + hr = pCurDDSurf->GetAttachedSurface(&ddsCaps, &pMipLevel_DDSurf); + if(FAILED(hr)) { + dxgsg_cat.error() << "CreateTexture failed creating mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n"; + pCurDDSurf->Release(); + goto error_exit; + } - hr = ConvertPixBuftoDDSurf(ConvNeeded,pLastMipLevelStart,pMipLevel_DDSurf); - if(FAILED(hr)) { - pCurDDSurf->Release(); - goto error_exit; - } + hr = ConvertPixBuftoDDSurf(ConvNeeded,pLastMipLevelStart,pMipLevel_DDSurf); + if(FAILED(hr)) { + pCurDDSurf->Release(); + goto error_exit; + } - pCurDDSurf->Release(); - pCurDDSurf=pMipLevel_DDSurf; - } + pCurDDSurf->Release(); + pCurDDSurf=pMipLevel_DDSurf; + } // finish1=clock(); // double elapsed_time = (double)(finish1 - start1) / CLOCKS_PER_SEC; // cerr << "mipmap gen takes " << elapsed_time << " secs for this texture\n"; - - pCurDDSurf->Release(); - delete pMipMapPixBufSpace; - - #ifdef _DEBUG - if(dx_debug_view_mipmaps) { + pCurDDSurf->Release(); + + delete pMipMapPixBufSpace; + +#ifdef _DEBUG + if(dx_debug_view_mipmaps) { #if 0 - if(!(ddcaps.dwCaps & DDCAPS_BLTSTRETCH)) { - dxgsg_cat.error() << "CreateTexture failed debug-viewing mipmaps, BLT stretching not supported! ( we need to do SW stretch) \n"; - goto error_exit; - } + if(!(ddcaps.dwCaps & DDCAPS_BLTSTRETCH)) { + dxgsg_cat.error() << "CreateTexture failed debug-viewing mipmaps, BLT stretching not supported! ( we need to do SW stretch) \n"; + goto error_exit; + } #endif - // display mipmaps on primary surf - HDC hTexDC; - LPDIRECTDRAWSURFACE7 pTextureCurrent,pTexturePrev = _surface; - int cury,curx; - HDC hScreenDC; - RECT scrnrect; - hScreenDC=GetDC(NULL); - - scrnrect.left=scrnrect.top=0; - scrnrect.bottom=GetDeviceCaps(hScreenDC,VERTRES); - scrnrect.right=GetDeviceCaps(hScreenDC,HORZRES); - char msg[500]; + // display mipmaps on primary surf + HDC hTexDC; + LPDIRECTDRAWSURFACE7 pTextureCurrent,pTexturePrev = _surface; + int cury,curx; + HDC hScreenDC; + RECT scrnrect; + hScreenDC=GetDC(NULL); - pTexturePrev->AddRef(); - + scrnrect.left=scrnrect.top=0; + scrnrect.bottom=GetDeviceCaps(hScreenDC,VERTRES); + scrnrect.right=GetDeviceCaps(hScreenDC,HORZRES); + char msg[500]; - for (i = 0,curx=scrnrect.left,cury=scrnrect.top; i < ddsd.dwMipMapCount; i++) { - - DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_cur); - pTexturePrev->GetSurfaceDesc(&ddsd_cur); - - hr = pTexturePrev->GetDC(&hTexDC); - if (FAILED(hr)) { - dxgsg_cat.error() << "GetDC failed hr = " << ConvD3DErrorToString(hr) << "\n"; - break; - } - - BOOL res; - // res = BitBlt(PrimaryDC,0,0,ddsd.dwWidth,ddsd.dwHeight, TexDC,0,0,SRCCOPY); - // loader inverts y, so use StretchBlt to re-invert it - // res = StretchBlt(PrimaryDC,0,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY); + pTexturePrev->AddRef(); + + + for(i = 0,curx=scrnrect.left,cury=scrnrect.top; i < ddsd.dwMipMapCount; i++) { + + DX_DECLARE_CLEAN(DDSURFACEDESC2, ddsd_cur); + pTexturePrev->GetSurfaceDesc(&ddsd_cur); + + hr = pTexturePrev->GetDC(&hTexDC); + if(FAILED(hr)) { + dxgsg_cat.error() << "GetDC failed hr = " << ConvD3DErrorToString(hr) << "\n"; + break; + } + + BOOL res; + // res = BitBlt(PrimaryDC,0,0,ddsd.dwWidth,ddsd.dwHeight, TexDC,0,0,SRCCOPY); + // loader inverts y, so use StretchBlt to re-invert it + // res = StretchBlt(PrimaryDC,0,ddsd_cur.dwHeight+cury,ddsd_cur.dwWidth,-ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,SRCCOPY); #if 0 - // dxgsg_cat.error() << "WINVER = " << (void*)WINVER << "\n"; - if(cNumAlphaBits>0) { - BLENDFUNCTION bf; - bf.BlendOp = AC_SRC_OVER; bf.BlendFlags=0; - bf.SourceConstantAlpha=255; bf.AlphaFormat=AC_SRC_ALPHA; - res = AlphaBlend(hScreenDC,curx,cury,ddsd_cur.dwWidth,ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,bf); - if (!res) { - PrintLastError(msg); - dxgsg_cat.error() << "AlphaBlend BLT failed: "<0) { + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; bf.BlendFlags=0; + bf.SourceConstantAlpha=255; bf.AlphaFormat=AC_SRC_ALPHA; + res = AlphaBlend(hScreenDC,curx,cury,ddsd_cur.dwWidth,ddsd_cur.dwHeight, TexDC,0,0,ddsd_cur.dwWidth,ddsd_cur.dwHeight,bf); + if(!res) { + PrintLastError(msg); + dxgsg_cat.error() << "AlphaBlend BLT failed: "<scrnrect.right) { - curx=0; cury+=(scrnrect.bottom-scrnrect.top)/2; - } - - hr = pTexturePrev->ReleaseDC(hTexDC); - - if (FAILED(hr)) { - dxgsg_cat.error() << "tex ReleaseDC failed for mip "<Release(); - continue; - } - - DDSCAPS2 ddsCaps; - ZeroMemory(&ddsCaps,sizeof(DDSCAPS2)); - ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; - ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; - hr = pTexturePrev->GetAttachedSurface(&ddsCaps, &pTextureCurrent); - if (FAILED(hr)) { - dxgsg_cat.error() << " failed displaying mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n"; - } - // done with the previous texture - pTexturePrev->Release(); - pTexturePrev = pTextureCurrent; - } - - ReleaseDC(0,hScreenDC); - - HANDLE hArr[1]; - MSG winmsg; - hArr[0]=GetStdHandle(STD_INPUT_HANDLE); - GetMessage(&winmsg,NULL,0,0); - - int val=MsgWaitForMultipleObjects(1,hArr,TRUE,INFINITE,QS_KEY); - if(val==-1) { - PrintLastError(msg); - dxgsg_cat.error() << " MsgWaitForMultipleObjects returns " << val << " " <Release(); + if(curx>scrnrect.right) { + curx=0; cury+=(scrnrect.bottom-scrnrect.top)/2; + } - // Return the newly created texture - return _surface; + hr = pTexturePrev->ReleaseDC(hTexDC); - error_exit: + if(FAILED(hr)) { + dxgsg_cat.error() << "tex ReleaseDC failed for mip "<Release(); - if(_surface!=NULL) { - _surface->Release(); - _surface = NULL; - } + if(i==ddsd.dwMipMapCount-1) { + pTexturePrev->Release(); + continue; + } - return NULL; + DDSCAPS2 ddsCaps; + ZeroMemory(&ddsCaps,sizeof(DDSCAPS2)); + ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP; + ddsCaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL; + hr = pTexturePrev->GetAttachedSurface(&ddsCaps, &pTextureCurrent); + if(FAILED(hr)) { + dxgsg_cat.error() << " failed displaying mipmaps: GetAttachedSurf hr = " << ConvD3DErrorToString(hr) << "\n"; + } + // done with the previous texture + pTexturePrev->Release(); + pTexturePrev = pTextureCurrent; + } + + ReleaseDC(0,hScreenDC); + + HANDLE hArr[1]; + MSG winmsg; + hArr[0]=GetStdHandle(STD_INPUT_HANDLE); + GetMessage(&winmsg,NULL,0,0); + + int val=MsgWaitForMultipleObjects(1,hArr,TRUE,INFINITE,QS_KEY); + if(val==-1) { + PrintLastError(msg); + dxgsg_cat.error() << " MsgWaitForMultipleObjects returns " << val << " " <Release(); + + // Return the newly created texture + return _surface; + + error_exit: + + if(pDD!=NULL) + pDD->Release(); + if(_surface!=NULL) { + _surface->Release(); + _surface = NULL; + } + + return NULL; } @@ -1458,10 +1762,9 @@ CreateTexture( HDC PrimaryDC, LPDIRECT3DDEVICE7 pd3dDevice, int cNumTexPixFmts, // Desc: Release the surface used to store the texture //----------------------------------------------------------------------------- void DXTextureContext:: -DeleteTexture( ) -{ - if (_surface) _surface->Release(); - _surface = NULL; +DeleteTexture( ) { + if(_surface) _surface->Release(); + _surface = NULL; } @@ -1472,24 +1775,22 @@ DeleteTexture( ) //////////////////////////////////////////////////////////////////// DXTextureContext:: DXTextureContext(Texture *tex) : - TextureContext(tex) -{ +TextureContext(tex) { #ifdef _DEBUG - dxgsg_cat.spam() << "Making DX texture for " << tex->get_name() << "\n"; + dxgsg_cat.spam() << "Making DX texture for " << tex->get_name() << "\n"; #endif - _surface = NULL; - _tex = tex; + _surface = NULL; + _tex = tex; } DXTextureContext:: -~DXTextureContext() -{ +~DXTextureContext() { #ifdef _DEBUG - dxgsg_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n"; + dxgsg_cat.spam() << "Deleting DX texture for " << _tex->get_name() << "\n"; #endif - DeleteTexture(); - TextureContext::~TextureContext(); - _tex = NULL; + DeleteTexture(); + TextureContext::~TextureContext(); + _tex = NULL; }