/**************************************************************************** * * Mesa 3-D graphics library * Direct3D Driver Interface * * ======================================================================== * * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * ====================================================================== * * Language: ANSI C * Environment: Windows 9x/2000/XP/XBox (Win32) * * Description: Texture / Bitmap functions * ****************************************************************************/ #include "dglcontext.h" #include "ddlog.h" #include "gld_dx9.h" #include #include "texformat.h" #include "colormac.h" #include "texstore.h" #include "image.h" // #include "mem.h" //--------------------------------------------------------------------------- #define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h)) //--------------------------------------------------------------------------- // 1D texture fetch //--------------------------------------------------------------------------- #define CHAN_SRC( t, i, j, k, sz ) \ ((GLchan *)(t)->Data + (i) * (sz)) #define UBYTE_SRC( t, i, j, k, sz ) \ ((GLubyte *)(t)->Data + (i) * (sz)) #define USHORT_SRC( t, i, j, k ) \ ((GLushort *)(t)->Data + (i)) #define FLOAT_SRC( t, i, j, k ) \ ((GLfloat *)(t)->Data + (i)) //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); GLchan *rgba = (GLchan *)texel; rgba[RCOMP] = src[2]; rgba[GCOMP] = src[1]; rgba[BCOMP] = src[0]; rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_f_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); texel[RCOMP] = CHAN_TO_FLOAT(src[0]); texel[GCOMP] = CHAN_TO_FLOAT(src[1]); texel[BCOMP] = CHAN_TO_FLOAT(src[2]); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_f_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_1d_texel_f_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- #undef CHAN_SRC #undef UBYTE_SRC #undef USHORT_SRC #undef FLOAT_SRC //--------------------------------------------------------------------------- // 2D texture fetch //--------------------------------------------------------------------------- #define CHAN_SRC( t, i, j, k, sz ) \ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) #define UBYTE_SRC( t, i, j, k, sz ) \ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) #define USHORT_SRC( t, i, j, k ) \ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i))) #define FLOAT_SRC( t, i, j, k ) \ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i))) //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); GLchan *rgba = (GLchan *)texel; rgba[RCOMP] = src[2]; rgba[GCOMP] = src[1]; rgba[BCOMP] = src[0]; rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_f_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); texel[RCOMP] = CHAN_TO_FLOAT(src[0]); texel[GCOMP] = CHAN_TO_FLOAT(src[1]); texel[BCOMP] = CHAN_TO_FLOAT(src[2]); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_f_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_2d_texel_f_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- #undef CHAN_SRC #undef UBYTE_SRC #undef USHORT_SRC #undef FLOAT_SRC //--------------------------------------------------------------------------- // 3D texture fetch //--------------------------------------------------------------------------- #define CHAN_SRC( t, i, j, k, sz ) \ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ (t)->Width + (i)) * (sz) #define UBYTE_SRC( t, i, j, k, sz ) \ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ (t)->Width + (i)) * (sz)) #define USHORT_SRC( t, i, j, k ) \ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ (t)->Width + (i))) #define FLOAT_SRC( t, i, j, k ) \ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ (t)->Width + (i))) //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); GLchan *rgba = (GLchan *)texel; rgba[RCOMP] = src[2]; rgba[GCOMP] = src[1]; rgba[BCOMP] = src[0]; rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_f_X8R8G8B8( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); texel[RCOMP] = CHAN_TO_FLOAT(src[0]); texel[GCOMP] = CHAN_TO_FLOAT(src[1]); texel[BCOMP] = CHAN_TO_FLOAT(src[2]); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_f_X1R5G5B5( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLchan *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLchan *rgba = (GLchan *) texel; GLushort s = *src; rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); rgba[ACOMP] = CHAN_MAX; } //--------------------------------------------------------------------------- static void gld_fetch_3d_texel_f_X4R4G4B4( const struct gl_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel ) { const GLushort *src = USHORT_SRC( texImage, i, j, k ); GLushort s = *src; texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf ); texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf ); texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf ); texel[ACOMP] = 1.f; } //--------------------------------------------------------------------------- #undef CHAN_SRC #undef UBYTE_SRC #undef USHORT_SRC #undef FLOAT_SRC //--------------------------------------------------------------------------- // Direct3D texture formats that have no Mesa equivalent //--------------------------------------------------------------------------- const struct gl_texture_format _gld_texformat_X8R8G8B8 = { MESA_FORMAT_ARGB8888, /* MesaFormat */ GL_RGBA, /* BaseFormat */ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ 8, /* RedBits */ 8, /* GreenBits */ 8, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ 0, /* DepthBits */ 4, /* TexelBytes */ _mesa_texstore_argb8888, /* StoreTexImageFunc */ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */ gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */ gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */ gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */ }; const struct gl_texture_format _gld_texformat_X1R5G5B5 = { MESA_FORMAT_ARGB1555, /* MesaFormat */ GL_RGBA, /* BaseFormat */ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ 5, /* RedBits */ 5, /* GreenBits */ 5, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ 0, /* DepthBits */ 2, /* TexelBytes */ _mesa_texstore_argb1555, /* StoreTexImageFunc */ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */ gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */ gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */ gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */ }; const struct gl_texture_format _gld_texformat_X4R4G4B4 = { MESA_FORMAT_ARGB4444, /* MesaFormat */ GL_RGBA, /* BaseFormat */ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */ 4, /* RedBits */ 4, /* GreenBits */ 4, /* BlueBits */ 0, /* AlphaBits */ 0, /* LuminanceBits */ 0, /* IntensityBits */ 0, /* IndexBits */ 0, /* DepthBits */ 2, /* TexelBytes */ _mesa_texstore_argb4444, /* StoreTexImageFunc */ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */ gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */ gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */ gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */ }; //--------------------------------------------------------------------------- // Texture unit constants //--------------------------------------------------------------------------- // List of possible combinations of texture environments. // Example: GLD_TEXENV_MODULATE_RGBA means // GL_MODULATE, GL_RGBA base internal format. #define GLD_TEXENV_DECAL_RGB 0 #define GLD_TEXENV_DECAL_RGBA 1 #define GLD_TEXENV_DECAL_ALPHA 2 #define GLD_TEXENV_REPLACE_RGB 3 #define GLD_TEXENV_REPLACE_RGBA 4 #define GLD_TEXENV_REPLACE_ALPHA 5 #define GLD_TEXENV_MODULATE_RGB 6 #define GLD_TEXENV_MODULATE_RGBA 7 #define GLD_TEXENV_MODULATE_ALPHA 8 #define GLD_TEXENV_BLEND_RGB 9 #define GLD_TEXENV_BLEND_RGBA 10 #define GLD_TEXENV_BLEND_ALPHA 11 #define GLD_TEXENV_ADD_RGB 12 #define GLD_TEXENV_ADD_RGBA 13 #define GLD_TEXENV_ADD_ALPHA 14 // Per-stage (i.e. per-unit) texture environment typedef struct { DWORD ColorArg1; // Colour argument 1 D3DTEXTUREOP ColorOp; // Colour operation DWORD ColorArg2; // Colour argument 2 DWORD AlphaArg1; // Alpha argument 1 D3DTEXTUREOP AlphaOp; // Alpha operation DWORD AlphaArg2; // Alpha argument 2 } GLD_texenv; // TODO: Do we really need to set ARG1 and ARG2 every time? // They seem to always be TEXTURE and CURRENT respectively. // C = Colour out // A = Alpha out // Ct = Colour from Texture // Cf = Colour from fragment (diffuse) // At = Alpha from Texture // Af = Alpha from fragment (diffuse) // Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND) const GLD_texenv gldTexEnv[] = { // DECAL_RGB: C=Ct, A=Af {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // DECAL_ALPHA: use DECAL_RGB {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // REPLACE_RGB: C=Ct, A=Af {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // REPLACE_RGBA: C=Ct, A=At {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, // REPLACE_ALPHA: C=Cf, A=At {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, // MODULATE_RGB: C=CfCt, A=Af {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // MODULATE_RGBA: C=CfCt, A=AfAt {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, // MODULATE_ALPHA: C=Cf, A=AfAt {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, // BLEND_ALPHA: C=Cf, A=AfAt {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, // ADD_RGB: C=Cf+Ct, A=Af {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, // ADD_RGBA: C=Cf+Ct, A=AfAt {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, // ADD_ALPHA: C=Cf, A=AfAt {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, }; //--------------------------------------------------------------------------- D3DTEXTUREADDRESS _gldConvertWrap( GLenum wrap) { return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP; } //--------------------------------------------------------------------------- D3DTEXTUREFILTERTYPE _gldConvertMagFilter( GLenum magfilter) { return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT; } //--------------------------------------------------------------------------- void _gldConvertMinFilter( GLenum minfilter, D3DTEXTUREFILTERTYPE *min_filter, D3DTEXTUREFILTERTYPE *mip_filter) { switch (minfilter) { case GL_NEAREST: *min_filter = D3DTEXF_POINT; *mip_filter = D3DTEXF_NONE; break; case GL_LINEAR: *min_filter = D3DTEXF_LINEAR; *mip_filter = D3DTEXF_NONE; break; case GL_NEAREST_MIPMAP_NEAREST: *min_filter = D3DTEXF_POINT; *mip_filter = D3DTEXF_POINT; break; case GL_LINEAR_MIPMAP_NEAREST: *min_filter = D3DTEXF_LINEAR; *mip_filter = D3DTEXF_POINT; break; case GL_NEAREST_MIPMAP_LINEAR: *min_filter = D3DTEXF_POINT; *mip_filter = D3DTEXF_LINEAR; break; case GL_LINEAR_MIPMAP_LINEAR: *min_filter = D3DTEXF_LINEAR; *mip_filter = D3DTEXF_LINEAR; break; } } //--------------------------------------------------------------------------- D3DFORMAT _gldGLFormatToD3DFormat( GLenum internalFormat) { switch (internalFormat) { case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures return D3DFMT_L8; case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: return D3DFMT_L8; case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: return D3DFMT_A8; case GL_COLOR_INDEX: case GL_COLOR_INDEX1_EXT: case GL_COLOR_INDEX2_EXT: case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT: return D3DFMT_X8R8G8B8; case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: return D3DFMT_A8L8; case GL_R3_G3_B2: // TODO: Mesa does not support RGB332 internally return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2; case GL_RGB4: return D3DFMT_X4R4G4B4; case GL_RGB5: return D3DFMT_X1R5G5B5; case 3: case GL_RGB: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: return D3DFMT_R8G8B8; case GL_RGBA4: return D3DFMT_A4R4G4B4; case 4: case GL_RGBA: case GL_RGBA2: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: return D3DFMT_A8R8G8B8; case GL_RGB5_A1: return D3DFMT_A1R5G5B5; } // Return an acceptable default return D3DFMT_A8R8G8B8; } //--------------------------------------------------------------------------- GLenum _gldDecodeBaseFormat( IDirect3DTexture9 *pTex) { // Examine Direct3D texture and return base OpenGL internal texture format // NOTE: We can't use any base format info from Mesa because D3D might have // used a different texture format when we used D3DXCreateTexture(). // Base internal format is one of (Red Book p355): // GL_ALPHA, // GL_LUMINANCE, // GL_LUMINANCE_ALPHA, // GL_INTENSITY, // GL_RGB, // GL_RGBA // NOTE: INTENSITY not used (not supported by Direct3D) // LUMINANCE has same texture functions as RGB // LUMINANCE_ALPHA has same texture functions as RGBA // TODO: cache format instead of using GetLevelDesc() D3DSURFACE_DESC desc; _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc)); switch (desc.Format) { case D3DFMT_R8G8B8: case D3DFMT_X8R8G8B8: case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: case D3DFMT_R3G3B2: case D3DFMT_X4R4G4B4: case D3DFMT_P8: case D3DFMT_L8: return GL_RGB; case D3DFMT_A8R8G8B8: case D3DFMT_A1R5G5B5: case D3DFMT_A4R4G4B4: case D3DFMT_A8R3G3B2: case D3DFMT_A8P8: case D3DFMT_A8L8: case D3DFMT_A4L4: return GL_RGBA; case D3DFMT_A8: return GL_ALPHA; // Compressed texture formats. Need to check these... case D3DFMT_DXT1: return GL_RGBA; case D3DFMT_DXT2: return GL_RGB; case D3DFMT_DXT3: return GL_RGBA; case D3DFMT_DXT4: return GL_RGB; case D3DFMT_DXT5: return GL_RGBA; } // Fell through. Return arbitary default. return GL_RGBA; } //--------------------------------------------------------------------------- const struct gl_texture_format* _gldMesaFormatForD3DFormat( D3DFORMAT d3dfmt) { switch (d3dfmt) { case D3DFMT_A8R8G8B8: return &_mesa_texformat_argb8888; case D3DFMT_R8G8B8: return &_mesa_texformat_rgb888; case D3DFMT_R5G6B5: return &_mesa_texformat_rgb565; case D3DFMT_A4R4G4B4: return &_mesa_texformat_argb4444; case D3DFMT_A1R5G5B5: return &_mesa_texformat_argb1555; case D3DFMT_A8L8: return &_mesa_texformat_al88; case D3DFMT_R3G3B2: return &_mesa_texformat_rgb332; case D3DFMT_A8: return &_mesa_texformat_a8; case D3DFMT_L8: return &_mesa_texformat_l8; case D3DFMT_X8R8G8B8: return &_gld_texformat_X8R8G8B8; case D3DFMT_X1R5G5B5: return &_gld_texformat_X1R5G5B5; case D3DFMT_X4R4G4B4: return &_gld_texformat_X4R4G4B4; } // If we reach here then we've made an error somewhere else // by allowing a format that is not supported. assert(0); return NULL; // Shut up compiler warning } //--------------------------------------------------------------------------- // Copy* functions //--------------------------------------------------------------------------- void gldCopyTexImage1D_DX9( GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border ) { // TODO } //--------------------------------------------------------------------------- void gldCopyTexImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) { // TODO } //--------------------------------------------------------------------------- void gldCopyTexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ) { // TODO } //--------------------------------------------------------------------------- void gldCopyTexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) { // TODO } //--------------------------------------------------------------------------- void gldCopyTexSubImage3D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) { // TODO ? } //--------------------------------------------------------------------------- // Bitmap/Pixel functions //--------------------------------------------------------------------------- #define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) #define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1) typedef struct { FLOAT x, y; // 2D raster coords FLOAT z; // depth value FLOAT rhw; // reciprocal homogenous W (always 1.0f) FLOAT tu, tv; // texture coords } _GLD_IMAGE_VERTEX; //--------------------------------------------------------------------------- HRESULT _gldDrawPixels( GLcontext *ctx, BOOL bChromakey, // Alpha test for glBitmap() images GLint x, // GL x position GLint y, // GL y position (needs flipping) GLsizei width, // Width of input image GLsizei height, // Height of input image IDirect3DSurface9 *pImage) { // // Draw input image as texture implementing PixelZoom and clipping. // Any fragment operations currently enabled will be used. // GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); IDirect3DTexture9 *pTexture; D3DSURFACE_DESC d3dsd; IDirect3DSurface9 *pSurface; _GLD_IMAGE_VERTEX v[4]; HRESULT hr; float ZoomWidth, ZoomHeight; float ScaleWidth, ScaleHeight; // Create a texture to hold image hr = D3DXCreateTexture( gld->pDev, width, height, 1, // miplevels 0, // usage D3DFMT_A8R8G8B8, // format D3DPOOL_MANAGED, // pool &pTexture); if (FAILED(hr)) return hr; hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface); if (FAILED(hr)) { IDirect3DTexture9_Release(pTexture); return hr; } // Copy image into texture hr = D3DXLoadSurfaceFromSurface( pSurface, NULL, NULL, // Dest surface pImage, NULL, NULL, // Src surface D3DX_FILTER_NONE, 0); IDirect3DSurface9_Release(pSurface); if (FAILED(hr)) { IDirect3DTexture9_Release(pTexture); return hr; } // // Set up the quad like this (ascii-art ahead!) // // 3--2 // | | // 0--1 // // // Set depth v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2]; // Set Reciprocal Homogenous W v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f; // Set texcoords // Examine texture size - if different to input width and height // then we'll need to munge the texcoords to fit. IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd); ScaleWidth = (float)width / (float)d3dsd.Width; ScaleHeight = (float)height / (float)d3dsd.Height; v[0].tu = 0.0f; v[0].tv = 0.0f; v[1].tu = ScaleWidth; v[1].tv = 0.0f; v[2].tu = ScaleWidth; v[2].tv = ScaleHeight; v[3].tu = 0.0f; v[3].tv = ScaleHeight; // Set raster positions ZoomWidth = (float)width * ctx->Pixel.ZoomX; ZoomHeight = (float)height * ctx->Pixel.ZoomY; v[0].x = x; v[0].y = GLD_FLIP_Y(y); v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y); v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight); v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight); // Draw image with full HW acceleration // NOTE: Be nice to use a State Block for all this state... IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture); IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE); // IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT); // IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT); // IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT); // IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); // IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); IDirect3DDevice9_SetVertexShader(gld->pDev, NULL); IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE); // // Emulate Chromakey with an Alpha Test. // [Alpha Test is more widely supported anyway] // if (bChromakey) { // Switch on alpha testing IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE); // Fragment passes is alpha is greater than reference value IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER); // Set alpha reference value between Bitmap alpha values of // zero (transparent) and one (opaque). IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f); } IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX)); // Release texture IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL); IDirect3DTexture9_Release(pTexture); // Reset state to before we messed it up FLUSH_VERTICES(ctx, _NEW_ALL); return S_OK; } //--------------------------------------------------------------------------- void gld_DrawPixels_DX9( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels ) { GLD_context *gldCtx; GLD_driver_dx9 *gld; IDirect3DSurface9 *pImage; HRESULT hr; D3DLOCKED_RECT d3dLockedRect; const struct gl_texture_format *MesaFormat; MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); // Mesa does not currently handle this format. if (format == GL_BGR) return; gldCtx = GLD_GET_CONTEXT(ctx); gld = GLD_GET_DX9_DRIVER(gldCtx); hr = IDirect3DDevice9_CreateOffscreenPlainSurface( gld->pDev, width, height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pImage, NULL); if (FAILED(hr)) { return; } // // Use Mesa to fill in image // // Lock all of surface hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); if (FAILED(hr)) { IDirect3DSurface9_Release(pImage); return; } // unpack image, apply transfer ops and store directly in texture MesaFormat->StoreImage( ctx, 2, GL_RGBA, &_mesa_texformat_argb8888, d3dLockedRect.pBits, width, height, 1, 0, 0, 0, d3dLockedRect.Pitch, 0, /* dstImageStride */ format, type, pixels, unpack); IDirect3DSurface9_UnlockRect(pImage); _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage); IDirect3DSurface9_Release(pImage); } //--------------------------------------------------------------------------- void gld_ReadPixels_DX9( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *pack, GLvoid *dest) { GLD_context *gldCtx; GLD_driver_dx9 *gld; IDirect3DSurface9 *pBackbuffer = NULL; IDirect3DSurface9 *pNativeImage = NULL; IDirect3DSurface9 *pCanonicalImage = NULL; D3DSURFACE_DESC d3dsd; RECT rcSrc; // Source rect POINT ptDst; // Dest point HRESULT hr; D3DLOCKED_RECT d3dLockedRect; struct gl_pixelstore_attrib srcPacking; int i; GLint DstRowStride; const struct gl_texture_format *MesaFormat; switch (format) { case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: return; } MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); DstRowStride = _mesa_image_row_stride(pack, width, format, type); gldCtx = GLD_GET_CONTEXT(ctx); gld = GLD_GET_DX9_DRIVER(gldCtx); // Get backbuffer hr = IDirect3DDevice9_GetBackBuffer( gld->pDev, 0, // First swapchain 0, // First backbuffer D3DBACKBUFFER_TYPE_MONO, &pBackbuffer); if (FAILED(hr)) return; // Get backbuffer description hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } // Create a surface compatible with backbuffer hr = IDirect3DDevice9_CreateOffscreenPlainSurface( gld->pDev, width, height, d3dsd.Format, D3DPOOL_SCRATCH, &pNativeImage, NULL); if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } // Compute source rect and dest point SetRect(&rcSrc, 0, 0, width, height); OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height)); ptDst.x = ptDst.y = 0; // Get source pixels. // // This intermediate surface ensure that we can use CopyRects() // instead of relying on D3DXLoadSurfaceFromSurface(), which may // try and lock the backbuffer. This way seems safer. // // CopyRects has been removed for DX9. // /* hr = IDirect3DDevice9_CopyRects( gld->pDev, pBackbuffer, &rcSrc, 1, pNativeImage, &ptDst);*/ hr = D3DXLoadSurfaceFromSurface( pNativeImage, // Dest surface NULL, // Dest palette &rcSrc, // Dest rect pBackbuffer, // Src surface NULL, // Src palette &rcSrc, // Src rect D3DX_FILTER_NONE, // Filter 0 // Colorkey (0=no colorkey) ); if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } // Create an RGBA8888 surface hr = IDirect3DDevice9_CreateOffscreenPlainSurface( gld->pDev, width, height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pCanonicalImage, NULL); if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } // Convert to RGBA8888 hr = D3DXLoadSurfaceFromSurface( pCanonicalImage, // Dest surface NULL, NULL, // Dest palette, RECT pNativeImage, // Src surface NULL, NULL, // Src palette, RECT D3DX_FILTER_NONE, // Filter 0); // Colourkey if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } srcPacking.Alignment = 1; srcPacking.ImageHeight = height; srcPacking.LsbFirst = GL_FALSE; srcPacking.RowLength = 0; srcPacking.SkipImages = 0; srcPacking.SkipPixels = 0; srcPacking.SkipRows = 0; srcPacking.SwapBytes = GL_FALSE; // Lock all of image hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0); if (FAILED(hr)) { goto gld_ReadPixels_DX9_return; } // We need to flip the data. Yuck. // Perhaps Mesa has a span packer we can use in future... for (i=0; iStoreImage( ctx, 2, GL_RGBA, // base format MesaFormat, // dst format pDestRow, // dest addr width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z DstRowStride, // dst row stride 0, // dstImageStride GL_BGRA, // src format GL_UNSIGNED_BYTE, // src type pSrcRow, // src addr &srcPacking); // packing params of source image } IDirect3DSurface9_UnlockRect(pCanonicalImage); gld_ReadPixels_DX9_return: SAFE_RELEASE_SURFACE9(pCanonicalImage); SAFE_RELEASE_SURFACE9(pNativeImage); SAFE_RELEASE_SURFACE9(pBackbuffer); } //--------------------------------------------------------------------------- void gld_CopyPixels_DX9( GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type) { // // NOTE: Not allowed to copy vidmem to vidmem! // Therefore we use an intermediate image surface. // GLD_context *gldCtx; GLD_driver_dx9 *gld; IDirect3DSurface9 *pBackbuffer; D3DSURFACE_DESC d3dsd; IDirect3DSurface9 *pImage; RECT rcSrc; // Source rect POINT ptDst; // Dest point HRESULT hr; // Only backbuffer if (type != GL_COLOR) return; gldCtx = GLD_GET_CONTEXT(ctx); gld = GLD_GET_DX9_DRIVER(gldCtx); // Get backbuffer hr = IDirect3DDevice9_GetBackBuffer( gld->pDev, 0, // First swapchain 0, // First backbuffer D3DBACKBUFFER_TYPE_MONO, &pBackbuffer); if (FAILED(hr)) return; // Get backbuffer description hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); if (FAILED(hr)) { IDirect3DSurface9_Release(pBackbuffer); return; } // Create a surface compatible with backbuffer hr = IDirect3DDevice9_CreateOffscreenPlainSurface( gld->pDev, width, height, d3dsd.Format, D3DPOOL_SCRATCH, &pImage, NULL); if (FAILED(hr)) { IDirect3DSurface9_Release(pBackbuffer); return; } // Compute source rect and dest point SetRect(&rcSrc, 0, 0, width, height); OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height)); ptDst.x = ptDst.y = 0; // Get source pixels /* hr = IDirect3DDevice8_CopyRects( gld->pDev, pBackbuffer, &rcSrc, 1, pImage, &ptDst);*/ hr = D3DXLoadSurfaceFromSurface( pImage, // Dest surface NULL, // Dest palette &rcSrc, // Dest rect pBackbuffer, // Src surface NULL, // Src palette &rcSrc, // Src rect D3DX_FILTER_NONE, // Filter 0 // Colorkey (0=no colorkey) ); IDirect3DSurface9_Release(pBackbuffer); if (FAILED(hr)) { IDirect3DSurface9_Release(pImage); return; } _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage); IDirect3DSurface9_Release(pImage); } //--------------------------------------------------------------------------- void gld_Bitmap_DX9( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap) { GLD_context *gldCtx; GLD_driver_dx9 *gld; IDirect3DSurface9 *pImage; HRESULT hr; D3DLOCKED_RECT d3dLockedRect; BYTE *pTempBitmap; D3DCOLOR clBitmapOne, clBitmapZero; D3DCOLOR *pBits; const GLubyte *src; int i, j, k; gldCtx = GLD_GET_CONTEXT(ctx); gld = GLD_GET_DX9_DRIVER(gldCtx); // A NULL bitmap is valid, but merely advances the raster position if ((bitmap == NULL) || (width == 0) || (height == 0)) return; clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero clBitmapOne = D3DCOLOR_COLORVALUE( ctx->Current.RasterColor[0], ctx->Current.RasterColor[1], ctx->Current.RasterColor[2], 1.0f); // NOTE: Alpha is One hr = IDirect3DDevice9_CreateOffscreenPlainSurface( gld->pDev, width, height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pImage, NULL); if (FAILED(hr)) { return; } // Lock all of surface hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); if (FAILED(hr)) { IDirect3DSurface9_Release(pImage); return; } pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack); if (pTempBitmap == NULL) { IDirect3DSurface9_Release(pImage); return; } pBits = (D3DCOLOR*)d3dLockedRect.pBits; for (i=0; iDefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP, 0, i, 0); for (j=0; j<(width>>3); j++) { byte = *src++; for (k=0; k<8; k++) { *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; byte <<= 1; } } // Fill remaining bits from bitmap if (width & 7) { byte = *src; for (k=0; k<(width & 7); k++) { *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; byte <<= 1; } } } FREE(pTempBitmap); /* // unpack image, apply transfer ops and store directly in texture texImage->TexFormat->StoreImage( ctx, 2, GL_BITMAP, &_mesa_texformat_argb8888, d3dLockedRect.pBits, width, height, 1, 0, 0, 0, d3dLockedRect.Pitch, 0, // dstImageStride GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack); */ IDirect3DSurface9_UnlockRect(pImage); _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage); IDirect3DSurface9_Release(pImage); } //--------------------------------------------------------------------------- // Texture functions //--------------------------------------------------------------------------- void _gldAllocateTexture( GLcontext *ctx, struct gl_texture_object *tObj, struct gl_texture_image *texImage) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); IDirect3DTexture9 *pTex; D3DFORMAT d3dFormat; if (!tObj || !texImage) return; pTex = (IDirect3DTexture9*)tObj->DriverData; if (pTex) { // Decide whether we can keep existing D3D texture // by examining top-level surface. D3DSURFACE_DESC d3dsd; _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd)); // Release existing texture if not compatible if ((d3dsd.Width == texImage->Width) || (d3dsd.Height == texImage->Height)) { return; // Keep the existing texture } tObj->DriverData = NULL; _GLD_DX9_TEX(Release(pTex)); } d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat); D3DXCreateTexture( gld->pDev, texImage->Width, texImage->Height, // TODO: Re-evaluate mipmapping (glb.bUseMipmaps) ? D3DX_DEFAULT : 1, 0, // Usage d3dFormat, D3DPOOL_MANAGED, &pTex); tObj->DriverData = pTex; } //--------------------------------------------------------------------------- const struct gl_texture_format* gld_ChooseTextureFormat_DX9( GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType) { // [Based on mesa_choose_tex_format()] // // We will choose only texture formats that are supported // by Direct3D. If the hardware doesn't support a particular // texture format, then the D3DX texture calls that we use // will automatically use a HW supported format. // // The most critical aim is to reduce copying; if we can use // texture-image data directly then it will be a big performance assist. // switch (internalFormat) { case GL_INTENSITY: case GL_INTENSITY4: case GL_INTENSITY8: case GL_INTENSITY12: case GL_INTENSITY16: return &_mesa_texformat_l8; // D3DFMT_L8 case 1: case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: return &_mesa_texformat_l8; // D3DFMT_L8 case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: return &_mesa_texformat_a8; // D3DFMT_A8 case GL_COLOR_INDEX: case GL_COLOR_INDEX1_EXT: case GL_COLOR_INDEX2_EXT: case GL_COLOR_INDEX4_EXT: case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX12_EXT: case GL_COLOR_INDEX16_EXT: return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5 // Mesa will convert this for us later... // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5 case 2: case GL_LUMINANCE_ALPHA: case GL_LUMINANCE4_ALPHA4: case GL_LUMINANCE6_ALPHA2: case GL_LUMINANCE8_ALPHA8: case GL_LUMINANCE12_ALPHA4: case GL_LUMINANCE12_ALPHA12: case GL_LUMINANCE16_ALPHA16: return &_mesa_texformat_al88; // D3DFMT_A8L8 case GL_R3_G3_B2: return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2 case GL_RGB4: case GL_RGBA4: case GL_RGBA2: return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4 case 3: case GL_RGB: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: return &_mesa_texformat_rgb565; case 4: case GL_RGBA: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: return &_mesa_texformat_argb8888; case GL_RGB5_A1: return &_mesa_texformat_argb1555; default: _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); return NULL; } } //--------------------------------------------------------------------------- /* // Safer(?), slower version. void gld_TexImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); IDirect3DTexture9 *pTex; IDirect3DSurface9 *pSurface; RECT rcSrcRect; HRESULT hr; GLint texelBytes = 4; GLvoid *tempImage; if (!tObj || !texImage) return; if (level == 0) { _gldAllocateTexture(ctx, tObj, texImage); } pTex = (IDirect3DTexture9*)tObj->DriverData; if (!pTex) return; // Texture has not been created if (level >= IDirect3DTexture9_GetLevelCount(pTex)) return; // Level does not exist hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); if (FAILED(hr)) return; // Surface level doesn't exist (or just a plain error) tempImage = MALLOC(width * height * texelBytes); if (!tempImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); IDirect3DSurface9_Release(pSurface); return; } // unpack image, apply transfer ops and store in tempImage texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, &_mesa_texformat_argb8888, // dest format tempImage, width, height, 1, 0, 0, 0, width * texelBytes, 0, // dstImageStride format, type, pixels, packing); SetRect(&rcSrcRect, 0, 0, width, height); D3DXLoadSurfaceFromMemory( pSurface, NULL, NULL, tempImage, D3DFMT_A8R8G8B8, width * texelBytes, NULL, &rcSrcRect, D3DX_FILTER_NONE, 0); FREE(tempImage); IDirect3DSurface9_Release(pSurface); } */ //--------------------------------------------------------------------------- // Faster, more efficient version. // Copies subimage straight to dest texture void gld_TexImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); IDirect3DTexture9 *pTex; IDirect3DSurface9 *pSurface; HRESULT hr; D3DLOCKED_RECT d3dLockedRect; D3DSURFACE_DESC d3dsd; if (!tObj || !texImage) return; // GLQUAKE FIX // Test for input alpha data with non-alpha internalformat if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) { // Input format has alpha, but a non-alpha format has been requested. texImage->IntFormat = GL_RGBA; internalFormat = GL_RGBA; } if (level == 0) { _gldAllocateTexture(ctx, tObj, texImage); } pTex = (IDirect3DTexture9*)tObj->DriverData; if (!pTex) return; // Texture has not been created if (level >= IDirect3DTexture9_GetLevelCount(pTex)) return; // Level does not exist hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); if (FAILED(hr)) return; // Surface level doesn't exist (or just a plain error) IDirect3DSurface9_GetDesc(pSurface, &d3dsd); // Lock all of surface hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0); if (FAILED(hr)) { IDirect3DSurface9_Release(pSurface); return; } // unpack image, apply transfer ops and store directly in texture texImage->TexFormat->StoreImage( ctx, 2, texImage->Format, _gldMesaFormatForD3DFormat(d3dsd.Format), d3dLockedRect.pBits, width, height, 1, 0, 0, 0, d3dLockedRect.Pitch, 0, // dstImageStride format, type, pixels, packing); IDirect3DSurface9_UnlockRect(pSurface); IDirect3DSurface9_Release(pSurface); } //--------------------------------------------------------------------------- void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { // A 1D texture is a 2D texture with a height of zero gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage); } //--------------------------------------------------------------------------- /* void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage ) { GLD_GET_CONTEXT IDirect3DTexture9 *pTex; IDirect3DSurface9 *pSurface; D3DFORMAT d3dFormat; HRESULT hr; GLint texelBytes = 4; GLvoid *tempImage; RECT rcSrcRect; RECT rcDstRect; if (!tObj || !texImage) return; pTex = (IDirect3DTexture9*)tObj->DriverData; if (!pTex) return; // Texture has not been created if (level >= _GLD_DX9_TEX(GetLevelCount(pTex)) return; // Level does not exist hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface); if (FAILED(hr)) return; // Surface level doesn't exist (or just a plain error) d3dFormat = _gldGLFormatToD3DFormat(texImage->Format); tempImage = MALLOC(width * height * texelBytes); if (!tempImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); IDirect3DSurface9_Release(pSurface); return; } // unpack image, apply transfer ops and store in tempImage texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, &_mesa_texformat_argb8888, // dest format tempImage, width, height, 1, 0, 0, 0, width * texelBytes, 0, // dstImageStride format, type, pixels, packing); // Source rectangle is whole of input image SetRect(&rcSrcRect, 0, 0, width, height); // Dest rectangle must be offset to dest image SetRect(&rcDstRect, 0, 0, width, height); OffsetRect(&rcDstRect, xoffset, yoffset); D3DXLoadSurfaceFromMemory( pSurface, NULL, &rcDstRect, tempImage, D3DFMT_A8R8G8B8, width * texelBytes, NULL, &rcSrcRect, D3DX_FILTER_NONE, 0); FREE(tempImage); IDirect3DSurface9_Release(pSurface); } */ //--------------------------------------------------------------------------- // Faster, more efficient version. // Copies subimage straight to dest texture void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage ) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); IDirect3DTexture9 *pTex; IDirect3DSurface9 *pSurface; HRESULT hr; RECT rcDstRect; D3DLOCKED_RECT d3dLockedRect; D3DSURFACE_DESC d3dsd; if (!tObj || !texImage) return; pTex = (IDirect3DTexture9*)tObj->DriverData; if (!pTex) return; // Texture has not been created if (level >= IDirect3DTexture9_GetLevelCount(pTex)) return; // Level does not exist hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); if (FAILED(hr)) return; // Surface level doesn't exist (or just a plain error) IDirect3DSurface9_GetDesc(pSurface, &d3dsd); // Dest rectangle must be offset to dest image SetRect(&rcDstRect, 0, 0, width, height); OffsetRect(&rcDstRect, xoffset, yoffset); // Lock sub-rect of surface hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0); if (FAILED(hr)) { IDirect3DSurface9_Release(pSurface); return; } // unpack image, apply transfer ops and store directly in texture texImage->TexFormat->StoreImage(ctx, 2, texImage->Format, _gldMesaFormatForD3DFormat(d3dsd.Format), d3dLockedRect.pBits, width, height, 1, 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!! d3dLockedRect.Pitch, 0, // dstImageStride format, type, pixels, packing); IDirect3DSurface9_UnlockRect(pSurface); IDirect3DSurface9_Release(pSurface); } //--------------------------------------------------------------------------- void gld_TexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ) { gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage); } //--------------------------------------------------------------------------- void gld_DeleteTexture_DX9( GLcontext *ctx, struct gl_texture_object *tObj) { GLD_context *gld = (GLD_context*)(ctx->DriverCtx); if (tObj) { IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData; if (pTex) { /* // Make sure texture is not bound to a stage before releasing it for (int i=0; iCurrentTexture[i] == pTex) { gld->pDev->SetTexture(i, NULL); gld->CurrentTexture[i] = NULL; } }*/ _GLD_DX9_TEX(Release(pTex)); tObj->DriverData = NULL; } } } //--------------------------------------------------------------------------- __inline void _gldSetColorOps( const GLD_driver_dx9 *gld, GLuint unit, DWORD ColorArg1, D3DTEXTUREOP ColorOp, DWORD ColorArg2) { _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1)); _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp)); _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2)); } //--------------------------------------------------------------------------- __inline void _gldSetAlphaOps( const GLD_driver_dx9 *gld, GLuint unit, DWORD AlphaArg1, D3DTEXTUREOP AlphaOp, DWORD AlphaArg2) { _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1)); _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp)); _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2)); } //--------------------------------------------------------------------------- void gldUpdateTextureUnit( GLcontext *ctx, GLuint unit, BOOL bPassThrough) { GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); D3DTEXTUREFILTERTYPE minfilter; D3DTEXTUREFILTERTYPE mipfilter; GLenum BaseFormat; DWORD dwColorArg0; int iTexEnv = 0; GLD_texenv *pTexenv; // NOTE: If bPassThrough is FALSE then texture stage can be // disabled otherwise it must pass-through it's current fragment. const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit]; const struct gl_texture_object *tObj = pUnit->_Current; IDirect3DTexture9 *pTex = NULL; if (tObj) { pTex = (IDirect3DTexture9*)tObj->DriverData; } // Enable texturing if unit is enabled and a valid D3D texture exists // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) { if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) { // Enable texturing _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex)); } else { // Disable texturing, then return _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL)); if (bPassThrough) { _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); } else { _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); } return; } // Texture parameters _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter); // _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter)); // _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter)); // _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); // _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS))); // _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT))); _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter)); _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter)); _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS))); _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT))); // Texture priority _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f))); // Texture environment // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops. // See Page 355 of the Red Book. BaseFormat = _gldDecodeBaseFormat(pTex); switch (BaseFormat) { case GL_RGB: iTexEnv = 0; break; case GL_RGBA: iTexEnv = 1; break; case GL_ALPHA: iTexEnv = 2; break; } switch (pUnit->EnvMode) { case GL_DECAL: iTexEnv += 0; break; case GL_REPLACE: iTexEnv += 3; break; case GL_MODULATE: iTexEnv += 6; break; case GL_BLEND: // Set blend colour dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]); _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0)); iTexEnv += 9; break; case GL_ADD: iTexEnv += 12; break; } pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv]; _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2); _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2); } //--------------------------------------------------------------------------- void gld_NEW_TEXTURE_DX9( GLcontext *ctx) { // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units BOOL bUnit0Enabled; BOOL bUnit1Enabled; if (!ctx) return; // Sanity check if (ctx->Const.MaxTextureUnits == 1) { gldUpdateTextureUnit(ctx, 0, TRUE); return; } // // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!! // // Mesa 5: Texture Units altered //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE; //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE; bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; // If Unit0 is disabled and Unit1 is enabled then we must pass-though gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE); // We can always disable the last texture unit gldUpdateTextureUnit(ctx, 1, FALSE); #ifdef _DEBUG #if 0 { // Find out whether device supports current renderstates GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); // GLD_context *gld = GLD_GET_CONTEXT(ctx); DWORD dwPasses; _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses)); // if (FAILED(hr)) { // gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr); // } if (dwPasses != 1) { gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n"); } } #endif #endif }; //---------------------------------------------------------------------------