2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the implementation of interface Direct3DTexture2.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 #include "mesa_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
38 /* Define this if you want to save to a file all the textures used by a game
39 (can be funny to see how they managed to cram all the pictures in
47 snoop_texture(IDirectDrawSurfaceImpl *This) {
48 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
52 sprintf(buf, "tex_%05d_%02d.pnm", glThis->tex_name, This->mipmap_level);
54 DDRAW_dump_surface_to_disk(This, f);
59 #define snoop_texture(a)
63 static IDirectDrawSurfaceImpl *
64 get_sub_mimaplevel(IDirectDrawSurfaceImpl *tex_ptr)
66 /* Now go down the mipmap chain to the next surface */
67 static const DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
68 LPDIRECTDRAWSURFACE7 next_level;
69 IDirectDrawSurfaceImpl *surf_ptr;
72 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(tex_ptr, IDirectDrawSurface7),
73 (DDSCAPS2 *) &mipmap_caps, &next_level);
74 if (FAILED(hr)) return NULL;
76 surf_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, next_level);
77 IDirectDrawSurface7_Release(next_level);
82 /*******************************************************************************
83 * IDirectSurface callback methods
86 gltex_upload_texture(IDirectDrawSurfaceImpl *This) {
87 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
89 static BOOL color_table_queried = FALSE;
91 static void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
92 GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
93 IDirectDrawSurfaceImpl *surf_ptr;
94 GLuint tex_name = glThis->tex_name;
96 TRACE(" activating OpenGL texture id %d.\n", tex_name);
97 glBindTexture(GL_TEXTURE_2D, tex_name);
99 if (This->mipmap_level != 0) {
100 WARN(" application activating a sub-level of the mipmapping chain (level %d) !\n", This->mipmap_level);
104 while (surf_ptr != NULL) {
105 GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */
106 VOID *surface = NULL;
107 DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(surf_ptr->surface_desc);
108 IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
109 BOOL upload_done = FALSE;
112 if (gl_surf_ptr->dirty_flag == FALSE) {
113 TRACE(" - level %d already uploaded.\n", surf_ptr->mipmap_level);
115 TRACE(" - uploading texture level %d (initial done = %d).\n",
116 surf_ptr->mipmap_level, gl_surf_ptr->initial_upload_done);
118 /* Texture snooping for the curious :-) */
119 snoop_texture(surf_ptr);
121 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
125 IDirectDrawPaletteImpl* pal = surf_ptr->palette;
130 if (color_table_queried == FALSE) {
132 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) surf_ptr->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
137 /* Upload a black texture. The real one will be uploaded on palette change */
138 WARN("Palettized texture Loading with a NULL palette !\n");
139 memset(table, 0, 256 * 4);
141 /* Get the surface's palette */
142 for (i = 0; i < 256; i++) {
143 table[i][0] = pal->palents[i].peRed;
144 table[i][1] = pal->palents[i].peGreen;
145 table[i][2] = pal->palents[i].peBlue;
146 if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
147 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
148 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
149 /* We should maybe here put a more 'neutral' color than the standard bright purple
150 one often used by application to prevent the nice purple borders when bi-linear
158 if (ptr_ColorTableEXT != NULL) {
159 /* use Paletted Texture Extension */
160 ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */
161 GL_RGBA, /* internal format */
162 256, /* table size */
163 GL_RGBA, /* table format */
164 GL_UNSIGNED_BYTE, /* table type */
165 table); /* the color table */
167 glTexImage2D(GL_TEXTURE_2D, /* target */
168 surf_ptr->mipmap_level, /* level */
169 GL_COLOR_INDEX8_EXT, /* internal format */
170 src_d->dwWidth, src_d->dwHeight, /* width, height */
172 GL_COLOR_INDEX, /* texture format */
173 GL_UNSIGNED_BYTE, /* texture type */
174 src_d->lpSurface); /* the texture */
179 BYTE *src = (BYTE *) src_d->lpSurface, *dst;
181 surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
182 dst = (BYTE *) surface;
184 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
186 *dst++ = table[color][0];
187 *dst++ = table[color][1];
188 *dst++ = table[color][2];
189 *dst++ = table[color][3];
193 pixel_format = GL_UNSIGNED_BYTE;
195 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
199 if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
200 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xE0) &&
201 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x1C) &&
202 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x03)) {
203 /* **********************
204 GL_UNSIGNED_BYTE_3_3_2
205 ********************** */
206 if (src_d->dwFlags & DDSD_CKSRCBLT) {
207 /* This texture format will never be used.. So do not care about color keying
208 up until the point in time it will be needed :-) */
212 pixel_format = GL_UNSIGNED_BYTE_3_3_2;
217 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
218 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
219 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
220 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
221 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
222 if (src_d->dwFlags & DDSD_CKSRCBLT) {
223 /* Converting the 565 format in 5551 packed to emulate color-keying.
225 Note : in all these conversion, it would be best to average the averaging
226 pixels to get the color of the pixel that will be color-keyed to
227 prevent 'color bleeding'. This will be done later on if ever it is
230 Note2: when using color-keying + alpha, are the alpha bits part of the
234 WORD *src = (WORD *) src_d->lpSurface, *dst;
236 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
237 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
238 dst = (WORD *) surface;
239 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
241 *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
242 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
243 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
249 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
252 pixel_format = GL_UNSIGNED_SHORT_5_6_5;
254 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
255 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07C0) &&
256 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x003E) &&
257 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0001)) {
259 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
260 if (src_d->dwFlags & DDSD_CKSRCBLT) {
261 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
263 WORD *src = (WORD *) src_d->lpSurface, *dst;
265 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
266 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
267 dst = (WORD *) surface;
268 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
270 *dst = color & 0xFFFE;
271 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
272 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
273 *dst |= color & 0x0001;
277 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF000) &&
278 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0F00) &&
279 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x00F0) &&
280 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000F)) {
282 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
283 if (src_d->dwFlags & DDSD_CKSRCBLT) {
284 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
286 WORD *src = (WORD *) src_d->lpSurface, *dst;
288 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
289 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
290 dst = (WORD *) surface;
291 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
293 *dst = color & 0xFFF0;
294 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
295 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
296 *dst |= color & 0x000F;
300 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x0F00) &&
301 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00F0) &&
302 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000F) &&
303 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xF000)) {
304 /* Move the four Alpha bits... */
306 WORD *src = (WORD *) src_d->lpSurface, *dst;
308 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
309 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
312 if (src_d->dwFlags & DDSD_CKSRCBLT) {
313 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
315 *dst = (color & 0x0FFF) << 4;
316 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
317 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
318 *dst |= (color & 0xF000) >> 12;
322 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
324 *dst++ = (((color & 0x0FFF) << 4) |
325 ((color & 0xF000) >> 12));
330 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
331 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x7C00) &&
332 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x03E0) &&
333 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
334 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x8000)) {
335 /* Converting the 1555 format in 5551 packed */
337 WORD *src = (WORD *) src_d->lpSurface, *dst;
339 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
340 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
341 dst = (WORD *) surface;
343 if (src_d->dwFlags & DDSD_CKSRCBLT) {
344 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
346 *dst = (color & 0x7FFF) << 1;
347 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
348 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
349 *dst |= (color & 0x8000) >> 15;
353 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
355 *dst++ = (((color & 0x7FFF) << 1) |
356 ((color & 0x8000) >> 15));
361 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
362 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x7C00) &&
363 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x03E0) &&
364 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
365 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
366 /* Converting the 0555 format in 5551 packed */
368 WORD *src = (WORD *) src_d->lpSurface, *dst;
370 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
371 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
372 dst = (WORD *) surface;
374 if (src_d->dwFlags & DDSD_CKSRCBLT) {
375 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
377 *dst = (color & 0x7FFF) << 1;
378 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
379 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
384 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
386 *dst++ = ((color & 0x7FFF) << 1) | 0x0001;
391 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
395 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
396 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
397 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
398 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
399 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
400 if (src_d->dwFlags & DDSD_CKSRCBLT) {
401 /* This is a pain :-) */
403 BYTE *src = (BYTE *) src_d->lpSurface;
406 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
407 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
408 dst = (DWORD *) surface;
409 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
410 DWORD color = *((DWORD *) src) & 0x00FFFFFF;
413 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
414 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
419 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
422 pixel_format = GL_UNSIGNED_BYTE;
427 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
428 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xFF000000) &&
429 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00FF0000) &&
430 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x0000FF00) &&
431 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000000FF)) {
432 if (src_d->dwFlags & DDSD_CKSRCBLT) {
433 /* Just use the alpha component to handle color-keying... */
435 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
437 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
438 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
439 dst = (DWORD *) surface;
440 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
441 DWORD color = *src++;
442 *dst = color & 0xFFFFFF00;
443 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
444 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
445 *dst |= color & 0x000000FF;
450 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
451 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
452 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
453 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
454 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xFF000000)) {
455 /* Convert from ARGB (Windows' format) to RGBA.
456 Note: need to check for GL extensions handling ARGB instead of always converting */
458 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
460 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
461 dst = (DWORD *) surface;
462 if (src_d->dwFlags & DDSD_CKSRCBLT) {
463 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
464 DWORD color = *src++;
465 *dst = (color & 0x00FFFFFF) << 8;
466 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
467 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
468 *dst |= (color & 0xFF000000) >> 24;
472 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
473 DWORD color = *src++;
474 *dst = (color & 0x00FFFFFF) << 8;
475 *dst |= (color & 0xFF000000) >> 24;
480 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
481 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
482 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
483 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
484 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
485 /* Just add an alpha component and handle color-keying... */
487 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
489 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
490 dst = (DWORD *) surface;
492 if (src_d->dwFlags & DDSD_CKSRCBLT) {
493 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
494 DWORD color = *src++;
496 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
497 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
502 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
503 *dst++ = (*src++ << 8) | 0xFF;
507 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
518 if ((upload_done == FALSE) && (error == FALSE)) {
519 if (gl_surf_ptr->initial_upload_done == FALSE) {
520 glTexImage2D(GL_TEXTURE_2D,
521 surf_ptr->mipmap_level,
523 src_d->dwWidth, src_d->dwHeight,
527 surface == NULL ? src_d->lpSurface : surface);
528 gl_surf_ptr->initial_upload_done = TRUE;
530 glTexSubImage2D(GL_TEXTURE_2D,
531 surf_ptr->mipmap_level,
533 src_d->dwWidth, src_d->dwHeight,
536 surface == NULL ? src_d->lpSurface : surface);
538 gl_surf_ptr->dirty_flag = FALSE;
540 if (surface) HeapFree(GetProcessHeap(), 0, surface);
541 } else if (error == TRUE) {
543 ERR(" unsupported pixel format for textures : \n");
544 DDRAW_dump_pixelformat(&src_d->ddpfPixelFormat);
549 surf_ptr = get_sub_mimaplevel(surf_ptr);
556 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
557 LPDIRECT3DDEVICE lpDirect3DDevice,
558 LPDIRECTDRAWSURFACE lpDDSurface)
560 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
561 FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
566 gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY ckey )
568 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
570 glThis->dirty_flag = TRUE;
571 /* TODO: check color-keying on mipmapped surfaces... */
577 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
581 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
582 FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
587 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
589 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
590 FIXME("(%p/%p)->(): stub!\n", This, iface);
595 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
596 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
597 LPD3DTEXTUREHANDLE lpHandle)
599 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
600 IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
602 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
604 /* The handle is simply the pointer to the implementation structure */
605 *lpHandle = (D3DTEXTUREHANDLE) This;
607 TRACE(" returning handle %08lx.\n", *lpHandle);
609 /* Now set the device for this texture */
610 This->d3ddevice = lpDeviceImpl;
616 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
617 LPDIRECT3DTEXTURE2 lpD3DTexture2)
619 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
620 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
624 static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal)
626 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
628 /* First call the previous set_palette function */
629 glThis->set_palette(This, pal);
631 /* And set the dirty flag */
632 glThis->dirty_flag = TRUE;
634 /* TODO: check palette on mipmapped surfaces... */
638 gltex_final_release(IDirectDrawSurfaceImpl *This)
640 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
644 TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
646 /* And delete texture handle */
648 if (glThis->tex_name != 0)
649 glDeleteTextures(1, &(glThis->tex_name));
652 /* And if this texture was the current one, remove it at the device level */
653 if (This->d3ddevice != NULL)
654 for (i = 0; i < MAX_TEXTURES; i++)
655 if (This->d3ddevice->current_texture[i] == This)
656 This->d3ddevice->current_texture[i] = NULL;
658 /* All this should be part of main surface management not just a hack for texture.. */
659 if (glThis->loaded) {
660 mem_used = This->surface_desc.dwHeight *
661 This->surface_desc.u1.lPitch;
662 This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
665 glThis->final_release(This);
669 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
671 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
673 glThis->lock_update(This, pRect, dwFlags);
677 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
679 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
681 glThis->unlock_update(This, pRect);
683 /* Set the dirty flag according to the lock type */
684 if ((This->lastlocktype & DDLOCK_READONLY) == 0)
685 glThis->dirty_flag = TRUE;
689 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
690 LPDIRECT3DTEXTURE2 lpD3DTexture2)
692 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
693 IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
694 IDirectDrawSurfaceImpl *dst_ptr = This;
695 HRESULT ret_value = D3D_OK;
697 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
699 if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
700 (src_ptr->surface_desc.u2.dwMipMapCount != dst_ptr->surface_desc.u2.dwMipMapCount)) {
701 ERR("Trying to load surfaces with different mip-map counts !\n");
704 /* Now loop through all mipmap levels and load all of them... */
706 IDirect3DTextureGLImpl *gl_dst_ptr = (IDirect3DTextureGLImpl *) dst_ptr->tex_private;
707 DDSURFACEDESC *src_d, *dst_d;
709 if (gl_dst_ptr != NULL) {
710 if (gl_dst_ptr->loaded == FALSE) {
711 /* Only check memory for not already loaded texture... */
712 DWORD mem_used = dst_ptr->surface_desc.dwHeight * dst_ptr->surface_desc.u1.lPitch;
713 if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
714 TRACE(" out of virtual memory... Warning application.\n");
715 return D3DERR_TEXTURE_LOAD_FAILED;
718 gl_dst_ptr->loaded = TRUE;
721 TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, dst_ptr, src_ptr->mipmap_level);
723 if ( dst_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
724 /* If the surface is not allocated and its location is not yet specified,
725 force it to video memory */
726 if ( !(dst_ptr->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
727 dst_ptr->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
729 /* Suppress the ALLOCONLOAD flag */
730 dst_ptr->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
732 /* After seeing some logs, not sure at all about this... */
733 if (dst_ptr->palette == NULL) {
734 dst_ptr->palette = src_ptr->palette;
735 if (src_ptr->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette));
737 if (src_ptr->palette != NULL) {
738 PALETTEENTRY palent[256];
739 IDirectDrawPalette_GetEntries(ICOM_INTERFACE(src_ptr->palette, IDirectDrawPalette),
741 IDirectDrawPalette_SetEntries(ICOM_INTERFACE(dst_ptr->palette, IDirectDrawPalette),
746 /* Copy one surface on the other */
747 dst_d = (DDSURFACEDESC *)&(dst_ptr->surface_desc);
748 src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc);
750 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
751 /* Should also check for same pixel format, u1.lPitch, ... */
752 ERR("Error in surface sizes\n");
753 return D3DERR_TEXTURE_LOAD_FAILED;
755 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
756 /* I should put a macro for the calculus of bpp */
758 /* Copy also the ColorKeying stuff */
759 if (src_d->dwFlags & DDSD_CKSRCBLT) {
760 dst_d->dwFlags |= DDSD_CKSRCBLT;
761 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
762 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
765 /* Copy the main memory texture into the surface that corresponds to the OpenGL
767 memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
769 if (gl_dst_ptr != NULL) {
770 /* If the GetHandle was not done, it is an error... */
771 if (gl_dst_ptr->tex_name == 0) ERR("Unbound GL texture !!!\n");
773 /* Set this texture as dirty */
774 gl_dst_ptr->dirty_flag = TRUE;
778 src_ptr = get_sub_mimaplevel(src_ptr);
779 dst_ptr = get_sub_mimaplevel(dst_ptr);
781 if ((src_ptr == NULL) || (dst_ptr == NULL)) {
782 if (src_ptr != dst_ptr) {
783 ERR(" Loading surface with different mipmap structure !!!\n");
793 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
797 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
798 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
804 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
806 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
807 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
811 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
813 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
814 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
818 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
822 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
823 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
829 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
831 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
832 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
836 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
838 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
839 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
843 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
847 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
848 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
854 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
855 LPDIRECT3DDEVICE lpDirect3DDevice,
856 LPD3DTEXTUREHANDLE lpHandle)
858 TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
859 return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
860 COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
865 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
866 LPDIRECT3DTEXTURE lpD3DTexture)
868 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
869 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
870 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
873 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
874 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture2.fun))
876 # define XCAST(fun) (void*)
879 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
881 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
882 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
883 XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
884 XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
885 XCAST(GetHandle) Main_IDirect3DTextureImpl_2_1T_GetHandle,
886 XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
887 XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
890 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
895 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
896 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture.fun))
898 # define XCAST(fun) (void*)
901 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
903 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
904 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
905 XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
906 XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
907 XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
908 XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
909 XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
910 XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
911 XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
914 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
918 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation,
919 IDirectDrawSurfaceImpl *main)
921 /* First, initialize the texture vtables... */
922 ICOM_INIT_INTERFACE(surf, IDirect3DTexture, VTABLE_IDirect3DTexture);
923 ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
925 /* Only create all the private stuff if we actually have an OpenGL context.. */
926 if (d3d->current_device != NULL) {
927 IDirect3DTextureGLImpl *private;
929 private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
930 if (private == NULL) return DDERR_OUTOFMEMORY;
932 private->final_release = surf->final_release;
933 private->lock_update = surf->lock_update;
934 private->unlock_update = surf->unlock_update;
935 private->set_palette = surf->set_palette;
937 /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
938 Otherwise, it will be uploaded here (and may be invalid). */
939 surf->final_release = gltex_final_release;
940 surf->lock_update = gltex_lock_update;
941 surf->unlock_update = gltex_unlock_update;
942 surf->tex_private = private;
943 surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
944 surf->set_palette = gltex_set_palette;
947 if (surf->mipmap_level == 0) {
948 glGenTextures(1, &(private->tex_name));
949 if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
950 TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
952 private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
953 TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
954 surf, private, private->tex_name, main, main->tex_private);
958 /* And set the dirty flag accordingly */
959 private->dirty_flag = (at_creation == FALSE);
960 private->initial_upload_done = FALSE;