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/
--- 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) ;