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.pnm", glThis->tex_name);
54 DDRAW_dump_surface_to_disk(This, f);
59 #define snoop_texture(a)
63 /*******************************************************************************
64 * IDirectSurface callback methods
67 gltex_upload_texture(IDirectDrawSurfaceImpl *This) {
68 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
70 static BOOL color_table_queried = FALSE;
72 void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
73 GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
74 BOOL upload_done = FALSE;
76 GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */
79 DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc);
81 glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
83 if (glThis->dirty_flag == FALSE) {
84 TRACE(" activating OpenGL texture id %d.\n", glThis->tex_name);
87 TRACE(" activating and uploading texture id %d (initial done = %d).\n", glThis->tex_name, glThis->initial_upload_done);
90 /* Texture snooping for the curious :-) */
93 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
97 IDirectDrawPaletteImpl* pal = This->palette;
102 if (color_table_queried == FALSE) {
104 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
109 /* Upload a black texture. The real one will be uploaded on palette change */
110 WARN("Palettized texture Loading with a NULL palette !\n");
111 memset(table, 0, 256 * 4);
113 /* Get the surface's palette */
114 for (i = 0; i < 256; i++) {
115 table[i][0] = pal->palents[i].peRed;
116 table[i][1] = pal->palents[i].peGreen;
117 table[i][2] = pal->palents[i].peBlue;
118 if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
119 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
120 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
121 /* We should maybe here put a more 'neutral' color than the standard bright purple
122 one often used by application to prevent the nice purple borders when bi-linear
130 if (ptr_ColorTableEXT != NULL) {
131 /* use Paletted Texture Extension */
132 ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */
133 GL_RGBA, /* internal format */
134 256, /* table size */
135 GL_RGBA, /* table format */
136 GL_UNSIGNED_BYTE, /* table type */
137 table); /* the color table */
139 glTexImage2D(GL_TEXTURE_2D, /* target */
140 This->mipmap_level, /* level */
141 GL_COLOR_INDEX8_EXT, /* internal format */
142 src_d->dwWidth, src_d->dwHeight, /* width, height */
144 GL_COLOR_INDEX, /* texture format */
145 GL_UNSIGNED_BYTE, /* texture type */
146 src_d->lpSurface); /* the texture */
151 BYTE *src = (BYTE *) src_d->lpSurface, *dst;
153 surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
154 dst = (BYTE *) surface;
156 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
158 *dst++ = table[color][0];
159 *dst++ = table[color][1];
160 *dst++ = table[color][2];
161 *dst++ = table[color][3];
165 pixel_format = GL_UNSIGNED_BYTE;
167 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
171 if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
172 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xE0) &&
173 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x1C) &&
174 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x03)) {
175 /* **********************
176 GL_UNSIGNED_BYTE_3_3_2
177 ********************** */
178 if (src_d->dwFlags & DDSD_CKSRCBLT) {
179 /* This texture format will never be used.. So do not care about color keying
180 up until the point in time it will be needed :-) */
184 pixel_format = GL_UNSIGNED_BYTE_3_3_2;
189 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
190 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
191 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
192 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
193 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
194 if (src_d->dwFlags & DDSD_CKSRCBLT) {
195 /* Converting the 565 format in 5551 packed to emulate color-keying.
197 Note : in all these conversion, it would be best to average the averaging
198 pixels to get the color of the pixel that will be color-keyed to
199 prevent 'color bleeding'. This will be done later on if ever it is
202 Note2: when using color-keying + alpha, are the alpha bits part of the
206 WORD *src = (WORD *) src_d->lpSurface, *dst;
208 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
209 dst = (WORD *) surface;
210 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
212 *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
213 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
214 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
220 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
223 pixel_format = GL_UNSIGNED_SHORT_5_6_5;
225 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
226 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x07C0) &&
227 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x003E) &&
228 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0001)) {
230 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
231 if (src_d->dwFlags & DDSD_CKSRCBLT) {
232 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
234 WORD *src = (WORD *) src_d->lpSurface, *dst;
236 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
237 dst = (WORD *) surface;
238 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
240 *dst = color & 0xFFFE;
241 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
242 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
243 *dst |= color & 0x0001;
247 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xF000) &&
248 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0F00) &&
249 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x00F0) &&
250 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000F)) {
252 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
253 if (src_d->dwFlags & DDSD_CKSRCBLT) {
254 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
256 WORD *src = (WORD *) src_d->lpSurface, *dst;
258 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
259 dst = (WORD *) surface;
260 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
262 *dst = color & 0xFFF0;
263 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
264 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
265 *dst |= color & 0x000F;
269 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x0F00) &&
270 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00F0) &&
271 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000F) &&
272 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xF000)) {
273 /* Move the four Alpha bits... */
275 WORD *src = (WORD *) src_d->lpSurface, *dst;
277 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
280 if (src_d->dwFlags & DDSD_CKSRCBLT) {
281 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
283 *dst = (color & 0x0FFF) << 4;
284 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
285 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
286 *dst |= (color & 0xF000) >> 12;
290 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
292 *dst++ = (((color & 0x0FFF) << 4) |
293 ((color & 0xF000) >> 12));
298 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
299 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x7C00) &&
300 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x03E0) &&
301 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
302 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x8000)) {
303 /* Converting the 1555 format in 5551 packed */
305 WORD *src = (WORD *) src_d->lpSurface, *dst;
307 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
308 dst = (WORD *) surface;
310 if (src_d->dwFlags & DDSD_CKSRCBLT) {
311 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
313 *dst = (color & 0x7FFF) << 1;
314 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
315 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
316 *dst |= (color & 0x8000) >> 15;
320 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
322 *dst++ = (((color & 0x7FFF) << 1) |
323 ((color & 0x8000) >> 15));
328 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
332 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
333 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
334 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
335 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
336 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
337 if (src_d->dwFlags & DDSD_CKSRCBLT) {
338 /* This is a pain :-) */
340 BYTE *src = (BYTE *) src_d->lpSurface;
343 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
344 dst = (DWORD *) surface;
345 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
346 DWORD color = *((DWORD *) src) & 0x00FFFFFF;
349 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
350 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
355 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
358 pixel_format = GL_UNSIGNED_BYTE;
363 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
364 if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0xFF000000) &&
365 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x00FF0000) &&
366 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x0000FF00) &&
367 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x000000FF)) {
368 if (src_d->dwFlags & DDSD_CKSRCBLT) {
369 /* Just use the alpha component to handle color-keying... */
371 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
373 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
374 dst = (DWORD *) surface;
375 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
376 DWORD color = *src++;
377 *dst = color & 0xFFFFFF00;
378 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
379 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
380 *dst |= color & 0x000000FF;
385 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
386 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
387 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
388 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
389 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xFF000000)) {
390 /* Convert from ARGB (Windows' format) to RGBA.
391 Note: need to check for GL extensions handling ARGB instead of always converting */
393 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
395 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
396 dst = (DWORD *) surface;
397 if (src_d->dwFlags & DDSD_CKSRCBLT) {
398 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
399 DWORD color = *src++;
400 *dst = (color & 0x00FFFFFF) << 8;
401 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
402 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
403 *dst |= (color & 0xFF000000) >> 24;
407 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
408 DWORD color = *src++;
409 *dst = (color & 0x00FFFFFF) << 8;
410 *dst |= (color & 0xFF000000) >> 24;
414 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
415 } else if ((src_d->ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
416 (src_d->ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
417 (src_d->ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
418 (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
419 /* Just add an alpha component and handle color-keying... */
421 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
423 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
424 dst = (DWORD *) surface;
426 if (src_d->dwFlags & DDSD_CKSRCBLT) {
427 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
428 DWORD color = *src++;
430 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
431 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
436 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
437 *dst++ = (*src++ << 8) | 0xFF;
441 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
452 if ((upload_done == FALSE) && (error == FALSE)) {
453 if (glThis->initial_upload_done == FALSE) {
454 glTexImage2D(GL_TEXTURE_2D,
457 src_d->dwWidth, src_d->dwHeight,
461 surface == NULL ? src_d->lpSurface : surface);
462 glThis->initial_upload_done = TRUE;
464 glTexSubImage2D(GL_TEXTURE_2D,
467 src_d->dwWidth, src_d->dwHeight,
470 surface == NULL ? src_d->lpSurface : surface);
473 if (surface) HeapFree(GetProcessHeap(), 0, surface);
474 } else if (error == TRUE) {
476 ERR("Unsupported pixel format for textures : \n");
477 DDRAW_dump_pixelformat(&src_d->ddpfPixelFormat);
481 glThis->dirty_flag = FALSE;
487 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
488 LPDIRECT3DDEVICE lpDirect3DDevice,
489 LPDIRECTDRAWSURFACE lpDDSurface)
491 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
492 FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
497 gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY ckey )
499 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
501 glThis->dirty_flag = TRUE;
507 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
511 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
512 FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
517 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
519 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
520 FIXME("(%p/%p)->(): stub!\n", This, iface);
525 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
526 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
527 LPD3DTEXTUREHANDLE lpHandle)
529 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
530 IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
532 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
534 /* The handle is simply the pointer to the implementation structure */
535 *lpHandle = (D3DTEXTUREHANDLE) This;
537 TRACE(" returning handle %08lx.\n", *lpHandle);
539 /* Now set the device for this texture */
540 This->d3ddevice = lpDeviceImpl;
546 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
547 LPDIRECT3DTEXTURE2 lpD3DTexture2)
549 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
550 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
554 static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal)
556 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
558 /* First call the previous set_palette function */
559 glThis->set_palette(This, pal);
561 /* And set the dirty flag */
562 glThis->dirty_flag = TRUE;
566 gltex_final_release(IDirectDrawSurfaceImpl *This)
568 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
572 TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
574 /* And delete texture handle */
576 if (glThis->tex_name != 0)
577 glDeleteTextures(1, &(glThis->tex_name));
580 /* And if this texture was the current one, remove it at the device level */
581 if (This->d3ddevice != NULL)
582 for (i = 0; i < MAX_TEXTURES; i++)
583 if (This->d3ddevice->current_texture[i] == This)
584 This->d3ddevice->current_texture[i] = NULL;
586 /* All this should be part of main surface management not just a hack for texture.. */
587 if (glThis->loaded) {
588 mem_used = This->surface_desc.dwHeight *
589 This->surface_desc.u1.lPitch;
590 This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
593 glThis->final_release(This);
597 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
599 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
601 glThis->lock_update(This, pRect, dwFlags);
605 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
607 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
609 glThis->unlock_update(This, pRect);
611 /* Set the dirty flag according to the lock type */
612 if ((This->lastlocktype & DDLOCK_READONLY) == 0)
613 glThis->dirty_flag = TRUE;
617 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
618 LPDIRECT3DTEXTURE2 lpD3DTexture2)
620 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
621 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
622 IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
624 DDSURFACEDESC *src_d, *dst_d;
625 HRESULT ret_value = D3D_OK;
627 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
629 if (glThis != NULL) {
630 if (glThis->loaded == FALSE) {
631 /* Only check memory for not already loaded texture... */
632 mem_used = This->surface_desc.dwHeight *
633 This->surface_desc.u1.lPitch;
634 if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
635 TRACE(" out of virtual memory... Warning application.\n");
636 return D3DERR_TEXTURE_LOAD_FAILED;
639 glThis->loaded = TRUE;
642 TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This);
644 if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
645 /* If the surface is not allocated and its location is not yet specified,
646 force it to video memory */
647 if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
648 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
650 /* Suppress the ALLOCONLOAD flag */
651 This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
653 /* After seeing some logs, not sure at all about this... */
654 if (This->palette == NULL) {
655 This->palette = lpD3DTextureImpl->palette;
656 if (lpD3DTextureImpl->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(lpD3DTextureImpl->palette,
657 IDirectDrawPalette));
659 if (lpD3DTextureImpl->palette != NULL) {
660 PALETTEENTRY palent[256];
661 IDirectDrawPalette *pal_int = ICOM_INTERFACE(lpD3DTextureImpl->palette, IDirectDrawPalette);
662 IDirectDrawPalette_GetEntries(pal_int, 0, 0, 256, palent);
663 IDirectDrawPalette_SetEntries(ICOM_INTERFACE(This->palette, IDirectDrawPalette),
668 /* Copy one surface on the other */
669 dst_d = (DDSURFACEDESC *)&(This->surface_desc);
670 src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc);
672 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
673 /* Should also check for same pixel format, u1.lPitch, ... */
674 ERR("Error in surface sizes\n");
675 return D3DERR_TEXTURE_LOAD_FAILED;
677 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
678 /* I should put a macro for the calculus of bpp */
680 /* Copy also the ColorKeying stuff */
681 if (src_d->dwFlags & DDSD_CKSRCBLT) {
682 dst_d->dwFlags |= DDSD_CKSRCBLT;
683 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
684 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
687 /* Copy the main memory texture into the surface that corresponds to the OpenGL
689 memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
691 if (glThis != NULL) {
692 /* If the GetHandle was not done, it is an error... */
693 if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
695 /* Set this texture as dirty */
696 glThis->dirty_flag = TRUE;
704 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
708 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
709 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
715 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
717 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
718 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
722 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
724 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
725 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
729 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
733 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
734 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
740 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
742 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
743 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
747 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
749 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
750 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
754 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
758 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
759 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
765 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
766 LPDIRECT3DDEVICE lpDirect3DDevice,
767 LPD3DTEXTUREHANDLE lpHandle)
769 TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
770 return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
771 COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
776 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
777 LPDIRECT3DTEXTURE lpD3DTexture)
779 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
780 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
781 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
784 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
785 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture2.fun))
787 # define XCAST(fun) (void*)
790 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
792 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
793 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
794 XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
795 XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
796 XCAST(GetHandle) Main_IDirect3DTextureImpl_2_1T_GetHandle,
797 XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
798 XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
801 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
806 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
807 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture.fun))
809 # define XCAST(fun) (void*)
812 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
814 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
815 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
816 XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
817 XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
818 XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
819 XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
820 XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
821 XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
822 XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
825 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
829 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation,
830 IDirectDrawSurfaceImpl *main)
832 /* First, initialize the texture vtables... */
833 ICOM_INIT_INTERFACE(surf, IDirect3DTexture, VTABLE_IDirect3DTexture);
834 ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
836 /* Only create all the private stuff if we actually have an OpenGL context.. */
837 if (d3d->current_device != NULL) {
838 IDirect3DTextureGLImpl *private;
840 private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
841 if (private == NULL) return DDERR_OUTOFMEMORY;
843 private->final_release = surf->final_release;
844 private->lock_update = surf->lock_update;
845 private->unlock_update = surf->unlock_update;
846 private->set_palette = surf->set_palette;
848 /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
849 Otherwise, it will be uploaded here (and may be invalid). */
850 surf->final_release = gltex_final_release;
851 surf->lock_update = gltex_lock_update;
852 surf->unlock_update = gltex_unlock_update;
853 surf->tex_private = private;
854 surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
855 surf->set_palette = gltex_set_palette;
858 if (surf->mipmap_level == 0) {
859 glGenTextures(1, &(private->tex_name));
860 if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
861 TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
863 private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
864 TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
865 surf, private, private->tex_name, main, main->tex_private);
869 /* And set the dirty flag accordingly */
870 private->dirty_flag = (at_creation == FALSE);
871 private->initial_upload_done = FALSE;