Changelog: - some fixes / optimisations in the color keying code - minimize at the maximum texture uploads -- Lionel Ulmer - http://www.bbrox.org/
--- /home/ulmer/Wine/wine_base//dlls/ddraw/d3ddevice/mesa.c 2003-01-03 14:30:30.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3ddevice/mesa.c 2003-01-03 15:58:15.000000000 +0100 @@ -1413,15 +1413,13 @@ glDisable(GL_TEXTURE_2D); } else { IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2); - IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private; This->current_texture[dwStage] = tex_impl; IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */ - TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name); + gltex_upload_texture(tex_impl); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glThis->render_state.mag); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glThis->render_state.min); } --- /home/ulmer/Wine/wine_base//dlls/ddraw/d3dtexture.c 2003-01-03 14:30:30.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/d3dtexture.c 2003-01-03 15:59:29.000000000 +0100 @@ -61,10 +61,9 @@ /******************************************************************************* * IDirectSurface callback methods */ -static HRESULT -gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { +HRESULT +gltex_upload_texture(IDirectDrawSurfaceImpl *This) { IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; - GLuint current_texture; #if 0 static BOOL color_table_queried = FALSE; #endif @@ -77,11 +76,15 @@ DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc); - TRACE(" uploading texture to GL id %d (initial = %d).\n", glThis->tex_name, init_upload); - - glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); glBindTexture(GL_TEXTURE_2D, glThis->tex_name); + if (glThis->dirty_flag == FALSE) { + TRACE(" activating OpenGL texture id %d.\n", glThis->tex_name); + return DD_OK; + } else { + TRACE(" activating and uploading texture id %d (initial done = %d).\n", glThis->tex_name, glThis->initial_upload_done); + } + /* Texture snooping for the curious :-) */ snoop_texture(This); @@ -272,14 +275,21 @@ surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); dst = surface; - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - WORD color = *src++; - *dst = (color & 0x0FFF) << 4; - if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) || - (color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= (color & 0xF000) >> 12; - dst++; + if (src_d->dwFlags & DDSD_CKSRCBLT) { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + WORD color = *src++; + *dst = (color & 0x0FFF) << 4; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= (color & 0xF000) >> 12; + dst++; + } + } else { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + WORD color = *src++; + *dst++ = (((color & 0x0FFF) << 4) | + ((color & 0xF000) >> 12)); + } } format = GL_RGBA; @@ -294,14 +304,22 @@ surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); dst = (WORD *) surface; - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - WORD color = *src++; - *dst = (color & 0x7FFF) << 1; - if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) || - (color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= (color & 0x8000) >> 15; - dst++; + + if (src_d->dwFlags & DDSD_CKSRCBLT) { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + WORD color = *src++; + *dst = (color & 0x7FFF) << 1; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= (color & 0x8000) >> 15; + dst++; + } + } else { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + WORD color = *src++; + *dst++ = (((color & 0x7FFF) << 1) | + ((color & 0x8000) >> 15)); + } } format = GL_RGBA; @@ -367,13 +385,14 @@ (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* Just add an alpha component and handle color-keying... */ - DWORD i; - DWORD *src = (DWORD *) src_d->lpSurface, *dst; + /* Just add an alpha component and handle color-keying... */ + DWORD i; + DWORD *src = (DWORD *) src_d->lpSurface, *dst; - surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); - dst = (DWORD *) surface; + surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); + dst = (DWORD *) surface; + + if (src_d->dwFlags & DDSD_CKSRCBLT) { for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { DWORD color = *src++; *dst = color << 8; @@ -382,6 +401,10 @@ *dst |= 0xFF; dst++; } + } else { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + *dst++ = (*src++ << 8) | 0xFF; + } } format = GL_RGBA; pixel_format = GL_UNSIGNED_INT_8_8_8_8; @@ -396,7 +419,7 @@ } if ((upload_done == FALSE) && (error == FALSE)) { - if (init_upload) + if (glThis->initial_upload_done == FALSE) { glTexImage2D(GL_TEXTURE_2D, This->mipmap_level, format, @@ -405,7 +428,8 @@ format, pixel_format, surface == NULL ? src_d->lpSurface : surface); - else + glThis->initial_upload_done = TRUE; + } else { glTexSubImage2D(GL_TEXTURE_2D, This->mipmap_level, 0, 0, @@ -413,6 +437,8 @@ format, pixel_format, surface == NULL ? src_d->lpSurface : surface); + } + if (surface) HeapFree(GetProcessHeap(), 0, surface); } else if (error == TRUE) { if (ERR_ON(ddraw)) { @@ -421,7 +447,8 @@ } } - glBindTexture(GL_TEXTURE_2D, current_texture); + glThis->dirty_flag = FALSE; + return DD_OK; } @@ -440,12 +467,8 @@ { IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; - /* Basically, the only thing we have to do is to re-upload the texture */ - if (glThis->first_unlock == FALSE) { - ENTER_GL(); - gltex_upload_texture(This, glThis->first_unlock); - LEAVE_GL(); - } + glThis->dirty_flag = TRUE; + return DD_OK; } @@ -492,13 +515,9 @@ /* First call the previous set_palette function */ glThis->set_palette(This, pal); - - /* Then re-upload the texture to OpenGL only if the surface was already 'unlocked' once */ - if (glThis->first_unlock == FALSE) { - ENTER_GL(); - gltex_upload_texture(This, glThis->first_unlock); - LEAVE_GL(); - } + + /* And set the dirty flag */ + glThis->dirty_flag = TRUE; } static void @@ -545,10 +564,9 @@ glThis->unlock_update(This, pRect); - ENTER_GL(); - gltex_upload_texture(This, glThis->first_unlock); - LEAVE_GL(); - glThis->first_unlock = FALSE; + /* Set the dirty flag according to the lock type */ + if ((This->lastlocktype & DDLOCK_READONLY) == 0) + glThis->dirty_flag = TRUE; } HRESULT WINAPI @@ -661,15 +679,8 @@ /* If the GetHandle was not done, it is an error... */ if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n"); - ENTER_GL(); - - /* Now, load the texture */ - /* d3dd->set_context(d3dd); We need to set the context somehow.... */ - - ret_value = gltex_upload_texture(This, glThis->first_unlock); - glThis->first_unlock = FALSE; - - LEAVE_GL(); + /* Set this texture as dirty */ + glThis->dirty_flag = TRUE; } } @@ -823,10 +834,6 @@ /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL. Otherwise, it will be uploaded here (and may be invalid). */ - if (at_creation == TRUE) - private->first_unlock = TRUE; - else - private->first_unlock = FALSE; surf->final_release = gltex_final_release; surf->lock_update = gltex_lock_update; surf->unlock_update = gltex_unlock_update; @@ -844,13 +851,11 @@ 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); } - - if ((at_creation == FALSE) && - ((surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) == 0)) - { - gltex_upload_texture(surf, TRUE); - } LEAVE_GL(); + + /* And set the dirty flag accordingly */ + private->dirty_flag = (at_creation == FALSE); + private->initial_upload_done = FALSE; } return D3D_OK; --- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa.c 2003-01-03 14:30:30.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa.c 2003-01-03 15:58:28.000000000 +0100 @@ -86,16 +86,15 @@ glDisable(GL_TEXTURE_2D); TRACE("disabling texturing\n"); } else { - IDirect3DTextureGLImpl *gl_tex = (IDirect3DTextureGLImpl *) tex->tex_private; - glEnable(GL_TEXTURE_2D); + /* Default parameters */ - glBindTexture(GL_TEXTURE_2D, gl_tex->tex_name); + gltex_upload_texture(tex); + /* To prevent state change, we could test here what are the parameters stored in the texture */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, rs->mag); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, rs->min); - TRACE("setting OpenGL texture handle : %d\n", gl_tex->tex_name); } } break; --- /home/ulmer/Wine/wine_base//dlls/ddraw/mesa_private.h 2003-01-02 18:01:43.000000000 +0100 +++ /home/ulmer/Wine/wine_work//dlls/ddraw/mesa_private.h 2003-01-03 15:52:58.000000000 +0100 @@ -102,7 +102,11 @@ { GLuint tex_name; BOOLEAN loaded; /* For the moment, this is here.. Should be part of surface management though */ - BOOLEAN first_unlock; + + /* Texture upload management */ + BOOLEAN initial_upload_done; + BOOLEAN dirty_flag; + /* This is for now used to override 'standard' surface stuff to be as transparent as possible */ void (*final_release)(struct IDirectDrawSurfaceImpl *This); void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags); @@ -157,6 +161,9 @@ extern HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context) ; extern HRESULT d3ddevice_find(IDirect3DImpl *d3d, LPD3DFINDDEVICESEARCH lpD3DDFS, LPD3DFINDDEVICERESULT lplpD3DDevice); +/* Used to upload the texture */ +extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This) ; + /* Common functions defined in d3dcommon.c */ void set_render_state(IDirect3DDeviceGLImpl* This, D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState);