Commit 13ee7cd1 authored by Jason Edmeades's avatar Jason Edmeades Committed by Alexandre Julliard

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.
parent 4feb257e
...@@ -314,6 +314,10 @@ struct IDirect3DDevice8Impl ...@@ -314,6 +314,10 @@ struct IDirect3DDevice8Impl
Display *display; Display *display;
Window win; Window win;
/* OpenGL Extension related */
BOOL isMultiTexture;
UINT TextureUnits;
UINT dummyTextureName[8]; UINT dummyTextureName[8];
}; };
......
...@@ -177,7 +177,7 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, ...@@ -177,7 +177,7 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
} else { } else {
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
checkGLcall("glMatrixMode"); checkGLcall("glMatrixMode");
glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_PROJECTION].u.m[0][0]); glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_PROJECTION].u.m[0][0]);
checkGLcall("glLoadMatrixf"); checkGLcall("glLoadMatrixf");
...@@ -301,6 +301,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, ...@@ -301,6 +301,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
float s,t,r,q; 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 */ /* Query tex coords */
if (This->StateBlock.textures[textureNo] != NULL) { if (This->StateBlock.textures[textureNo] != NULL) {
switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) { switch (IDirect3DBaseTexture8Impl_GetType((LPDIRECT3DBASETEXTURE8) This->StateBlock.textures[textureNo])) {
...@@ -310,7 +315,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, ...@@ -310,7 +315,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
t = *(float *)curPos; t = *(float *)curPos;
curPos = curPos + sizeof(float); curPos = curPos + sizeof(float);
TRACE("tex:%d, s,t=%f,%f\n", textureNo, s,t); 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; break;
case D3DRTYPE_VOLUMETEXTURE: case D3DRTYPE_VOLUMETEXTURE:
...@@ -321,7 +330,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface, ...@@ -321,7 +330,11 @@ void DrawPrimitiveI(LPDIRECT3DDEVICE8 iface,
r = *(float *)curPos; r = *(float *)curPos;
curPos = curPos + sizeof(float); curPos = curPos + sizeof(float);
TRACE("tex:%d, s,t,r=%f,%f,%f\n", textureNo, s,t,r); 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; break;
default: default:
...@@ -535,8 +548,12 @@ void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) { ...@@ -535,8 +548,12 @@ void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
float col[4]; float col[4];
/* Make appropriate texture active */ /* Make appropriate texture active */
glActiveTextureARB(GL_TEXTURE0_ARB + Stage); if (This->isMultiTexture) {
checkGLcall("glActiveTextureARB"); 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); TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
for (i=1; i<HIGHEST_TEXTURE_STATE; i++) { for (i=1; i<HIGHEST_TEXTURE_STATE; i++) {
...@@ -1901,12 +1918,16 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3 ...@@ -1901,12 +1918,16 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3
checkGLcall("glBlendColor"); checkGLcall("glBlendColor");
/* And now the default texture color as well */ /* And now the default texture color as well */
for (i=0; i<8; i++) { for (i=0; i<This->TextureUnits; i++) {
/* Note the D3DRS value applies to all textures, but GL has one /* Note the D3DRS value applies to all textures, but GL has one
per texture, so apply it now ready to be used! */ per texture, so apply it now ready to be used! */
checkGLcall("Activate texture.. to update const color"); if (This->isMultiTexture) {
glActiveTextureARB(GL_TEXTURE0_ARB + i); 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]); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
...@@ -2283,7 +2304,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D ...@@ -2283,7 +2304,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D
} }
/* Texture */ /* Texture */
for (j=0; j<8; j++) { for (j=0; j<This->TextureUnits; j++) {
for (i=0; i<HIGHEST_TEXTURE_STATE; i++) { for (i=0; i<HIGHEST_TEXTURE_STATE; i++) {
if (pSB->Set.texture_state[j][i] && pSB->Changed.texture_state[j][i]) if (pSB->Set.texture_state[j][i] && pSB->Changed.texture_state[j][i])
...@@ -2304,7 +2325,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D ...@@ -2304,7 +2325,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D
} }
for (j=0; j<8; i++) { for (j=0; j<This->TextureUnits; i++) {
for (i=0; i<NUM_SAVEDPIXELSTATES_T; i++) { for (i=0; i<NUM_SAVEDPIXELSTATES_T; i++) {
if (pSB->Set.texture_state[j][SavedPixelStates_T[i]] && if (pSB->Set.texture_state[j][SavedPixelStates_T[i]] &&
...@@ -2321,7 +2342,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D ...@@ -2321,7 +2342,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, D
} }
for (j=0; j<8; i++) { for (j=0; j<This->TextureUnits; i++) {
for (i=0; i<NUM_SAVEDVERTEXSTATES_T; i++) { for (i=0; i<NUM_SAVEDVERTEXSTATES_T; i++) {
if (pSB->Set.texture_state[j][SavedVertexStates_T[i]] && if (pSB->Set.texture_state[j][SavedVertexStates_T[i]] &&
...@@ -2457,7 +2478,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, ...@@ -2457,7 +2478,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface,
} }
/* Texture */ /* Texture */
for (j=0; j<8; j++) { for (j=0; j<This->TextureUnits; j++) {
for (i=0; i<HIGHEST_TEXTURE_STATE; i++) { for (i=0; i<HIGHEST_TEXTURE_STATE; i++) {
if (updateBlock->Set.texture_state[j][i] && (updateBlock->texture_state[j][i] != if (updateBlock->Set.texture_state[j][i] && (updateBlock->texture_state[j][i] !=
...@@ -2522,7 +2543,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, ...@@ -2522,7 +2543,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface,
for (i=0; i<NUM_SAVEDPIXELSTATES_R; i++) { for (i=0; i<NUM_SAVEDPIXELSTATES_R; i++) {
s->Changed.renderstate[SavedPixelStates_R[i]] = TRUE; s->Changed.renderstate[SavedPixelStates_R[i]] = TRUE;
} }
for (j=0; j<8; i++) { for (j=0; j<This->TextureUnits; i++) {
for (i=0; i<NUM_SAVEDPIXELSTATES_T; i++) { for (i=0; i<NUM_SAVEDPIXELSTATES_T; i++) {
s->Changed.texture_state[j][SavedPixelStates_T[i]] = TRUE; s->Changed.texture_state[j][SavedPixelStates_T[i]] = TRUE;
} }
...@@ -2538,7 +2559,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, ...@@ -2538,7 +2559,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface,
for (i=0; i<NUM_SAVEDVERTEXSTATES_R; i++) { for (i=0; i<NUM_SAVEDVERTEXSTATES_R; i++) {
s->Changed.renderstate[SavedVertexStates_R[i]] = TRUE; s->Changed.renderstate[SavedVertexStates_R[i]] = TRUE;
} }
for (j=0; j<8; i++) { for (j=0; j<This->TextureUnits; i++) {
for (i=0; i<NUM_SAVEDVERTEXSTATES_T; i++) { for (i=0; i<NUM_SAVEDVERTEXSTATES_T; i++) {
s->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE; s->Changed.texture_state[j][SavedVertexStates_T[i]] = TRUE;
} }
...@@ -2592,8 +2613,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD ...@@ -2592,8 +2613,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD
} }
/* Make appropriate texture active */ /* Make appropriate texture active */
glActiveTextureARB(GL_TEXTURE0_ARB + Stage); if (This->isMultiTexture) {
checkGLcall("glActiveTextureARB"); 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 */ /* Decrement the count of the previous texture */
/* FIXME PERF: If old == new and not dirty then skip all this */ /* FIXME PERF: If old == new and not dirty then skip all this */
...@@ -2765,8 +2790,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa ...@@ -2765,8 +2790,12 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa
/* Make appropriate texture active */ /* Make appropriate texture active */
TRACE("Activating appropriate texture state %ld\n", Stage); TRACE("Activating appropriate texture state %ld\n", Stage);
glActiveTextureARB(GL_TEXTURE0_ARB + Stage); if (This->isMultiTexture) {
checkGLcall("glActiveTextureARB"); 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) { switch (Type) {
...@@ -3687,7 +3716,7 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { ...@@ -3687,7 +3716,7 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) {
IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALORDER, D3DORDER_LINEAR); IDirect3DDevice8Impl_SetRenderState(iface, D3DRS_NORMALORDER, D3DORDER_LINEAR);
/* Texture Stage States - Put directly into state block, we will call function below */ /* Texture Stage States - Put directly into state block, we will call function below */
for (i=0; i<8;i++) { for (i=0; i<This->TextureUnits;i++) {
This->StateBlock.texture_state[i][D3DTSS_COLOROP ] = (i==0)? D3DTOP_MODULATE : D3DTOP_DISABLE; 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_COLORARG1 ] = D3DTA_TEXTURE;
This->StateBlock.texture_state[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT; This->StateBlock.texture_state[i][D3DTSS_COLORARG2 ] = D3DTA_CURRENT;
...@@ -3719,11 +3748,11 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { ...@@ -3719,11 +3748,11 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) {
/* Under DirectX you can have texture stage operations even if no texture is /* 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, 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 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 */ then the default texture will kick in until replaced by a SetTexture call */
for (i=0; i<8; i++) { for (i=0; i<This->TextureUnits; i++) {
GLubyte white = 255; GLubyte white = 255;
/* Note this avoids calling settexture, so pretend it has been called */ /* Note this avoids calling settexture, so pretend it has been called */
...@@ -3732,8 +3761,12 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) { ...@@ -3732,8 +3761,12 @@ void CreateStateBlock(LPDIRECT3DDEVICE8 iface) {
This->StateBlock.textures[i] = NULL; This->StateBlock.textures[i] = NULL;
/* Make appropriate texture active */ /* Make appropriate texture active */
glActiveTextureARB(GL_TEXTURE0_ARB + i); if (This->isMultiTexture) {
checkGLcall("glActiveTextureARB"); 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 */ /* Generate an opengl texture name */
glGenTextures(1, &This->dummyTextureName[i]); glGenTextures(1, &This->dummyTextureName[i]);
......
...@@ -343,8 +343,14 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps (LPDIRECT3D8 iface, ...@@ -343,8 +343,14 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps (LPDIRECT3D8 iface,
pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x80000; pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x80000;
pCaps->TextureOpCaps = 0xFFFFFFFF; 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; pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_TEXGEN;
...@@ -538,8 +544,9 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, ...@@ -538,8 +544,9 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
checkGLcall("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 */ /* Initialize openGL extension related variables */
CreateStateBlock((LPDIRECT3DDEVICE8) object); object->isMultiTexture = FALSE;
object->TextureUnits = 1;
/* Parse the gl supported features, in theory enabling parts of our code appropriately */ /* Parse the gl supported features, in theory enabling parts of our code appropriately */
GL_Extensions = glGetString(GL_EXTENSIONS); GL_Extensions = glGetString(GL_EXTENSIONS);
...@@ -551,13 +558,22 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, ...@@ -551,13 +558,22 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
while (*GL_Extensions!=0x00) { while (*GL_Extensions!=0x00) {
const char *Start = GL_Extensions; const char *Start = GL_Extensions;
char ThisExtn[256]; char ThisExtn[256];
memset(ThisExtn, 0x00, sizeof(ThisExtn)); memset(ThisExtn, 0x00, sizeof(ThisExtn));
while (*GL_Extensions!=' ' && *GL_Extensions!=0x00) { while (*GL_Extensions!=' ' && *GL_Extensions!=0x00) {
GL_Extensions++; GL_Extensions++;
} }
memcpy(ThisExtn, Start, (GL_Extensions-Start)); memcpy(ThisExtn, Start, (GL_Extensions-Start));
TRACE (" %s\n", ThisExtn); 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++; if (*GL_Extensions==' ') GL_Extensions++;
} }
} }
...@@ -571,10 +587,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, ...@@ -571,10 +587,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
while (*GLX_Extensions!=0x00) { while (*GLX_Extensions!=0x00) {
const char *Start = GLX_Extensions; const char *Start = GLX_Extensions;
char ThisExtn[256]; char ThisExtn[256];
memset(ThisExtn, 0x00, sizeof(ThisExtn)); memset(ThisExtn, 0x00, sizeof(ThisExtn));
while (*GLX_Extensions!=' ' && *GLX_Extensions!=0x00) { while (*GLX_Extensions!=' ' && *GLX_Extensions!=0x00) {
GLX_Extensions++; GLX_Extensions++;
} }
memcpy(ThisExtn, Start, (GLX_Extensions-Start)); memcpy(ThisExtn, Start, (GLX_Extensions-Start));
TRACE (" %s\n", ThisExtn); TRACE (" %s\n", ThisExtn);
...@@ -582,13 +598,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface, ...@@ -582,13 +598,10 @@ HRESULT WINAPI IDirect3D8Impl_CreateDevice (LPDIRECT3D8 iface,
} }
} }
LEAVE_GL(); /* Setup all the devices defaults */
CreateStateBlock((LPDIRECT3DDEVICE8) object);
{ LEAVE_GL();
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);
}
{ /* Set a default viewport */ { /* Set a default viewport */
D3DVIEWPORT8 vp; D3DVIEWPORT8 vp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment