Commit f89ea649 authored by Lionel Ulmer's avatar Lionel Ulmer Committed by Alexandre Julliard

- some fixes / optimisations in the color keying code

- minimize at the maximum texture uploads
parent cec93d0a
...@@ -1413,15 +1413,13 @@ GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface, ...@@ -1413,15 +1413,13 @@ GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
} else { } else {
IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2); IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
This->current_texture[dwStage] = tex_impl; This->current_texture[dwStage] = tex_impl;
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */ 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); 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_MAG_FILTER, glThis->render_state.mag);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glThis->render_state.min); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glThis->render_state.min);
} }
......
...@@ -61,10 +61,9 @@ snoop_texture(IDirectDrawSurfaceImpl *This) { ...@@ -61,10 +61,9 @@ snoop_texture(IDirectDrawSurfaceImpl *This) {
/******************************************************************************* /*******************************************************************************
* IDirectSurface callback methods * IDirectSurface callback methods
*/ */
static HRESULT HRESULT
gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { gltex_upload_texture(IDirectDrawSurfaceImpl *This) {
IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
GLuint current_texture;
#if 0 #if 0
static BOOL color_table_queried = FALSE; static BOOL color_table_queried = FALSE;
#endif #endif
...@@ -77,11 +76,15 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -77,11 +76,15 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc); 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, &current_texture);
glBindTexture(GL_TEXTURE_2D, glThis->tex_name); 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 :-) */ /* Texture snooping for the curious :-) */
snoop_texture(This); snoop_texture(This);
...@@ -272,15 +275,22 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -272,15 +275,22 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
dst = surface; dst = surface;
if (src_d->dwFlags & DDSD_CKSRCBLT) {
for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
WORD color = *src++; WORD color = *src++;
*dst = (color & 0x0FFF) << 4; *dst = (color & 0x0FFF) << 4;
if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) || if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0xF000) >> 12; *dst |= (color & 0xF000) >> 12;
dst++; 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; format = GL_RGBA;
pixel_format = GL_UNSIGNED_SHORT_4_4_4_4; pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
...@@ -294,15 +304,23 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -294,15 +304,23 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
dst = (WORD *) surface; dst = (WORD *) surface;
if (src_d->dwFlags & DDSD_CKSRCBLT) {
for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
WORD color = *src++; WORD color = *src++;
*dst = (color & 0x7FFF) << 1; *dst = (color & 0x7FFF) << 1;
if (((src_d->dwFlags & DDSD_CKSRCBLT) == 0) || if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0x8000) >> 15; *dst |= (color & 0x8000) >> 15;
dst++; 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; format = GL_RGBA;
pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
...@@ -367,13 +385,14 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -367,13 +385,14 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
(src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
(src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
(src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
if (src_d->dwFlags & DDSD_CKSRCBLT) {
/* Just add an alpha component and handle color-keying... */ /* Just add an alpha component and handle color-keying... */
DWORD i; DWORD i;
DWORD *src = (DWORD *) src_d->lpSurface, *dst; DWORD *src = (DWORD *) src_d->lpSurface, *dst;
surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
dst = (DWORD *) surface; dst = (DWORD *) surface;
if (src_d->dwFlags & DDSD_CKSRCBLT) {
for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
DWORD color = *src++; DWORD color = *src++;
*dst = color << 8; *dst = color << 8;
...@@ -382,6 +401,10 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -382,6 +401,10 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
*dst |= 0xFF; *dst |= 0xFF;
dst++; dst++;
} }
} else {
for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
*dst++ = (*src++ << 8) | 0xFF;
}
} }
format = GL_RGBA; format = GL_RGBA;
pixel_format = GL_UNSIGNED_INT_8_8_8_8; pixel_format = GL_UNSIGNED_INT_8_8_8_8;
...@@ -396,7 +419,7 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -396,7 +419,7 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
} }
if ((upload_done == FALSE) && (error == FALSE)) { if ((upload_done == FALSE) && (error == FALSE)) {
if (init_upload) if (glThis->initial_upload_done == FALSE) {
glTexImage2D(GL_TEXTURE_2D, glTexImage2D(GL_TEXTURE_2D,
This->mipmap_level, This->mipmap_level,
format, format,
...@@ -405,7 +428,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -405,7 +428,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
format, format,
pixel_format, pixel_format,
surface == NULL ? src_d->lpSurface : surface); surface == NULL ? src_d->lpSurface : surface);
else glThis->initial_upload_done = TRUE;
} else {
glTexSubImage2D(GL_TEXTURE_2D, glTexSubImage2D(GL_TEXTURE_2D,
This->mipmap_level, This->mipmap_level,
0, 0, 0, 0,
...@@ -413,6 +437,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -413,6 +437,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
format, format,
pixel_format, pixel_format,
surface == NULL ? src_d->lpSurface : surface); surface == NULL ? src_d->lpSurface : surface);
}
if (surface) HeapFree(GetProcessHeap(), 0, surface); if (surface) HeapFree(GetProcessHeap(), 0, surface);
} else if (error == TRUE) { } else if (error == TRUE) {
if (ERR_ON(ddraw)) { if (ERR_ON(ddraw)) {
...@@ -421,7 +447,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) { ...@@ -421,7 +447,8 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
} }
} }
glBindTexture(GL_TEXTURE_2D, current_texture); glThis->dirty_flag = FALSE;
return DD_OK; return DD_OK;
} }
...@@ -440,12 +467,8 @@ gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY c ...@@ -440,12 +467,8 @@ gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY c
{ {
IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
/* Basically, the only thing we have to do is to re-upload the texture */ glThis->dirty_flag = TRUE;
if (glThis->first_unlock == FALSE) {
ENTER_GL();
gltex_upload_texture(This, glThis->first_unlock);
LEAVE_GL();
}
return DD_OK; return DD_OK;
} }
...@@ -493,12 +516,8 @@ static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteIm ...@@ -493,12 +516,8 @@ static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteIm
/* First call the previous set_palette function */ /* First call the previous set_palette function */
glThis->set_palette(This, pal); glThis->set_palette(This, pal);
/* Then re-upload the texture to OpenGL only if the surface was already 'unlocked' once */ /* And set the dirty flag */
if (glThis->first_unlock == FALSE) { glThis->dirty_flag = TRUE;
ENTER_GL();
gltex_upload_texture(This, glThis->first_unlock);
LEAVE_GL();
}
} }
static void static void
...@@ -545,10 +564,9 @@ gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect) ...@@ -545,10 +564,9 @@ gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
glThis->unlock_update(This, pRect); glThis->unlock_update(This, pRect);
ENTER_GL(); /* Set the dirty flag according to the lock type */
gltex_upload_texture(This, glThis->first_unlock); if ((This->lastlocktype & DDLOCK_READONLY) == 0)
LEAVE_GL(); glThis->dirty_flag = TRUE;
glThis->first_unlock = FALSE;
} }
HRESULT WINAPI HRESULT WINAPI
...@@ -661,15 +679,8 @@ GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface, ...@@ -661,15 +679,8 @@ GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
/* If the GetHandle was not done, it is an error... */ /* If the GetHandle was not done, it is an error... */
if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n"); if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
ENTER_GL(); /* Set this texture as dirty */
glThis->dirty_flag = TRUE;
/* 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();
} }
} }
...@@ -823,10 +834,6 @@ HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOL ...@@ -823,10 +834,6 @@ HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOL
/* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL. /* 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). */ 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->final_release = gltex_final_release;
surf->lock_update = gltex_lock_update; surf->lock_update = gltex_lock_update;
surf->unlock_update = gltex_unlock_update; surf->unlock_update = gltex_unlock_update;
...@@ -844,13 +851,11 @@ HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOL ...@@ -844,13 +851,11 @@ HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOL
TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n", 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); 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(); LEAVE_GL();
/* And set the dirty flag accordingly */
private->dirty_flag = (at_creation == FALSE);
private->initial_upload_done = FALSE;
} }
return D3D_OK; return D3D_OK;
......
...@@ -86,16 +86,15 @@ void set_render_state(IDirect3DDeviceGLImpl* This, ...@@ -86,16 +86,15 @@ void set_render_state(IDirect3DDeviceGLImpl* This,
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
TRACE("disabling texturing\n"); TRACE("disabling texturing\n");
} else { } else {
IDirect3DTextureGLImpl *gl_tex = (IDirect3DTextureGLImpl *) tex->tex_private;
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
/* Default parameters */ /* 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 /* To prevent state change, we could test here what are the parameters
stored in the texture */ stored in the texture */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, rs->mag); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, rs->mag);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, rs->min); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, rs->min);
TRACE("setting OpenGL texture handle : %d\n", gl_tex->tex_name);
} }
} break; } break;
......
...@@ -102,7 +102,11 @@ typedef struct IDirect3DTextureGLImpl ...@@ -102,7 +102,11 @@ typedef struct IDirect3DTextureGLImpl
{ {
GLuint tex_name; GLuint tex_name;
BOOLEAN loaded; /* For the moment, this is here.. Should be part of surface management though */ 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 */ /* This is for now used to override 'standard' surface stuff to be as transparent as possible */
void (*final_release)(struct IDirectDrawSurfaceImpl *This); void (*final_release)(struct IDirectDrawSurfaceImpl *This);
void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags); void (*lock_update)(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags);
...@@ -157,6 +161,9 @@ extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context) ...@@ -157,6 +161,9 @@ extern HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
extern HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context) ; extern HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context) ;
extern HRESULT d3ddevice_find(IDirect3DImpl *d3d, LPD3DFINDDEVICESEARCH lpD3DDFS, LPD3DFINDDEVICERESULT lplpD3DDevice); 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 */ /* Common functions defined in d3dcommon.c */
void set_render_state(IDirect3DDeviceGLImpl* This, void set_render_state(IDirect3DDeviceGLImpl* This,
D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState); D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState);
......
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