Hi all, See the changelog :-) Changelog: - added mipmapping support - added locking for concurrent access to the D3D device - improved tracing - added support for most texture combine stages (inspired by the D3D8 code) - disable current lock / unlock code pending proper solution -- Lionel Ulmer - http://www.bbrox.org/
Index: dlls/ddraw/d3d_private.h =================================================================== RCS file: /home/wine/wine/dlls/ddraw/d3d_private.h,v retrieving revision 1.29 diff -u -r1.29 d3d_private.h --- dlls/ddraw/d3d_private.h 12 Feb 2003 21:40:25 -0000 1.29 +++ dlls/ddraw/d3d_private.h 9 May 2003 18:58:06 -0000 @@ -246,6 +246,9 @@ D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat); STATEBLOCK state_block; + + /* Used to prevent locks and rendering to overlap */ + CRITICAL_SECTION crit; }; /***************************************************************************** Index: dlls/ddraw/d3dtexture.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/d3dtexture.c,v retrieving revision 1.43 diff -u -r1.43 d3dtexture.c --- dlls/ddraw/d3dtexture.c 8 May 2003 21:03:57 -0000 1.43 +++ dlls/ddraw/d3dtexture.c 9 May 2003 18:58:07 -0000 @@ -49,7 +49,7 @@ char buf[128]; FILE *f; - sprintf(buf, "tex_%05d.pnm", glThis->tex_name); + sprintf(buf, "tex_%05d_%02d.pnm", glThis->tex_name, This->mipmap_level); f = fopen(buf, "wb"); DDRAW_dump_surface_to_disk(This, f); } @@ -60,6 +60,25 @@ #endif +static IDirectDrawSurfaceImpl * +get_sub_mimaplevel(IDirectDrawSurfaceImpl *tex_ptr) +{ + /* Now go down the mipmap chain to the next surface */ + static const DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 }; + LPDIRECTDRAWSURFACE7 next_level; + IDirectDrawSurfaceImpl *surf_ptr; + HRESULT hr; + + hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(tex_ptr, IDirectDrawSurface7), + (DDSCAPS2 *) &mipmap_caps, &next_level); + if (FAILED(hr)) return NULL; + + surf_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, next_level); + IDirectDrawSurface7_Release(next_level); + + return surf_ptr; +} + /******************************************************************************* * IDirectSurface callback methods */ @@ -69,416 +88,435 @@ #if 0 static BOOL color_table_queried = FALSE; #endif - void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat, - GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL; - BOOL upload_done = FALSE; - BOOL error = FALSE; - GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */ - VOID *surface = NULL; - - DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc); - - 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); + static void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat, + GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL; + IDirectDrawSurfaceImpl *surf_ptr; + GLuint tex_name = glThis->tex_name; - if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { - /* **************** - Paletted Texture - **************** */ - IDirectDrawPaletteImpl* pal = This->palette; - BYTE table[256][4]; - int i; + TRACE(" activating OpenGL texture id %d.\n", tex_name); + glBindTexture(GL_TEXTURE_2D, tex_name); -#if 0 - if (color_table_queried == FALSE) { - ptr_ColorTableEXT = - ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT; - } -#endif + if (This->mipmap_level != 0) { + WARN(" application activating a sub-level of the mipmapping chain (level %d) !\n", This->mipmap_level); + } + + surf_ptr = This; + while (surf_ptr != NULL) { + GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */ + VOID *surface = NULL; + DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(surf_ptr->surface_desc); + IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private; + BOOL upload_done = FALSE; + BOOL error = FALSE; - if (pal == NULL) { - /* Upload a black texture. The real one will be uploaded on palette change */ - WARN("Palettized texture Loading with a NULL palette !\n"); - memset(table, 0, 256 * 4); + if (gl_surf_ptr->dirty_flag == FALSE) { + TRACE(" - level %d already uploaded.\n", surf_ptr->mipmap_level); } else { - /* Get the surface's palette */ - for (i = 0; i < 256; i++) { - table[i][0] = pal->palents[i].peRed; - table[i][1] = pal->palents[i].peGreen; - table[i][2] = pal->palents[i].peBlue; - if ((src_d->dwFlags & DDSD_CKSRCBLT) && - (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) && - (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - /* We should maybe here put a more 'neutral' color than the standard bright purple - one often used by application to prevent the nice purple borders when bi-linear - filtering is on */ - table[i][3] = 0x00; - else - table[i][3] = 0xFF; - } - } + TRACE(" - uploading texture level %d (initial done = %d).\n", + surf_ptr->mipmap_level, gl_surf_ptr->initial_upload_done); - if (ptr_ColorTableEXT != NULL) { - /* use Paletted Texture Extension */ - ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */ - GL_RGBA, /* internal format */ - 256, /* table size */ - GL_RGBA, /* table format */ - GL_UNSIGNED_BYTE, /* table type */ - table); /* the color table */ - - glTexImage2D(GL_TEXTURE_2D, /* target */ - This->mipmap_level, /* level */ - GL_COLOR_INDEX8_EXT, /* internal format */ - src_d->dwWidth, src_d->dwHeight, /* width, height */ - 0, /* border */ - GL_COLOR_INDEX, /* texture format */ - GL_UNSIGNED_BYTE, /* texture type */ - src_d->lpSurface); /* the texture */ - - upload_done = TRUE; - } else { - DWORD i; - BYTE *src = (BYTE *) src_d->lpSurface, *dst; - - surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); - dst = (BYTE *) surface; - - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - BYTE color = *src++; - *dst++ = table[color][0]; - *dst++ = table[color][1]; - *dst++ = table[color][2]; - *dst++ = table[color][3]; - } - - format = GL_RGBA; - pixel_format = GL_UNSIGNED_BYTE; - } - } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) { - /* ************ - RGB Textures - ************ */ - if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) { - if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xE0) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x1C) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x03)) { - /* ********************** - GL_UNSIGNED_BYTE_3_3_2 - ********************** */ - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* This texture format will never be used.. So do not care about color keying - up until the point in time it will be needed :-) */ - error = TRUE; - } else { - format = GL_RGB; - pixel_format = GL_UNSIGNED_BYTE_3_3_2; - } - } else { - error = TRUE; - } - } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) { - if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07E0) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) { - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* Converting the 565 format in 5551 packed to emulate color-keying. - - Note : in all these conversion, it would be best to average the averaging - pixels to get the color of the pixel that will be color-keyed to - prevent 'color bleeding'. This will be done later on if ever it is - too visible. - - Note2: when using color-keying + alpha, are the alpha bits part of the - color-space or not ? - */ - DWORD i; - WORD *src = (WORD *) src_d->lpSurface, *dst; - - 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 & 0xFFC0) | ((color & 0x1F) << 1)); - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= 0x0001; - dst++; - } + /* Texture snooping for the curious :-) */ + snoop_texture(surf_ptr); + + if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { + /* **************** + Paletted Texture + **************** */ + IDirectDrawPaletteImpl* pal = surf_ptr->palette; + BYTE table[256][4]; + int i; - format = GL_RGBA; - pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; - } else { - format = GL_RGB; - pixel_format = GL_UNSIGNED_SHORT_5_6_5; - } - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07C0) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x003E) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0001)) { - format = GL_RGBA; - pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* Change the alpha value of the color-keyed pixels to emulate color-keying. */ - DWORD i; - WORD *src = (WORD *) src_d->lpSurface, *dst; - - 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 & 0xFFFE; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= color & 0x0001; - dst++; - } - } - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF000) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0F00) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x00F0) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000F)) { - format = GL_RGBA; - pixel_format = GL_UNSIGNED_SHORT_4_4_4_4; - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* Change the alpha value of the color-keyed pixels to emulate color-keying. */ - DWORD i; - WORD *src = (WORD *) src_d->lpSurface, *dst; - - 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 & 0xFFF0; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= color & 0x000F; - dst++; - } +#if 0 + if (color_table_queried == FALSE) { + ptr_ColorTableEXT = + ((Mesa_DeviceCapabilities *) ((x11_dd_private *) surf_ptr->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT; } - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x0F00) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00F0) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000F) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xF000)) { - /* Move the four Alpha bits... */ - DWORD i; - WORD *src = (WORD *) src_d->lpSurface, *dst; - - surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); - dst = surface; +#endif - 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++; - } + if (pal == NULL) { + /* Upload a black texture. The real one will be uploaded on palette change */ + WARN("Palettized texture Loading with a NULL palette !\n"); + memset(table, 0, 256 * 4); } else { - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - WORD color = *src++; - *dst++ = (((color & 0x0FFF) << 4) | - ((color & 0xF000) >> 12)); + /* Get the surface's palette */ + for (i = 0; i < 256; i++) { + table[i][0] = pal->palents[i].peRed; + table[i][1] = pal->palents[i].peGreen; + table[i][2] = pal->palents[i].peBlue; + if ((src_d->dwFlags & DDSD_CKSRCBLT) && + (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) && + (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + /* We should maybe here put a more 'neutral' color than the standard bright purple + one often used by application to prevent the nice purple borders when bi-linear + filtering is on */ + table[i][3] = 0x00; + else + table[i][3] = 0xFF; } } - format = GL_RGBA; - pixel_format = GL_UNSIGNED_SHORT_4_4_4_4; - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x7C00) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x03E0) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x8000)) { - /* Converting the 1555 format in 5551 packed */ - DWORD i; - WORD *src = (WORD *) src_d->lpSurface, *dst; - - surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); - dst = (WORD *) surface; - - 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++; - } + if (ptr_ColorTableEXT != NULL) { + /* use Paletted Texture Extension */ + ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */ + GL_RGBA, /* internal format */ + 256, /* table size */ + GL_RGBA, /* table format */ + GL_UNSIGNED_BYTE, /* table type */ + table); /* the color table */ + + glTexImage2D(GL_TEXTURE_2D, /* target */ + surf_ptr->mipmap_level, /* level */ + GL_COLOR_INDEX8_EXT, /* internal format */ + src_d->dwWidth, src_d->dwHeight, /* width, height */ + 0, /* border */ + GL_COLOR_INDEX, /* texture format */ + GL_UNSIGNED_BYTE, /* texture type */ + src_d->lpSurface); /* the texture */ + + upload_done = TRUE; } 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; - pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; - } else { - error = TRUE; - } - } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) { - if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* This is a pain :-) */ DWORD i; - BYTE *src = (BYTE *) src_d->lpSurface; - DWORD *dst; + BYTE *src = (BYTE *) src_d->lpSurface, *dst; + + surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); + dst = (BYTE *) surface; - surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); - dst = (DWORD *) surface; for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - DWORD color = *((DWORD *) src) & 0x00FFFFFF; - src += 3; - *dst = *src++ << 8; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= 0xFF; - dst++; + BYTE color = *src++; + *dst++ = table[color][0]; + *dst++ = table[color][1]; + *dst++ = table[color][2]; + *dst++ = table[color][3]; } + format = GL_RGBA; - pixel_format = GL_UNSIGNED_INT_8_8_8_8; + pixel_format = GL_UNSIGNED_BYTE; + } + } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) { + /* ************ + RGB Textures + ************ */ + if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) { + if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xE0) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x1C) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x03)) { + /* ********************** + GL_UNSIGNED_BYTE_3_3_2 + ********************** */ + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* This texture format will never be used.. So do not care about color keying + up until the point in time it will be needed :-) */ + error = TRUE; + } else { + format = GL_RGB; + pixel_format = GL_UNSIGNED_BYTE_3_3_2; + } + } else { + error = TRUE; + } + } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) { + if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07E0) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) { + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* Converting the 565 format in 5551 packed to emulate color-keying. + + Note : in all these conversion, it would be best to average the averaging + pixels to get the color of the pixel that will be color-keyed to + prevent 'color bleeding'. This will be done later on if ever it is + too visible. + + Note2: when using color-keying + alpha, are the alpha bits part of the + color-space or not ? + */ + DWORD i; + WORD *src = (WORD *) src_d->lpSurface, *dst; + + 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 & 0xFFC0) | ((color & 0x1F) << 1)); + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= 0x0001; + dst++; + } + + format = GL_RGBA; + pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; + } else { + format = GL_RGB; + pixel_format = GL_UNSIGNED_SHORT_5_6_5; + } + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07C0) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x003E) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0001)) { + format = GL_RGBA; + pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* Change the alpha value of the color-keyed pixels to emulate color-keying. */ + DWORD i; + WORD *src = (WORD *) src_d->lpSurface, *dst; + + 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 & 0xFFFE; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= color & 0x0001; + dst++; + } + } + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF000) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0F00) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x00F0) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000F)) { + format = GL_RGBA; + pixel_format = GL_UNSIGNED_SHORT_4_4_4_4; + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* Change the alpha value of the color-keyed pixels to emulate color-keying. */ + DWORD i; + WORD *src = (WORD *) src_d->lpSurface, *dst; + + 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 & 0xFFF0; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= color & 0x000F; + dst++; + } + } + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x0F00) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00F0) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000F) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xF000)) { + /* Move the four Alpha bits... */ + DWORD i; + WORD *src = (WORD *) src_d->lpSurface, *dst; + + surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); + dst = surface; + + 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; + pixel_format = GL_UNSIGNED_SHORT_4_4_4_4; + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x7C00) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x03E0) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x8000)) { + /* Converting the 1555 format in 5551 packed */ + DWORD i; + WORD *src = (WORD *) src_d->lpSurface, *dst; + + surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + src_d->dwWidth * src_d->dwHeight * sizeof(WORD)); + dst = (WORD *) surface; + + 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; + pixel_format = GL_UNSIGNED_SHORT_5_5_5_1; + } else { + error = TRUE; + } + } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) { + if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* This is a pain :-) */ + DWORD i; + BYTE *src = (BYTE *) src_d->lpSurface; + DWORD *dst; + + surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + src_d->dwWidth * src_d->dwHeight * sizeof(DWORD)); + dst = (DWORD *) surface; + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + DWORD color = *((DWORD *) src) & 0x00FFFFFF; + src += 3; + *dst = *src++ << 8; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= 0xFF; + dst++; + } + format = GL_RGBA; + pixel_format = GL_UNSIGNED_INT_8_8_8_8; + } else { + format = GL_BGR; + pixel_format = GL_UNSIGNED_BYTE; + } + } else { + error = TRUE; + } + } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) { + if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xFF000000) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00FF0000) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x0000FF00) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000000FF)) { + if (src_d->dwFlags & DDSD_CKSRCBLT) { + /* Just use the alpha component to 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; + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + DWORD color = *src++; + *dst = color & 0xFFFFFF00; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= color & 0x000000FF; + dst++; + } + } + format = GL_RGBA; + pixel_format = GL_UNSIGNED_INT_8_8_8_8; + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xFF000000)) { + /* Convert from ARGB (Windows' format) to RGBA. + Note: need to check for GL extensions handling ARGB instead of always converting */ + 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; + if (src_d->dwFlags & DDSD_CKSRCBLT) { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + DWORD color = *src++; + *dst = (color & 0x00FFFFFF) << 8; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *dst |= (color & 0xFF000000) >> 24; + dst++; + } + } else { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + DWORD color = *src++; + *dst = (color & 0x00FFFFFF) << 8; + *dst |= (color & 0xFF000000) >> 24; + } + } + format = GL_RGBA; + pixel_format = GL_UNSIGNED_INT_8_8_8_8; + } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && + (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && + (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && + (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { + /* 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; + + if (src_d->dwFlags & DDSD_CKSRCBLT) { + for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { + DWORD color = *src++; + *dst = color << 8; + if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || + (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) + *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; + } else { + error = TRUE; + } } else { - format = GL_BGR; - pixel_format = GL_UNSIGNED_BYTE; + error = TRUE; } } else { error = TRUE; - } - } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) { - if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xFF000000) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00FF0000) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x0000FF00) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000000FF)) { - if (src_d->dwFlags & DDSD_CKSRCBLT) { - /* Just use the alpha component to 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; - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - DWORD color = *src++; - *dst = color & 0xFFFFFF00; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= color & 0x000000FF; - dst++; - } - } - format = GL_RGBA; - pixel_format = GL_UNSIGNED_INT_8_8_8_8; - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xFF000000)) { - /* Convert from ARGB (Windows' format) to RGBA. - Note: need to check for GL extensions handling ARGB instead of always converting */ - 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; - if (src_d->dwFlags & DDSD_CKSRCBLT) { - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - DWORD color = *src++; - *dst = (color & 0x00FFFFFF) << 8; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= (color & 0xFF000000) >> 24; - dst++; - } + } + + if ((upload_done == FALSE) && (error == FALSE)) { + if (gl_surf_ptr->initial_upload_done == FALSE) { + glTexImage2D(GL_TEXTURE_2D, + surf_ptr->mipmap_level, + format, + src_d->dwWidth, src_d->dwHeight, + 0, + format, + pixel_format, + surface == NULL ? src_d->lpSurface : surface); + gl_surf_ptr->initial_upload_done = TRUE; } else { - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - DWORD color = *src++; - *dst = (color & 0x00FFFFFF) << 8; - *dst |= (color & 0xFF000000) >> 24; - } + glTexSubImage2D(GL_TEXTURE_2D, + surf_ptr->mipmap_level, + 0, 0, + src_d->dwWidth, src_d->dwHeight, + format, + pixel_format, + surface == NULL ? src_d->lpSurface : surface); } - format = GL_RGBA; - pixel_format = GL_UNSIGNED_INT_8_8_8_8; - } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) && - (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) && - (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) && - (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) { - /* Just add an alpha component and handle color-keying... */ - DWORD i; - DWORD *src = (DWORD *) src_d->lpSurface, *dst; + gl_surf_ptr->dirty_flag = FALSE; - 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; - if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) || - (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue)) - *dst |= 0xFF; - dst++; - } - } else { - for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) { - *dst++ = (*src++ << 8) | 0xFF; - } + if (surface) HeapFree(GetProcessHeap(), 0, surface); + } else if (error == TRUE) { + if (ERR_ON(ddraw)) { + ERR(" unsupported pixel format for textures : \n"); + DDRAW_dump_pixelformat(&src_d->ddpfPixelFormat); } - format = GL_RGBA; - pixel_format = GL_UNSIGNED_INT_8_8_8_8; - } else { - error = TRUE; } - } else { - error = TRUE; - } - } else { - error = TRUE; - } - - if ((upload_done == FALSE) && (error == FALSE)) { - if (glThis->initial_upload_done == FALSE) { - glTexImage2D(GL_TEXTURE_2D, - This->mipmap_level, - format, - src_d->dwWidth, src_d->dwHeight, - 0, - format, - pixel_format, - surface == NULL ? src_d->lpSurface : surface); - glThis->initial_upload_done = TRUE; - } else { - glTexSubImage2D(GL_TEXTURE_2D, - This->mipmap_level, - 0, 0, - src_d->dwWidth, src_d->dwHeight, - format, - pixel_format, - surface == NULL ? src_d->lpSurface : surface); } - - if (surface) HeapFree(GetProcessHeap(), 0, surface); - } else if (error == TRUE) { - if (ERR_ON(ddraw)) { - ERR("Unsupported pixel format for textures : \n"); - DDRAW_dump_pixelformat(&src_d->ddpfPixelFormat); - } - } - glThis->dirty_flag = FALSE; + surf_ptr = get_sub_mimaplevel(surf_ptr); + } return DD_OK; } @@ -499,7 +537,8 @@ IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; glThis->dirty_flag = TRUE; - + /* TODO: check color-keying on mipmapped surfaces... */ + return DD_OK; } @@ -560,6 +599,8 @@ /* And set the dirty flag */ glThis->dirty_flag = TRUE; + + /* TODO: check palette on mipmapped surfaces... */ } static void @@ -618,82 +659,99 @@ LPDIRECT3DTEXTURE2 lpD3DTexture2) { ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface); - IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private; - IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2); - DWORD mem_used; - DDSURFACEDESC *src_d, *dst_d; + IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2); + IDirectDrawSurfaceImpl *dst_ptr = This; HRESULT ret_value = D3D_OK; - + TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2); - if (glThis != NULL) { - if (glThis->loaded == FALSE) { - /* Only check memory for not already loaded texture... */ - mem_used = This->surface_desc.dwHeight * - This->surface_desc.u1.lPitch; - if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) { - TRACE(" out of virtual memory... Warning application.\n"); - return D3DERR_TEXTURE_LOAD_FAILED; + if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) || + (src_ptr->surface_desc.u2.dwMipMapCount != dst_ptr->surface_desc.u2.dwMipMapCount)) { + ERR("Trying to load surfaces with different mip-map counts !\n"); + } + + /* Now loop through all mipmap levels and load all of them... */ + while (1) { + IDirect3DTextureGLImpl *gl_dst_ptr = (IDirect3DTextureGLImpl *) dst_ptr->tex_private; + DDSURFACEDESC *src_d, *dst_d; + + if (gl_dst_ptr != NULL) { + if (gl_dst_ptr->loaded == FALSE) { + /* Only check memory for not already loaded texture... */ + DWORD mem_used = dst_ptr->surface_desc.dwHeight * dst_ptr->surface_desc.u1.lPitch; + if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) { + TRACE(" out of virtual memory... Warning application.\n"); + return D3DERR_TEXTURE_LOAD_FAILED; + } } + gl_dst_ptr->loaded = TRUE; } - glThis->loaded = TRUE; - } - TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This); + TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, dst_ptr, src_ptr->mipmap_level); - if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD ) - /* If the surface is not allocated and its location is not yet specified, - force it to video memory */ - if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) ) - This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; - - /* Suppress the ALLOCONLOAD flag */ - This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD; - - /* After seeing some logs, not sure at all about this... */ - if (This->palette == NULL) { - This->palette = lpD3DTextureImpl->palette; - if (lpD3DTextureImpl->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(lpD3DTextureImpl->palette, - IDirectDrawPalette)); - } else { - if (lpD3DTextureImpl->palette != NULL) { - PALETTEENTRY palent[256]; - IDirectDrawPalette *pal_int = ICOM_INTERFACE(lpD3DTextureImpl->palette, IDirectDrawPalette); - IDirectDrawPalette_GetEntries(pal_int, 0, 0, 256, palent); - IDirectDrawPalette_SetEntries(ICOM_INTERFACE(This->palette, IDirectDrawPalette), - 0, 0, 256, palent); + if ( dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD ) + /* If the surface is not allocated and its location is not yet specified, + force it to video memory */ + if ( !(dst_ptr->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) ) + dst_ptr->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + + /* Suppress the ALLOCONLOAD flag */ + dst_ptr->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD; + + /* After seeing some logs, not sure at all about this... */ + if (dst_ptr->palette == NULL) { + dst_ptr->palette = src_ptr->palette; + if (src_ptr->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette)); + } else { + if (src_ptr->palette != NULL) { + PALETTEENTRY palent[256]; + IDirectDrawPalette_GetEntries(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette), + 0, 0, 256, palent); + IDirectDrawPalette_SetEntries(ICOM_INTERFACE(dst_ptr->palette, IDirectDrawPalette), + 0, 0, 256, palent); + } } - } - - /* Copy one surface on the other */ - dst_d = (DDSURFACEDESC *)&(This->surface_desc); - src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc); - - if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) { - /* Should also check for same pixel format, u1.lPitch, ... */ - ERR("Error in surface sizes\n"); - return D3DERR_TEXTURE_LOAD_FAILED; - } else { - /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */ - /* I should put a macro for the calculus of bpp */ - - /* Copy also the ColorKeying stuff */ - if (src_d->dwFlags & DDSD_CKSRCBLT) { - dst_d->dwFlags |= DDSD_CKSRCBLT; - dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue; - dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue; + + /* Copy one surface on the other */ + dst_d = (DDSURFACEDESC *)&(dst_ptr->surface_desc); + src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc); + + if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) { + /* Should also check for same pixel format, u1.lPitch, ... */ + ERR("Error in surface sizes\n"); + return D3DERR_TEXTURE_LOAD_FAILED; + } else { + /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */ + /* I should put a macro for the calculus of bpp */ + + /* Copy also the ColorKeying stuff */ + if (src_d->dwFlags & DDSD_CKSRCBLT) { + dst_d->dwFlags |= DDSD_CKSRCBLT; + dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue; + dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue; + } + + /* Copy the main memory texture into the surface that corresponds to the OpenGL + texture object. */ + memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight); + + if (gl_dst_ptr != NULL) { + /* If the GetHandle was not done, it is an error... */ + if (gl_dst_ptr->tex_name == 0) ERR("Unbound GL texture !!!\n"); + + /* Set this texture as dirty */ + gl_dst_ptr->dirty_flag = TRUE; + } } - /* Copy the main memory texture into the surface that corresponds to the OpenGL - texture object. */ - memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight); - - if (glThis != NULL) { - /* If the GetHandle was not done, it is an error... */ - if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n"); + src_ptr = get_sub_mimaplevel(src_ptr); + dst_ptr = get_sub_mimaplevel(dst_ptr); - /* Set this texture as dirty */ - glThis->dirty_flag = TRUE; + if ((src_ptr == NULL) || (dst_ptr == NULL)) { + if (src_ptr != dst_ptr) { + ERR(" Loading surface with different mipmap structure !!!\n"); + } + break; } } Index: dlls/ddraw/d3ddevice/main.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/d3ddevice/main.c,v retrieving revision 1.38 diff -u -r1.38 main.c --- dlls/ddraw/d3ddevice/main.c 15 Mar 2003 01:11:15 -0000 1.38 +++ dlls/ddraw/d3ddevice/main.c 9 May 2003 18:58:08 -0000 @@ -132,10 +132,10 @@ }; DWORD InitTextureStageStateTab[] = { - D3DTSS_COLOROP, D3DTOP_DISABLE, + D3DTSS_COLOROP, D3DTOP_DISABLE, /* Note, it's manually set for stage 0 */ D3DTSS_COLORARG1, D3DTA_TEXTURE, D3DTSS_COLORARG2, D3DTA_CURRENT, - D3DTSS_ALPHAOP, D3DTOP_DISABLE, + D3DTSS_ALPHAOP, D3DTOP_DISABLE, /* Note, it's manually set for stage 0 */ D3DTSS_ALPHAARG1, D3DTA_TEXTURE, D3DTSS_ALPHAARG2, D3DTA_CURRENT, /* FIXME: D3DTSS_BUMPENVMAT00,01,10,11 */ @@ -143,13 +143,13 @@ D3DTSS_ADDRESS, D3DTADDRESS_WRAP, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP, - /* FIXME: D3DTSS_BORDERCOLOR */ + D3DTSS_BORDERCOLOR, 0x00000000, D3DTSS_MAGFILTER, D3DTFG_POINT, D3DTSS_MINFILTER, D3DTFN_POINT, D3DTSS_MIPFILTER, D3DTFP_NONE, D3DTSS_MIPMAPLODBIAS, 0x00000000, /* 0.0f */ - D3DTSS_MAXMIPLEVEL, 0 - /* FIXME: D3DTSS_MAXANISOTROPY */ + D3DTSS_MAXMIPLEVEL, 0, + D3DTSS_MAXANISOTROPY, 1, /* FIXME: D3DTSS_BUMPENVLSCALE */ /* FIXME: D3DTSS_NUMPENVLOFFSET */ /* FIXME: D3DTSS_TEXTURETRANSFORMFLAGS */ @@ -158,21 +158,21 @@ void InitDefaultStateBlock(STATEBLOCK* lpStateBlock, int version) { - int i,j; + int i, j; TRACE("(%p,%d)\n", lpStateBlock, version); memset(lpStateBlock, 0, sizeof(STATEBLOCK)); /* Initialize render states */ - for(i = 0; i < sizeof(InitRenderStateTab) / sizeof(InitRenderStateTab[0]); i += 2) + for (i = 0; i < sizeof(InitRenderStateTab) / sizeof(InitRenderStateTab[0]); i += 2) { lpStateBlock->render_state[InitRenderStateTab[i] - 1] = InitRenderStateTab[i + 1]; lpStateBlock->set_flags.render_state[InitRenderStateTab[i] - 1] = TRUE; } /* Initialize texture stages states */ - for(i = 0; i < MAX_TEXTURES; i++) + for (i = 0; i < MAX_TEXTURES; i++) { - for(j = 0; j < sizeof(InitTextureStageStateTab) / sizeof(InitTextureStageStateTab[0]); j += 2) + for (j = 0; j < sizeof(InitTextureStageStateTab) / sizeof(InitTextureStageStateTab[0]); j += 2) { lpStateBlock->texture_stage_state[i][InitTextureStageStateTab[j] - 1] = InitTextureStageStateTab[j + 1]; lpStateBlock->set_flags.texture_stage_state[i][InitTextureStageStateTab[j] - 1] = TRUE; @@ -185,6 +185,8 @@ /* The first texture is particular, update it consequently */ lpStateBlock->texture_stage_state[0][D3DTSS_COLOROP - 1] = D3DTOP_MODULATE; lpStateBlock->texture_stage_state[0][D3DTSS_ALPHAOP - 1] = D3DTOP_SELECTARG1; + lpStateBlock->texture_stage_state[0][D3DTSS_COLORARG2 - 1] = D3DTA_DIFFUSE; + lpStateBlock->texture_stage_state[0][D3DTSS_ALPHAARG2 - 1] = D3DTA_DIFFUSE; /* Updates for particular versions */ if ((version == 1) || (version==2)) Index: dlls/ddraw/d3ddevice/mesa.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/d3ddevice/mesa.c,v retrieving revision 1.93 diff -u -r1.93 mesa.c --- dlls/ddraw/d3ddevice/mesa.c 8 May 2003 21:03:57 -0000 1.93 +++ dlls/ddraw/d3ddevice/mesa.c 9 May 2003 18:58:09 -0000 @@ -327,6 +327,8 @@ if (This->current_texture[i] != NULL) IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7)); + /* TODO: remove the 'callbacks' for Flip and Lock/Unlock */ + /* And warn the D3D object that this device is no longer active... */ This->d3d->removed_device(This->d3d, This); @@ -334,6 +336,8 @@ HeapFree(GetProcessHeap(), 0, This->view_mat); HeapFree(GetProcessHeap(), 0, This->proj_mat); + DeleteCriticalSection(&(This->crit)); + ENTER_GL(); glXDestroyContext(glThis->display, glThis->gl_context); LEAVE_GL(); @@ -408,6 +412,18 @@ if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK; if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK; +#if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */ + TRACE("Enumerating GL_RGB unpacked (32)\n"); + pformat->dwFlags = DDPF_RGB; + pformat->u1.dwRGBBitCount = 32; + pformat->u2.dwRBitMask = 0x00FF0000; + pformat->u3.dwGBitMask = 0x0000FF00; + pformat->u4.dwBBitMask = 0x000000FF; + pformat->u5.dwRGBAlphaBitMask = 0x00000000; + if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK; + if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK; +#endif + TRACE("Enumerating GL_RGB unpacked (24)\n"); pformat->dwFlags = DDPF_RGB; pformat->u1.dwRGBBitCount = 24; @@ -847,7 +835,7 @@ } break; default: - FIXME("Unhandled vertex type\n"); + FIXME("Unhandled vertex type %08x\n", d3dvt); break; } } @@ -1051,6 +1040,10 @@ BOOLEAN vertex_lighted = FALSE; IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This; + /* This is to prevent 'thread contention' between a thread locking the device and another + doing 3D display on it... */ + EnterCriticalSection(&(This->crit)); + if (TRACE_ON(ddraw)) { TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType); } @@ -1232,6 +1225,8 @@ LEAVE_GL(); TRACE("End\n"); + + LeaveCriticalSection(&(This->crit)); } HRESULT WINAPI @@ -1396,20 +1391,28 @@ } static GLenum -convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwState) +convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState) { GLenum gl_state; - switch (dwState) { - case D3DTFN_POINT: - gl_state = GL_NEAREST; - break; - case D3DTFN_LINEAR: - gl_state = GL_LINEAR; - break; - default: - gl_state = GL_LINEAR; - break; + 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; } @@ -1433,6 +1436,73 @@ return gl_state; } +/* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */ +static BOOLEAN +handle_color_alpha_args(DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op) +{ + BOOLEAN is_complement = FALSE; + BOOLEAN is_alpha_replicate = FALSE; + BOOLEAN handled = TRUE; + GLenum src; + BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)); + int num; + + if (is_color) { + if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0; + else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1; + else { + handled = FALSE; + num = 0; + } + if (tex_op == D3DTOP_SELECTARG2) { + num = 1 - num; + } + } else { + if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0; + else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1; + else { + handled = FALSE; + num = 0; + } + if (tex_op == D3DTOP_SELECTARG2) { + num = 1 - num; + } + } + + if (dwState & D3DTA_COMPLEMENT) { + is_complement = TRUE; + } + if (dwState & D3DTA_ALPHAREPLICATE) { + is_alpha_replicate = TRUE; + } + dwState &= D3DTA_SELECTMASK; + if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) { + dwState = D3DTA_DIFFUSE; + } + + switch (dwState) { + case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break; + case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_ARB; break; + case D3DTA_TEXTURE: src = GL_TEXTURE; break; + case D3DTA_TFACTOR: src = GL_CONSTANT_ARB; FIXME(" no handling yet of setting of constant value !\n"); break; + default: src = GL_TEXTURE; handled = FALSE; break; + } + + if (is_color) { + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB + num, src); + if (is_alpha_replicate) { + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA); + } else { + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR); + } + } else { + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB + num, src); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA); + } + + return handled; +} + HRESULT WINAPI GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface, DWORD dwStage, @@ -1440,63 +1510,83 @@ DWORD dwState) { ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface); + const char *type; + DWORD prev_state; TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState); if (dwStage > 0) return DD_OK; /* We nothing in this case for now */ - if (TRACE_ON(ddraw)) { - TRACE(" Stage type is : "); - switch (d3dTexStageStateType) { -#define GEN_CASE(a) case a: TRACE(#a " "); break - GEN_CASE(D3DTSS_COLOROP); - GEN_CASE(D3DTSS_COLORARG1); - GEN_CASE(D3DTSS_COLORARG2); - GEN_CASE(D3DTSS_ALPHAOP); - GEN_CASE(D3DTSS_ALPHAARG1); - GEN_CASE(D3DTSS_ALPHAARG2); - GEN_CASE(D3DTSS_BUMPENVMAT00); - GEN_CASE(D3DTSS_BUMPENVMAT01); - GEN_CASE(D3DTSS_BUMPENVMAT10); - GEN_CASE(D3DTSS_BUMPENVMAT11); - GEN_CASE(D3DTSS_TEXCOORDINDEX); - GEN_CASE(D3DTSS_ADDRESS); - GEN_CASE(D3DTSS_ADDRESSU); - GEN_CASE(D3DTSS_ADDRESSV); - GEN_CASE(D3DTSS_BORDERCOLOR); - GEN_CASE(D3DTSS_MAGFILTER); - GEN_CASE(D3DTSS_MINFILTER); - GEN_CASE(D3DTSS_MIPFILTER); - GEN_CASE(D3DTSS_MIPMAPLODBIAS); - GEN_CASE(D3DTSS_MAXMIPLEVEL); - GEN_CASE(D3DTSS_MAXANISOTROPY); - GEN_CASE(D3DTSS_BUMPENVLSCALE); - GEN_CASE(D3DTSS_BUMPENVLOFFSET); - GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS); + switch (d3dTexStageStateType) { +#define GEN_CASE(a) case a: type = #a; break + GEN_CASE(D3DTSS_COLOROP); + GEN_CASE(D3DTSS_COLORARG1); + GEN_CASE(D3DTSS_COLORARG2); + GEN_CASE(D3DTSS_ALPHAOP); + GEN_CASE(D3DTSS_ALPHAARG1); + GEN_CASE(D3DTSS_ALPHAARG2); + GEN_CASE(D3DTSS_BUMPENVMAT00); + GEN_CASE(D3DTSS_BUMPENVMAT01); + GEN_CASE(D3DTSS_BUMPENVMAT10); + GEN_CASE(D3DTSS_BUMPENVMAT11); + GEN_CASE(D3DTSS_TEXCOORDINDEX); + GEN_CASE(D3DTSS_ADDRESS); + GEN_CASE(D3DTSS_ADDRESSU); + GEN_CASE(D3DTSS_ADDRESSV); + GEN_CASE(D3DTSS_BORDERCOLOR); + GEN_CASE(D3DTSS_MAGFILTER); + GEN_CASE(D3DTSS_MINFILTER); + GEN_CASE(D3DTSS_MIPFILTER); + GEN_CASE(D3DTSS_MIPMAPLODBIAS); + GEN_CASE(D3DTSS_MAXMIPLEVEL); + GEN_CASE(D3DTSS_MAXANISOTROPY); + GEN_CASE(D3DTSS_BUMPENVLSCALE); + GEN_CASE(D3DTSS_BUMPENVLOFFSET); + GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS); #undef GEN_CASE - default: TRACE("UNKNOWN !!!"); - } - TRACE(" => "); + default: type = "UNKNOWN"; } + /* Store the values in the state array */ + prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1]; + This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState; + /* Some special cases when one state modifies more than one... */ + if (d3dTexStageStateType == D3DTSS_ADDRESS) { + This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState; + This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState; + } + switch (d3dTexStageStateType) { case D3DTSS_MINFILTER: + case D3DTSS_MIPFILTER: if (TRACE_ON(ddraw)) { - switch ((D3DTEXTUREMINFILTER) dwState) { - case D3DTFN_POINT: TRACE("D3DTFN_POINT\n"); break; - case D3DTFN_LINEAR: TRACE("D3DTFN_LINEAR\n"); break; - default: TRACE(" state unhandled (%ld).\n", dwState); break; + if (d3dTexStageStateType == D3DTSS_MINFILTER) { + switch ((D3DTEXTUREMINFILTER) dwState) { + case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break; + case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break; + default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break; + } + } else { + switch ((D3DTEXTUREMIPFILTER) dwState) { + case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break; + case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break; + case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break; + default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break; + } } } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, convert_min_filter_to_GL(dwState)); - break; + + 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: if (TRACE_ON(ddraw)) { switch ((D3DTEXTUREMAGFILTER) dwState) { - case D3DTFG_POINT: TRACE("D3DTFN_POINT\n"); break; - case D3DTFG_LINEAR: TRACE("D3DTFN_LINEAR\n"); break; - default: TRACE(" state unhandled (%ld).\n", dwState); break; + case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break; + case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break; + 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)); @@ -1507,10 +1597,15 @@ case D3DTSS_ADDRESSV: { GLenum arg = GL_REPEAT; /* Default value */ switch ((D3DTEXTUREADDRESS) dwState) { - case D3DTADDRESS_WRAP: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_WRAP\n"); arg = GL_REPEAT; break; - case D3DTADDRESS_CLAMP: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_CLAMP\n"); arg = GL_CLAMP; break; - case D3DTADDRESS_BORDER: if (TRACE_ON(ddraw)) TRACE("D3DTADDRESS_BORDER\n"); arg = GL_CLAMP_TO_EDGE; break; - default: TRACE(" state unhandled (%ld).\n", dwState); + case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); arg = GL_REPEAT; break; + case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); arg = GL_CLAMP; break; + case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); arg = GL_CLAMP_TO_EDGE; break; +#if defined(GL_VERSION_1_4) + case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT; break; +#elif defined(GL_ARB_texture_mirrored_repeat) + case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); arg = GL_MIRRORED_REPEAT_ARB; break; +#endif + default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break; } if ((d3dTexStageStateType == D3DTSS_ADDRESS) || (d3dTexStageStateType == D3DTSS_ADDRESSU)) @@ -1519,18 +1614,174 @@ (d3dTexStageStateType == D3DTSS_ADDRESSV)) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg); } break; + + case D3DTSS_ALPHAOP: + case D3DTSS_COLOROP: { + int scale = 1; + GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_ARB : GL_COMBINE_RGB_ARB; + const char *value; + int handled = 1; + + switch (dwState) { +#define GEN_CASE(a) case a: value = #a; break + GEN_CASE(D3DTOP_DISABLE); + GEN_CASE(D3DTOP_SELECTARG1); + GEN_CASE(D3DTOP_SELECTARG2); + GEN_CASE(D3DTOP_MODULATE); + GEN_CASE(D3DTOP_MODULATE2X); + GEN_CASE(D3DTOP_MODULATE4X); + GEN_CASE(D3DTOP_ADD); + GEN_CASE(D3DTOP_ADDSIGNED); + GEN_CASE(D3DTOP_ADDSIGNED2X); + GEN_CASE(D3DTOP_SUBTRACT); + GEN_CASE(D3DTOP_ADDSMOOTH); + GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA); + GEN_CASE(D3DTOP_BLENDTEXTUREALPHA); + GEN_CASE(D3DTOP_BLENDFACTORALPHA); + GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM); + GEN_CASE(D3DTOP_BLENDCURRENTALPHA); + GEN_CASE(D3DTOP_PREMODULATE); + GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR); + GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA); + GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR); + GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA); + GEN_CASE(D3DTOP_BUMPENVMAP); + GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE); + GEN_CASE(D3DTOP_DOTPRODUCT3); + GEN_CASE(D3DTOP_FORCE_DWORD); +#undef GEN_CASE + default: value = "UNKNOWN"; + } + + if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) { + glDisable(GL_TEXTURE_2D); + TRACE(" disabling 2D texturing.\n"); + } else { + /* Re-enable texturing */ + if ((dwStage == 0) && (This->current_texture[0] != NULL)) { + glEnable(GL_TEXTURE_2D); + TRACE(" enabling 2D texturing.\n"); + } + + /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB */ + if (dwState != D3DTOP_DISABLE) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + } + + /* Now set up the operand correctly */ + switch (dwState) { + case D3DTOP_DISABLE: + /* Contrary to the docs, alpha can be disabled when colorop is enabled + and it works, so ignore this op */ + TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n"); + break; + + case D3DTOP_SELECTARG1: + case D3DTOP_SELECTARG2: + glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE); + break; + + case D3DTOP_MODULATE4X: + scale = scale * 2; /* Drop through */ + case D3DTOP_MODULATE2X: + scale = scale * 2; /* Drop through */ + case D3DTOP_MODULATE: + glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE); + break; + + case D3DTOP_ADD: + glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD); + break; + + case D3DTOP_ADDSIGNED2X: + scale = scale * 2; /* Drop through */ + case D3DTOP_ADDSIGNED: + glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_ARB); + break; + + default: + handled = FALSE; + break; + } + } + + if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) || + ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) { + /* Switch the arguments if needed... */ + if (d3dTexStageStateType == D3DTSS_COLOROP) { + handle_color_alpha_args(dwStage, D3DTSS_COLORARG1, + This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1], + dwState); + handle_color_alpha_args(dwStage, D3DTSS_COLORARG2, + This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1], + dwState); + } else { + handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG1, + This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1], + dwState); + handle_color_alpha_args(dwStage, D3DTSS_ALPHAARG2, + This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1], + dwState); + } + } + + if (handled) { + if (d3dTexStageStateType == D3DTSS_ALPHAOP) { + glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale); + } else { + glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, scale); + } + TRACE(" Stage type is : %s => %s\n", type, value); + } else { + FIXME(" Unhandled stage type is : %s => %s\n", type, value); + } + } break; + + case D3DTSS_COLORARG1: + case D3DTSS_COLORARG2: + case D3DTSS_ALPHAARG1: + case D3DTSS_ALPHAARG2: { + const char *value, *value_comp = "", *value_alpha = ""; + BOOLEAN handled; + D3DTEXTUREOP tex_op; + + switch (dwState & D3DTA_SELECTMASK) { +#define GEN_CASE(a) case a: value = #a; break + GEN_CASE(D3DTA_DIFFUSE); + GEN_CASE(D3DTA_CURRENT); + GEN_CASE(D3DTA_TEXTURE); + GEN_CASE(D3DTA_TFACTOR); + GEN_CASE(D3DTA_SPECULAR); +#undef GEN_CASE + default: value = "UNKNOWN"; + } + if (dwState & D3DTA_COMPLEMENT) { + value_comp = " | D3DTA_COMPLEMENT"; + } + if (dwState & D3DTA_ALPHAREPLICATE) { + value_alpha = " | D3DTA_ALPHAREPLICATE"; + } + + if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) { + tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1]; + } else { + tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1]; + } + + handled = handle_color_alpha_args(dwStage, d3dTexStageStateType, dwState, tex_op); + + if (handled) { + TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha); + } else { + FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha); + } + } break; default: - if (TRACE_ON(ddraw)) TRACE(" unhandled.\n"); + FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); + break; } - This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState; - /* Some special cases when one state modifies more than one... */ - if (d3dTexStageStateType == D3DTSS_ADDRESS) { - This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState; - This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState; - } - return DD_OK; } @@ -1558,17 +1809,30 @@ glDisable(GL_TEXTURE_2D); } else { IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2); + GLint max_mip_level; This->current_texture[dwStage] = tex_impl; IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */ - - glEnable(GL_TEXTURE_2D); + + 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; + } + 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])); + 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_MAX_LEVEL, max_mip_level); } LEAVE_GL(); @@ -2137,18 +2401,22 @@ */ static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags) { - /* First, check if we need to do anything */ + /* Try to acquire the device critical section */ + EnterCriticalSection(&(This->d3ddevice->crit)); + + /* Then check if we need to do anything */ if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) { GLenum buffer_type; GLenum prev_read; RECT loc_rect; + WARN(" application does a lock on a 3D surface - expect slow downs.\n"); + ENTER_GL(); glGetIntegerv(GL_READ_BUFFER, &prev_read); glFlush(); - WARN(" application does a lock on a 3D surface - expect slow downs.\n"); if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) { /* Application wants to lock the front buffer */ glReadBuffer(GL_FRONT); @@ -2174,10 +2442,12 @@ } else { loc_rect = *pRect; } +#if 0 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom, GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface + loc_rect.top * This->surface_desc.u1.lPitch + loc_rect.left * GET_BPP(This->surface_desc))); +#endif glReadBuffer(prev_read); LEAVE_GL(); } @@ -2190,11 +2460,12 @@ GLenum buffer_type; GLenum prev_draw; + WARN(" application does an unlock on a 3D surface - expect slow downs.\n"); + ENTER_GL(); glGetIntegerv(GL_DRAW_BUFFER, &prev_draw); - WARN(" application does an unlock on a 3D surface - expect slow downs.\n"); if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) { /* Application wants to lock the front buffer */ glDrawBuffer(GL_FRONT); @@ -2210,17 +2481,41 @@ } else { WARN(" unsupported pixel format.\n"); LEAVE_GL(); + + /* And 'frees' the device critical section */ + LeaveCriticalSection(&(This->d3ddevice->crit)); return; } glRasterPos2f(0.0, 0.0); +#if 0 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight, GL_RGB, buffer_type, This->surface_desc.lpSurface); +#endif glDrawBuffer(prev_draw); LEAVE_GL(); } + + /* And 'frees' the device critical section */ + LeaveCriticalSection(&(This->d3ddevice->crit)); } +static void +apply_texture_state(IDirect3DDeviceImpl *This) +{ + int stage, state; + + /* Initialize texture stages states */ + for (stage = 0; stage < MAX_TEXTURES; stage++) { + for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) { + if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) { + IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), + stage, state + 1, This->state_block.texture_stage_state[stage][state]); + } + } + } +} + HRESULT d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface) { @@ -2248,6 +2543,8 @@ object->set_matrices = d3ddevice_set_matrices; object->matrices_updated = d3ddevice_matrices_updated; + InitializeCriticalSection(&(object->crit)); + TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d); device_context = GetDC(surface->ddraw_owner->window); @@ -2295,18 +2592,26 @@ buffer = GL_FRONT; } - for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ; - for (; surf != NULL; surf = surf->next_attached) { - if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) && - ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) { - /* Override the Lock / Unlock function for all these surfaces */ - surf->lock_update = d3ddevice_lock_update; - surf->unlock_update = d3ddevice_unlock_update; - /* And install also the blt / bltfast overrides */ - surf->aux_blt = d3ddevice_blt; - surf->aux_bltfast = d3ddevice_bltfast; + for (surf = surface; surf != NULL; surf = surf->surface_owner) { + IDirectDrawSurfaceImpl *surf2; + for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ; + for (; surf2 != NULL; surf2 = surf2->next_attached) { + TRACE(" checking surface %p :", surf2); + if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) && + ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) { + /* Override the Lock / Unlock function for all these surfaces */ + surf2->lock_update = d3ddevice_lock_update; + surf2->unlock_update = d3ddevice_unlock_update; + /* And install also the blt / bltfast overrides */ + surf2->aux_blt = d3ddevice_blt; + surf2->aux_bltfast = d3ddevice_bltfast; + + TRACE(" overiding direct surface access.\n"); + } else { + TRACE(" no overide.\n"); + } + surf2->d3ddevice = object; } - surf->d3ddevice = object; } /* Set the various light parameters */ @@ -2369,9 +2672,9 @@ /* FIXME: Should handle other versions than just 7 */ InitDefaultStateBlock(&object->state_block, 7); - /* Apply default render state values */ + /* Apply default render state and texture stage state values */ apply_render_state(object, &object->state_block); - /* FIXME: do something similar for ligh_state and texture_stage_state */ + apply_texture_state(object); /* And fill the fog table with the default fog value */ build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);