[D3D] Texturing fixes (again :-) )
Lionel Ulmer
lionel.ulmer at free.fr
Mon Jun 2 15:28:26 CDT 2003
This should optimize a bit the texture handling in the D3D code...
Basically, it prevents the most changes to the texturing parameters
possible.
Lionel
Changelog:
- some GL critical section fixes
- only bind textures at start of rendering
- optimized the texture parameter code
- optimize of the 'dirty checking code' for mipmapping
- handles the MAXMIPLEVEL texture parameter
--
Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
--- dlls/ddraw_CVS/d3ddevice/mesa.c Sun Jun 1 20:56:09 2003
+++ dlls/ddraw/d3ddevice/mesa.c Mon Jun 2 17:59:06 2003
@@ -56,13 +56,6 @@
{ 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
};
-#ifndef HAVE_GLEXT_PROTOTYPES
-/* This is for non-OpenGL ABI compliant glext.h headers :-) */
-typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
- GLsizei width, GLenum format, GLenum type,
- const GLvoid *table);
-#endif
-
const float id_mat[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
@@ -79,6 +72,8 @@
DWORD dwIndexCount,
DWORD dwFlags) ;
+static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
+
/* retrieve the X display to use on a given DC */
inline static Display *get_display( HDC hdc )
{
@@ -651,9 +646,7 @@
IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
if (mat != NULL) {
- ENTER_GL();
mat->activate(mat);
- LEAVE_GL();
} else {
ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
}
@@ -1084,9 +1077,6 @@
glThis->state = SURFACE_GL;
- /* Compute the number of active texture stages */
- while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
-
if (TRACE_ON(ddraw)) {
TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
}
@@ -1098,6 +1088,9 @@
if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
}
+ /* Compute the number of active texture stages and set the various texture parameters */
+ num_active_stages = draw_primitive_handle_textures(This);
+
draw_primitive_handle_GL_state(This,
(d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
vertex_lighted);
@@ -1433,70 +1426,6 @@
return DD_OK;
}
-static GLenum
-convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
-{
- GLenum gl_state;
-
- if (dwMipState == D3DTFP_NONE) {
- switch (dwMinState) {
- case D3DTFN_POINT: gl_state = GL_NEAREST; break;
- case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
- default: gl_state = GL_LINEAR; break;
- }
- } else if (dwMipState == D3DTFP_POINT) {
- switch (dwMinState) {
- case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
- case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
- default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
- }
- } else {
- switch (dwMinState) {
- case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
- case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
- default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
- }
- }
- return gl_state;
-}
-
-static GLenum
-convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
-{
- GLenum gl_state;
-
- switch (dwState) {
- case D3DTFG_POINT:
- gl_state = GL_NEAREST;
- break;
- case D3DTFG_LINEAR:
- gl_state = GL_LINEAR;
- break;
- default:
- gl_state = GL_LINEAR;
- break;
- }
- return gl_state;
-}
-
-static GLenum
-convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
-{
- GLenum gl_state;
- switch (dwState) {
- case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
- case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
- case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
-#if defined(GL_VERSION_1_4)
- case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
-#elif defined(GL_ARB_texture_mirrored_repeat)
- case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
-#endif
- default: gl_state = GL_REPEAT; break;
- }
- return gl_state;
-}
-
/* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
static BOOLEAN
handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
@@ -1650,10 +1579,6 @@
}
}
}
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
- This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
break;
case D3DTSS_MAGFILTER:
@@ -1664,14 +1589,11 @@
default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
}
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
break;
case D3DTSS_ADDRESS:
case D3DTSS_ADDRESSU:
case D3DTSS_ADDRESSV: {
- GLenum arg = convert_tex_address_to_GL(dwState);
-
switch ((D3DTEXTUREADDRESS) dwState) {
case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
@@ -1683,13 +1605,6 @@
#endif
default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
}
-
- if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
- (d3dTexStageStateType == D3DTSS_ADDRESSU))
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
- if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
- (d3dTexStageStateType == D3DTSS_ADDRESSV))
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
} break;
case D3DTSS_ALPHAOP:
@@ -1890,29 +1805,16 @@
} break;
case D3DTSS_MAXMIPLEVEL:
- if (dwState == 0) {
- TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
- } else {
- FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
- }
+ TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
break;
- case D3DTSS_BORDERCOLOR: {
- GLfloat color[4];
-
- color[0] = ((dwState >> 16) & 0xFF) / 255.0;
- color[1] = ((dwState >> 8) & 0xFF) / 255.0;
- color[2] = ((dwState >> 0) & 0xFF) / 255.0;
- color[3] = ((dwState >> 24) & 0xFF) / 255.0;
-
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
-
+ case D3DTSS_BORDERCOLOR:
TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
((dwState >> 16) & 0xFF),
((dwState >> 8) & 0xFF),
((dwState >> 0) & 0xFF),
((dwState >> 24) & 0xFF));
- } break;
+ break;
case D3DTSS_TEXCOORDINDEX: {
BOOLEAN handled = TRUE;
@@ -1976,6 +1878,48 @@
return DD_OK;
}
+static DWORD
+draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
+{
+ IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
+ DWORD stage;
+
+ for (stage = 0; stage < MAX_TEXTURES; stage++) {
+ IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
+
+ /* First check if we need to bind any other texture for this stage */
+ if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
+ if (This->current_texture[stage] == NULL) {
+ TRACE(" disabling 2D texturing for stage %ld.\n", stage);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+ } else {
+ GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
+
+ if (glThis->current_bound_texture[stage] == NULL) {
+ if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
+ glEnable(GL_TEXTURE_2D);
+ }
+ }
+ TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
+ glBindTexture(GL_TEXTURE_2D, tex_name);
+ }
+
+ glThis->current_bound_texture[stage] = This->current_texture[stage];
+ }
+
+ /* If no texure valid for this stage, go out of the loop */
+ if (This->current_texture[stage] == NULL) break;
+
+ /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
+ This will also update the various texture parameters if needed.
+ */
+ gltex_upload_texture(surf_ptr, This, stage);
+ }
+
+ return stage;
+}
+
HRESULT WINAPI
GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
DWORD dwStage,
@@ -1991,57 +1935,13 @@
IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
}
- ENTER_GL();
if (lpTexture2 == NULL) {
This->current_texture[dwStage] = NULL;
-
- TRACE(" disabling 2D texturing.\n");
- glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_TEXTURE_2D);
} else {
IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
- GLint max_mip_level;
- GLfloat color[4];
-
- IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
-
- if (This->current_texture[dwStage] == tex_impl) {
- /* No need to do anything as the texture did not change. */
- return DD_OK;
- }
+ IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
This->current_texture[dwStage] = tex_impl;
-
- if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
- /* Do not re-enable texturing if it was disabled due to the COLOROP code */
- glEnable(GL_TEXTURE_2D);
- TRACE(" enabling 2D texturing.\n");
- }
- gltex_upload_texture(tex_impl);
-
- if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
- max_mip_level = 0;
- } else {
- max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
- }
-
- /* Now we need to reset all glTexParameter calls for this particular texture... */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
- This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
- convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
- convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
- color[0] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
- color[1] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
- color[2] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
- color[3] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
}
- LEAVE_GL();
return DD_OK;
}
@@ -2074,6 +1974,7 @@
This->current_material = *lpMat;
+ ENTER_GL();
glMaterialfv(GL_FRONT_AND_BACK,
GL_DIFFUSE,
(float *) &(This->current_material.u.diffuse));
@@ -2089,6 +1990,7 @@
glMaterialf(GL_FRONT_AND_BACK,
GL_SHININESS,
This->current_material.u4.power); /* Not sure about this... */
+ LEAVE_GL();
return DD_OK;
}
@@ -2146,6 +2048,7 @@
if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
+ ENTER_GL();
if (bEnable) {
if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
/* Set the default parameters.. */
@@ -2164,6 +2067,7 @@
glDisable(GL_LIGHT0 + dwLightIndex);
This->active_lights &= ~(0x00000001 << dwLightIndex);
}
+ LEAVE_GL();
return DD_OK;
}
@@ -2623,7 +2527,8 @@
trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
-
+
+ ENTER_GL();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
@@ -2637,12 +2542,14 @@
glTranslatef(0.375, 0.375, 0);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(trans_mat);
+ LEAVE_GL();
}
void
d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
{
+ ENTER_GL();
if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((float *) view_mat);
@@ -2745,6 +2652,7 @@
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((float *) proj_mat);
}
+ LEAVE_GL();
}
void
@@ -2913,8 +2821,6 @@
RECT loc_rect;
IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog;
- GLuint initial_texture;
- GLint tex_state;
int x, y;
BOOLEAN initial = FALSE;
@@ -2928,7 +2834,9 @@
TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
+ /* This is a hack to prevent querying the current texture from GL */
+ gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
+
if (gl_d3d_dev->unlock_tex == 0) {
glGenTextures(1, &gl_d3d_dev->unlock_tex);
glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
@@ -2938,11 +2846,11 @@
} else {
glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
}
+
if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != D3D_OK) {
ERR(" unsupported pixel format at frame buffer flush.\n");
- glBindTexture(GL_TEXTURE_2D, initial_texture);
return;
}
@@ -2952,7 +2860,6 @@
glGetIntegerv(GL_CULL_FACE, &cull_face);
glGetIntegerv(GL_LIGHTING, &lighting);
glGetIntegerv(GL_BLEND, &blend);
- glGetIntegerv(GL_TEXTURE_2D, &tex_state);
glGetIntegerv(GL_FOG, &fog);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
glMatrixMode(GL_TEXTURE);
@@ -3013,8 +2920,6 @@
if (cull_face != 0) glEnable(GL_CULL_FACE);
if (blend != 0) glEnable(GL_BLEND);
if (fog != 0) glEnable(GL_FOG);
- glBindTexture(GL_TEXTURE_2D, initial_texture);
- if (tex_state == 0) glDisable(GL_TEXTURE_2D);
glDisable(GL_SCISSOR_TEST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
--- dlls/ddraw_CVS/d3dtexture.c Mon Jun 2 10:50:35 2003
+++ dlls/ddraw/d3dtexture.c Mon Jun 2 17:53:04 2003
@@ -89,23 +89,169 @@
FIXME("This is not supported yet... Expect some graphical glitches !!!\n");
- /* GL and memory are in sync again ... */
+ /* GL and memory are in sync again ...
+ No need to change the 'global' flag as it only handles the 'MEMORY_DIRTY' case.
+ */
gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
return DD_OK;
}
+static GLenum
+convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
+{
+ GLenum gl_state;
+
+ if (dwMipState == D3DTFP_NONE) {
+ switch (dwMinState) {
+ case D3DTFN_POINT: gl_state = GL_NEAREST; break;
+ case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
+ default: gl_state = GL_LINEAR; break;
+ }
+ } else if (dwMipState == D3DTFP_POINT) {
+ switch (dwMinState) {
+ case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
+ case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
+ default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
+ }
+ } else {
+ switch (dwMinState) {
+ case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
+ case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
+ default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
+ }
+ }
+ return gl_state;
+}
+
+static GLenum
+convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
+{
+ GLenum gl_state;
+
+ switch (dwState) {
+ case D3DTFG_POINT:
+ gl_state = GL_NEAREST;
+ break;
+ case D3DTFG_LINEAR:
+ gl_state = GL_LINEAR;
+ break;
+ default:
+ gl_state = GL_LINEAR;
+ break;
+ }
+ return gl_state;
+}
+
+static GLenum
+convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
+{
+ GLenum gl_state;
+ switch (dwState) {
+ case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
+ case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
+ case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
+#if defined(GL_VERSION_1_4)
+ case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
+#elif defined(GL_ARB_texture_mirrored_repeat)
+ case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
+#endif
+ default: gl_state = GL_REPEAT; break;
+ }
+ return gl_state;
+}
+
HRESULT
-gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr) {
+gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr, IDirect3DDeviceImpl *d3ddev, DWORD stage) {
IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
- GLuint tex_name = gl_surf_ptr->tex_name;
+ BOOLEAN changed = FALSE;
- TRACE(" activating OpenGL texture id %d.\n", tex_name);
- glBindTexture(GL_TEXTURE_2D, tex_name);
-
if (surf_ptr->mipmap_level != 0) {
WARN(" application activating a sub-level of the mipmapping chain (level %d) !\n", surf_ptr->mipmap_level);
}
+
+ /* Now check if the texture parameters for this texture are still in-line with what D3D expect
+ us to do..
+
+ NOTE: there is no check for the situation where the same texture is bound to multiple stage
+ but with different parameters per stage.
+ */
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_MAXMIPLEVEL - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1])) {
+ DWORD max_mip_level;
+
+ if ((surf_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
+ max_mip_level = 0;
+ } else {
+ max_mip_level = surf_ptr->surface_desc.u2.dwMipMapCount - 1;
+ if (d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] != 0) {
+ if (max_mip_level >= d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1]) {
+ max_mip_level = d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] - 1;
+ }
+ }
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
+ changed = TRUE;
+ }
+
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_MAGFILTER - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1])) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ convert_mag_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1]));
+ changed = TRUE;
+ }
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_MINFILTER - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1]) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_MIPFILTER - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1])) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ convert_min_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1],
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1]));
+ changed = TRUE;
+ }
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSU - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1])) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
+ convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]));
+ changed = TRUE;
+ }
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSV - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1])) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
+ convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1]));
+ changed = TRUE;
+ }
+ if ((gl_surf_ptr->tex_parameters == NULL) ||
+ (gl_surf_ptr->tex_parameters[D3DTSS_BORDERCOLOR - D3DTSS_ADDRESSU] !=
+ d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1])) {
+ GLfloat color[4];
+
+ color[0] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
+ color[1] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
+ color[2] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
+ color[3] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
+ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
+ changed = TRUE;
+ }
+
+ if (changed == TRUE) {
+ if (gl_surf_ptr->tex_parameters == NULL) {
+ gl_surf_ptr->tex_parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
+ }
+ memcpy(gl_surf_ptr->tex_parameters, &(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]),
+ sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
+ }
+
+ if (*(gl_surf_ptr->global_dirty_flag) != SURFACE_MEMORY_DIRTY) {
+ TRACE(" nothing to do - memory copy and GL state in synch for all texture levels.\n");
+ return DD_OK;
+ }
while (surf_ptr != NULL) {
IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
@@ -133,7 +279,9 @@
surf_ptr = NULL;
}
}
-
+
+ *(gl_surf_ptr->global_dirty_flag) = SURFACE_MEMORY;
+
return DD_OK;
}
@@ -164,6 +312,7 @@
}
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
+ *(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
/* TODO: check color-keying on mipmapped surfaces... */
return DD_OK;
@@ -277,6 +426,7 @@
glBindTexture(GL_TEXTURE_2D, cur_tex);
LEAVE_GL();
+ /* The SURFACE_GL case is not handled by the 'global' dirty flag */
gl_surf_ptr->dirty_flag = SURFACE_GL;
return DD_OK;
@@ -353,6 +503,7 @@
/* And set the dirty flag */
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
+ *(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
/* TODO: check palette on mipmapped surfaces...
TODO: do we need to re-upload in case of usage of the paletted texture extension ? */
@@ -408,8 +559,10 @@
glThis->unlock_update(This, pRect);
/* Set the dirty flag according to the lock type */
- if ((This->lastlocktype & DDLOCK_READONLY) == 0)
+ if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
+ *(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
+ }
}
HRESULT WINAPI
@@ -499,6 +652,7 @@
/* Set this texture as dirty */
gl_dst_ptr->dirty_flag = SURFACE_MEMORY_DIRTY;
+ *(gl_dst_ptr->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
}
}
@@ -682,16 +836,19 @@
to save those... */
surf->aux_blt = gltex_blt;
surf->aux_bltfast = gltex_bltfast;
-
+
ENTER_GL();
if (surf->mipmap_level == 0) {
glGenTextures(1, &(private->tex_name));
if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
+ private->__global_dirty_flag = (at_creation == FALSE ? SURFACE_MEMORY_DIRTY : SURFACE_MEMORY);
+ private->global_dirty_flag = &(private->__global_dirty_flag);
} else {
private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
surf, private, private->tex_name, main, main->tex_private);
+ private->global_dirty_flag = &(((IDirect3DTextureGLImpl *) (main->tex_private))->__global_dirty_flag);
}
LEAVE_GL();
--- dlls/ddraw_CVS/mesa_private.h Sun Jun 1 20:56:09 2003
+++ dlls/ddraw/mesa_private.h Mon Jun 2 16:15:02 2003
@@ -68,6 +68,18 @@
BOOLEAN initial_upload_done;
SURFACE_STATE dirty_flag;
+ /* This is used to optimize dirty checking in case of mipmapping.
+ Note that a bitmap could have been used but it was not worth the pain as it will be very rare
+ to have only one mipmap level change...
+
+ The __global_dirty_flag will only be set for the main mipmap level.
+ */
+ SURFACE_STATE __global_dirty_flag;
+ SURFACE_STATE *global_dirty_flag;
+
+ /* This is to optimize the 'per-texture' parameters. */
+ DWORD *tex_parameters;
+
/* Surface optimization */
void *surface_ptr;
@@ -94,6 +106,9 @@
GLXContext gl_context;
+ /* This stores the textures which are actually bound to the GL context */
+ IDirectDrawSurfaceImpl *current_bound_texture[MAX_TEXTURES];
+
/* The last type of vertex drawn */
GL_TRANSFORM_STATE transform_state;
@@ -139,7 +154,7 @@
extern HRESULT d3ddevice_find(IDirectDrawImpl *d3d, LPD3DFINDDEVICESEARCH lpD3DDFS, LPD3DFINDDEVICERESULT lplpD3DDevice);
/* Used to upload the texture */
-extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This) ;
+extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This, IDirect3DDeviceImpl *d3ddev, DWORD stage) ;
/* Used to set-up our orthographic projection */
extern void d3ddevice_set_ortho(IDirect3DDeviceImpl *This) ;
More information about the wine-patches
mailing list