From 13ee7cd15485ca5ce8d5e7044ed4fb2dca29d180 Mon Sep 17 00:00:00 2001 From: Jason Edmeades Date: Mon, 23 Dec 2002 01:34:59 +0000 Subject: [PATCH] Query opengl to ensure it supports multitexture, and honour the number of supported texture units. Especially important for NVidia drivers which only support 2 texture units. --- dlls/d3d8/d3d8_private.h | 4 ++ dlls/d3d8/device.c | 79 ++++++++++++++++++++++++++++------------ dlls/d3d8/directx.c | 41 ++++++++++++++------- 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 2551ac7579f..6a9b0a41c4a 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -314,6 +314,10 @@ struct IDirect3DDevice8Impl Display *display; Window win; + /* OpenGL Extension related */ + BOOL isMultiTexture; + UINT TextureUnits; + UINT dummyTextureName[8]; }; diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 7ad03ccc255..99fa2de6cce 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -177,7 +177,7 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, } else { glMatrixMode(GL_PROJECTION); - checkGLcall("glMatrixMode"); + checkGLcall("glMatrixMode"); glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_PROJECTION].u.m[0][0]); checkGLcall("glLoadMatrixf"); @@ -301,6 +301,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, float s,t,r,q; + if (!(This->isMultiTexture) && textureNo>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + continue; + } + /* Query tex coords */ if (This->StateBlock.textures[textureNo] != NULL) { switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) { @@ -310,7 +315,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, t = *(float *)curPos; curPos = curPos + sizeof(float); TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t); - glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t); + if (This->isMultiTexture) { + glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t); + } else { + glTexCoord2f(s, t); + } break; case D3DRTYPE_VOLUMETEXTURE: @@ -321,7 +330,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, r = *(float *)curPos; curPos = curPos + sizeof(float); TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r); - glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r); + if (This->isMultiTexture) { + glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r); + } else { + glTexCoord3f(s, t, r); + } break; default: @@ -535,8 +548,12 @@ void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) { float col[4]; /* Make appropriate texture active */ - glActiveTextureARB(GL_TEXTURE0_ARB + Stage); - checkGLcall("glActiveTextureARB"); + if (This->isMultiTexture) { + glActiveTextureARB(GL_TEXTURE0_ARB + Stage); + checkGLcall("glActiveTextureARB"); + } else if (Stage>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + } TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage); for (i=1; iTextureUnits; i++) { /* Note the D3DRS value applies to all textures, but GL has one per texture, so apply it now ready to be used! */ - checkGLcall("Activate texture.. to update const color"); - glActiveTextureARB(GL_TEXTURE0_ARB + i); + if (This->isMultiTexture) { + glActiveTextureARB(GL_TEXTURE0_ARB + i); + checkGLcall("Activate texture.. to update const color"); + } else if (i>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + } glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); @@ -2283,7 +2304,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D } /* Texture */ - for (j=0; j<8; j++) { + for (j=0; jTextureUnits; j++) { for (i=0; iSet.texture_state[j][i] && pSB->Changed.texture_state[j][i]) @@ -2304,7 +2325,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D } - for (j=0; j<8; i++) { + for (j=0; jTextureUnits; i++) { for (i=0; iSet.texture_state[j][SavedPixelStates_T[i]] && @@ -2321,7 +2342,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D } - for (j=0; j<8; i++) { + for (j=0; jTextureUnits; i++) { for (i=0; iSet.texture_state[j][SavedVertexStates_T[i]] && @@ -2457,7 +2478,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, } /* Texture */ - for (j=0; j<8; j++) { + for (j=0; jTextureUnits; j++) { for (i=0; iSet.texture_state[j][i] && (updateBlock->texture_state[j][i] != @@ -2522,7 +2543,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, for (i=0; iChanged.renderstate[SavedPixelStates_R[i]] = TRUE; } - for (j=0; j<8; i++) { + for (j=0; jTextureUnits; i++) { for (i=0; iChanged.texture_state[j][SavedPixelStates_T[i]] = TRUE; } @@ -2538,7 +2559,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, for (i=0; iChanged.renderstate[SavedVertexStates_R[i]] = TRUE; } - for (j=0; j<8; i++) { + for (j=0; jTextureUnits; i++) { for (i=0; iChanged.texture_state[j][SavedVertexStates_T[i]] = TRUE; } @@ -2592,8 +2613,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD } /* Make appropriate texture active */ - glActiveTextureARB(GL_TEXTURE0_ARB + Stage); - checkGLcall("glActiveTextureARB"); + if (This->isMultiTexture) { + glActiveTextureARB(GL_TEXTURE0_ARB + Stage); + checkGLcall("glActiveTextureARB"); + } else if (Stage>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + } /* Decrement the count of the previous texture */ /* FIXME PERF: If old == new and not dirty then skip all this */ @@ -2765,8 +2790,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa /* Make appropriate texture active */ TRACE("Activating appropriate texture state %ld\n", Stage); - glActiveTextureARB(GL_TEXTURE0_ARB + Stage); - checkGLcall("glActiveTextureARB"); + if (This->isMultiTexture) { + glActiveTextureARB(GL_TEXTURE0_ARB + Stage); + checkGLcall("glActiveTextureARB"); + } else if (Stage>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + } switch (Type) { @@ -3687,7 +3716,7 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALORDER, D3DORDER_LINEAR); /* Texture Stage States - Put directly into state block, we will call function below */ - for (i=0; i<8;i++) { + for (i=0; iTextureUnits;i++) { This->StateBlock.texture_state[i][D3DTSS_COLOROP ] = (i==0)? D3DTOP_MODULATE : D3DTOP_DISABLE; This->StateBlock.texture_state[i][D3DTSS_COLORARG1 ] = D3DTA_TEXTURE; This->StateBlock.texture_state[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT; @@ -3719,11 +3748,11 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { /* Under DirectX you can have texture stage operations even if no texture is bound, whereas opengl will only do texture operations when a valid texture is - bound. We emulate this by creating 8 dummy textures and binding them to each + bound. We emulate this by creating dummy textures and binding them to each texture stage, but disable all stages by default. Hence if a stage is enabled then the default texture will kick in until replaced by a SetTexture call */ - for (i=0; i<8; i++) { + for (i=0; iTextureUnits; i++) { GLubyte white = 255; /* Note this avoids calling settexture, so pretend it has been called */ @@ -3732,8 +3761,12 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { This->StateBlock.textures[i] = NULL; /* Make appropriate texture active */ - glActiveTextureARB(GL_TEXTURE0_ARB + i); - checkGLcall("glActiveTextureARB"); + if (This->isMultiTexture) { + glActiveTextureARB(GL_TEXTURE0_ARB + i); + checkGLcall("glActiveTextureARB"); + } else if (i>0) { + FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n"); + } /* Generate an opengl texture name */ glGenTextures(1, &This->dummyTextureName[i]); diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index 2018b328f62..8409d8246f9 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -343,8 +343,14 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps (LPDIRECT3D8 iface, pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x80000; pCaps->TextureOpCaps = 0xFFFFFFFF; - pCaps->MaxTextureBlendStages = 256; - pCaps->MaxSimultaneousTextures = 256; + + { + GLint gl_max_texture_units_arb; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max_texture_units_arb); + TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max_texture_units_arb); + pCaps->MaxTextureBlendStages = min(8, gl_max_texture_units_arb); + pCaps->MaxSimultaneousTextures = min(8, gl_max_texture_units_arb); + } pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_TEXGEN; @@ -538,8 +544,9 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); checkGLcall("glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);"); - /* Setup all the devices defaults */ - CreateStateBlock((LPDIRECT3DDEVICE8) object); + /* Initialize openGL extension related variables */ + object->isMultiTexture = FALSE; + object->TextureUnits = 1; /* Parse the gl supported features, in theory enabling parts of our code appropriately */ GL_Extensions = glGetString(GL_EXTENSIONS); @@ -551,13 +558,22 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, while (*GL_Extensions!=0x00) { const char *Start = GL_Extensions; char ThisExtn[256]; - + memset(ThisExtn, 0x00, sizeof(ThisExtn)); while (*GL_Extensions!=' ' && *GL_Extensions!=0x00) { - GL_Extensions++; + GL_Extensions++; } memcpy(ThisExtn, Start, (GL_Extensions-Start)); TRACE (" %s\n", ThisExtn); + + if (strcmp(ThisExtn, "GL_ARB_multitexture")==0) { + GLint gl_max_texture_units_arb; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max_texture_units_arb); + object->isMultiTexture = TRUE; + object->TextureUnits = min(8, gl_max_texture_units_arb); + TRACE("FOUND: Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max_texture_units_arb); + } + if (*GL_Extensions==' ') GL_Extensions++; } } @@ -571,10 +587,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, while (*GLX_Extensions!=0x00) { const char *Start = GLX_Extensions; char ThisExtn[256]; - + memset(ThisExtn, 0x00, sizeof(ThisExtn)); while (*GLX_Extensions!=' ' && *GLX_Extensions!=0x00) { - GLX_Extensions++; + GLX_Extensions++; } memcpy(ThisExtn, Start, (GLX_Extensions-Start)); TRACE (" %s\n", ThisExtn); @@ -582,13 +598,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, } } - LEAVE_GL(); + /* Setup all the devices defaults */ + CreateStateBlock((LPDIRECT3DDEVICE8) object); - { - GLint gl_max_texture_units_arb; - glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max_texture_units_arb); - TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max_texture_units_arb); - } + LEAVE_GL(); { /* Set a default viewport */ D3DVIEWPORT8 vp;