Added 'blt' and 'bltfast' override functions.
[wine/multimedia.git] / dlls / ddraw / d3dtexture.c
blob96c21eb32c7230aa6c6d272f689bd97be2111b7f
1 /* Direct3D Texture
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
21 #include "config.h"
23 #include <string.h>
25 #include "windef.h"
26 #include "winerror.h"
27 #include "objbase.h"
28 #include "ddraw.h"
29 #include "d3d.h"
30 #include "wine/debug.h"
32 #include "mesa_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 /* Define this if you want to save to a file all the textures used by a game
37 (can be funny to see how they managed to cram all the pictures in
38 texture memory) */
39 #undef TEXTURE_SNOOP
41 #ifdef TEXTURE_SNOOP
42 #include <stdio.h>
44 static void snoop_texture(IDirectDrawSurfaceImpl *This) {
45 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
46 char buf[128];
47 FILE *f;
49 sprintf(buf, "tex_%05d.pnm", glThis->tex_name);
50 f = fopen(buf, "wb");
51 DDRAW_dump_surface_to_disk(This, f);
54 #else
56 #define snoop_texture(a)
58 #endif
60 /*******************************************************************************
61 * IDirectSurface callback methods
63 HRESULT gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
65 DDSURFACEDESC *tex_d;
66 GLuint current_texture;
67 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) texture->tex_private;
69 TRACE("(%p) : colorkey callback\n", texture);
71 /* Get the texture description */
72 tex_d = (DDSURFACEDESC *)&(texture->surface_desc);
74 /* Now, save the current texture */
75 ENTER_GL();
76 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
77 if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
78 glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
80 if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
81 FIXME("Todo Paletted\n");
82 } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
83 if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
84 FIXME("Todo 3_3_2_0\n");
85 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
86 if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
87 /* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
88 unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
89 HEAP_ZERO_MEMORY,
90 tex_d->u1.lPitch * tex_d->dwHeight);
91 unsigned short *src = (unsigned short *) tex_d->lpSurface;
92 int x, y;
94 for (y = 0; y < tex_d->dwHeight; y++) {
95 for (x = 0; x < tex_d->dwWidth; x++) {
96 unsigned short cpixel = src[x + y * tex_d->dwWidth];
98 if ((dwFlags & DDCKEY_SRCBLT) &&
99 (cpixel >= ckey->dwColorSpaceLowValue) &&
100 (cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
101 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
102 else /* Alpha bit is set => this pixel will be seen */
103 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001;
107 glTexSubImage2D(GL_TEXTURE_2D,
108 texture->mipmap_level,
109 0, 0,
110 tex_d->dwWidth, tex_d->dwHeight,
111 GL_RGBA,
112 GL_UNSIGNED_SHORT_5_5_5_1,
113 dest);
115 /* Frees the temporary surface */
116 HeapFree(GetProcessHeap(),0,dest);
117 } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
118 FIXME("Todo 5_5_5_1\n");
119 } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
120 FIXME("Todo 4_4_4_4\n");
121 } else {
122 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
124 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
125 FIXME("Todo 8_8_8_0\n");
126 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
127 FIXME("Todo 8_8_8_8\n");
128 } else {
129 ERR("Unhandled texture format (bad RGB count)\n");
131 } else {
132 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
134 glBindTexture(GL_TEXTURE_2D, current_texture);
135 LEAVE_GL();
137 return DD_OK;
140 static HRESULT
141 gltex_upload_texture(IDirectDrawSurfaceImpl *This, BOOLEAN init_upload) {
142 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
143 GLuint current_texture;
144 #if 0
145 static BOOL color_table_queried = FALSE;
146 #endif
147 void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
148 GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
149 BOOL upload_done = FALSE;
150 BOOL error = FALSE;
151 GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */
152 VOID *surface = NULL;
154 DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc);
156 TRACE(" uploading texture to GL id %d (initial = %d).\n", glThis->tex_name, init_upload);
158 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
159 glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
161 /* Texture snooping for the curious :-) */
162 snoop_texture(This);
164 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
165 /* ****************
166 Paletted Texture
167 **************** */
168 IDirectDrawPaletteImpl* pal = This->palette;
169 BYTE table[256][4];
170 int i;
172 #if 0
173 if (color_table_queried == FALSE) {
174 ptr_ColorTableEXT =
175 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
177 #endif
179 if (pal == NULL) {
180 ERR("Palettized texture Loading with a NULL palette !\n");
181 glBindTexture(GL_TEXTURE_2D, current_texture);
182 return D3DERR_INVALIDPALETTE;
184 /* Get the surface's palette */
185 for (i = 0; i < 256; i++) {
186 table[i][0] = pal->palents[i].peRed;
187 table[i][1] = pal->palents[i].peGreen;
188 table[i][2] = pal->palents[i].peBlue;
189 if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
190 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
191 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
192 table[i][3] = 0x00;
193 else
194 table[i][3] = 0xFF;
197 if (ptr_ColorTableEXT != NULL) {
198 /* use Paletted Texture Extension */
199 ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */
200 GL_RGBA, /* internal format */
201 256, /* table size */
202 GL_RGBA, /* table format */
203 GL_UNSIGNED_BYTE, /* table type */
204 table); /* the color table */
206 glTexImage2D(GL_TEXTURE_2D, /* target */
207 This->mipmap_level, /* level */
208 GL_COLOR_INDEX8_EXT, /* internal format */
209 src_d->dwWidth, src_d->dwHeight, /* width, height */
210 0, /* border */
211 GL_COLOR_INDEX, /* texture format */
212 GL_UNSIGNED_BYTE, /* texture type */
213 src_d->lpSurface); /* the texture */
215 upload_done = TRUE;
216 } else {
217 DWORD i;
218 BYTE *src = (BYTE *) src_d->lpSurface, *dst;
220 surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
221 dst = (BYTE *) surface;
223 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
224 BYTE color = *src++;
225 *dst++ = table[color][0];
226 *dst++ = table[color][1];
227 *dst++ = table[color][2];
228 *dst++ = table[color][3];
231 format = GL_RGBA;
232 pixel_format = GL_UNSIGNED_BYTE;
234 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
235 /* ************
236 RGB Textures
237 ************ */
238 if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
239 /* **********************
240 GL_UNSIGNED_BYTE_3_3_2
241 ********************** */
242 format = GL_RGB;
243 pixel_format = GL_UNSIGNED_BYTE_3_3_2;
244 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
245 if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
246 format = GL_RGB;
247 pixel_format = GL_UNSIGNED_SHORT_5_6_5;
248 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
249 format = GL_RGBA;
250 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
251 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
252 format = GL_RGBA;
253 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
254 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000F000) {
255 /* Move the four Alpha bits... */
256 DWORD i;
257 WORD *src = (WORD *) src_d->lpSurface, *dst;
259 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
260 dst = surface;
262 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
263 *dst++ = (((*src & 0xFFF0) >> 4) |
264 ((*src & 0x000F) << 12));
265 src++;
268 format = GL_RGBA;
269 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
270 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00008000) {
271 /* Converting the 1555 format in 5551 packed */
272 DWORD i;
273 WORD *src = (WORD *) src_d->lpSurface, *dst;
275 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
276 dst = (WORD *) surface;
277 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
278 *dst++ = (((*src & 0x8000) >> 15) |
279 ((*src & 0x7FFF) << 1));
280 src++;
283 format = GL_RGBA;
284 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
285 } else {
286 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
287 error = TRUE;
289 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
290 format = GL_RGB;
291 pixel_format = GL_UNSIGNED_BYTE;
292 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
293 format = GL_RGBA;
294 pixel_format = GL_UNSIGNED_BYTE;
295 } else {
296 ERR("Unhandled texture format (bad RGB count)\n");
297 error = TRUE;
299 } else {
300 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
301 error = TRUE;
304 if ((upload_done == FALSE) && (error == FALSE)) {
305 if (init_upload)
306 glTexImage2D(GL_TEXTURE_2D,
307 This->mipmap_level,
308 format,
309 src_d->dwWidth, src_d->dwHeight,
311 format,
312 pixel_format,
313 surface == NULL ? src_d->lpSurface : surface);
314 else
315 glTexSubImage2D(GL_TEXTURE_2D,
316 This->mipmap_level,
317 0, 0,
318 src_d->dwWidth, src_d->dwHeight,
319 format,
320 pixel_format,
321 surface == NULL ? src_d->lpSurface : surface);
322 if (surface) HeapFree(GetProcessHeap(), 0, surface);
325 glBindTexture(GL_TEXTURE_2D, current_texture);
326 return DD_OK;
329 HRESULT WINAPI
330 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
331 LPDIRECT3DDEVICE lpDirect3DDevice,
332 LPDIRECTDRAWSURFACE lpDDSurface)
334 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
335 FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
336 return DD_OK;
339 HRESULT WINAPI
340 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
341 DWORD dwStart,
342 DWORD dwCount)
344 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
345 FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
346 return DD_OK;
349 HRESULT WINAPI
350 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
352 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
353 FIXME("(%p/%p)->(): stub!\n", This, iface);
354 return DD_OK;
357 HRESULT WINAPI
358 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
359 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
360 LPD3DTEXTUREHANDLE lpHandle)
362 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
363 FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpDirect3DDevice2, lpHandle);
364 return DD_OK;
367 HRESULT WINAPI
368 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
369 LPDIRECT3DTEXTURE2 lpD3DTexture2)
371 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
372 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
373 return DD_OK;
376 static void
377 gltex_final_release(IDirectDrawSurfaceImpl *This)
379 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
380 DWORD mem_used;
382 TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
384 /* And delete texture handle */
385 ENTER_GL();
386 if (glThis->tex_name != 0)
387 glDeleteTextures(1, &(glThis->tex_name));
388 LEAVE_GL();
390 /* And if this texture was the current one, remove it at the device level */
391 if (This->d3ddevice != NULL)
392 if (This->d3ddevice->current_texture[0] == This)
393 This->d3ddevice->current_texture[0] = NULL;
395 /* All this should be part of main surface management not just a hack for texture.. */
396 if (glThis->loaded) {
397 mem_used = This->surface_desc.dwHeight *
398 This->surface_desc.u1.lPitch;
399 This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
402 glThis->final_release(This);
405 static void
406 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
408 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
410 glThis->lock_update(This, pRect, dwFlags);
413 static void
414 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
416 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
418 ENTER_GL();
419 gltex_upload_texture(This, glThis->first_unlock);
420 LEAVE_GL();
421 glThis->first_unlock = FALSE;
423 glThis->unlock_update(This, pRect);
426 HRESULT WINAPI
427 GL_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
428 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
429 LPD3DTEXTUREHANDLE lpHandle)
431 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
432 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
433 IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
435 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
437 /* The handle is simply the pointer to the implementation structure */
438 *lpHandle = (D3DTEXTUREHANDLE) This;
440 TRACE(" returning handle %08lx.\n", *lpHandle);
442 /* Now, bind a new texture */
443 This->d3ddevice = lpDeviceImpl;
445 /* Associate the texture with the device and perform the appropriate AddRef/Release */
446 /* FIXME: Is there only one or several textures associated with the device ? */
447 if (lpDeviceImpl->current_texture[0] != NULL)
448 IDirectDrawSurface7_Release(ICOM_INTERFACE(lpDeviceImpl->current_texture[0], IDirectDrawSurface7));
449 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(This, IDirectDrawSurface7));
450 lpDeviceImpl->current_texture[0] = This;
452 TRACE("OpenGL texture handle is : %d\n", glThis->tex_name);
454 return D3D_OK;
457 HRESULT WINAPI
458 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
459 LPDIRECT3DTEXTURE2 lpD3DTexture2)
461 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
462 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
463 IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
464 DWORD mem_used;
465 DDSURFACEDESC *src_d, *dst_d;
466 HRESULT ret_value = D3D_OK;
468 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
470 if (glThis != NULL) {
471 if (glThis->loaded == FALSE) {
472 /* Only check memory for not already loaded texture... */
473 mem_used = This->surface_desc.dwHeight *
474 This->surface_desc.u1.lPitch;
475 if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
476 TRACE(" out of virtual memory... Warning application.\n");
477 return D3DERR_TEXTURE_LOAD_FAILED;
480 glThis->loaded = TRUE;
483 TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This);
485 if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
486 /* If the surface is not allocated and its location is not yet specified,
487 force it to video memory */
488 if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
489 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
491 /* Suppress the ALLOCONLOAD flag */
492 This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
493 This->palette = lpD3DTextureImpl->palette;
495 /* Copy one surface on the other */
496 dst_d = (DDSURFACEDESC *)&(This->surface_desc);
497 src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc);
499 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
500 /* Should also check for same pixel format, u1.lPitch, ... */
501 ERR("Error in surface sizes\n");
502 return D3DERR_TEXTURE_LOAD_FAILED;
503 } else {
504 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
505 /* I should put a macro for the calculus of bpp */
507 /* Copy also the ColorKeying stuff */
508 if (src_d->dwFlags & DDSD_CKSRCBLT) {
509 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
510 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
513 /* Copy the main memry texture into the surface that corresponds to the OpenGL
514 texture object. */
515 memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
517 if (glThis != NULL) {
518 /* If the GetHandle was not done, it is an error... */
519 if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
521 ENTER_GL();
523 /* Now, load the texture */
524 /* d3dd->set_context(d3dd); We need to set the context somehow.... */
526 ret_value = gltex_upload_texture(This, glThis->first_unlock);
527 glThis->first_unlock = FALSE;
529 LEAVE_GL();
533 return ret_value;
536 HRESULT WINAPI
537 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
538 REFIID riid,
539 LPVOID* obp)
541 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
542 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
543 riid,
544 obp);
547 ULONG WINAPI
548 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
550 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
551 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
554 ULONG WINAPI
555 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
557 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
558 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
561 HRESULT WINAPI
562 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
563 REFIID riid,
564 LPVOID* obp)
566 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
567 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
568 riid,
569 obp);
572 ULONG WINAPI
573 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
575 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
576 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
579 ULONG WINAPI
580 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
582 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
583 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
586 HRESULT WINAPI
587 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
588 DWORD dwStart,
589 DWORD dwCount)
591 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
592 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
593 dwStart,
594 dwCount);
597 HRESULT WINAPI
598 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
599 LPDIRECT3DDEVICE lpDirect3DDevice,
600 LPD3DTEXTUREHANDLE lpHandle)
602 TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
603 return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
604 COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
605 lpHandle);
608 HRESULT WINAPI
609 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
610 LPDIRECT3DTEXTURE lpD3DTexture)
612 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
613 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
614 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
617 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
618 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture2.fun))
619 #else
620 # define XCAST(fun) (void*)
621 #endif
623 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
625 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
626 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
627 XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
628 XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
629 XCAST(GetHandle) GL_IDirect3DTextureImpl_2_1T_GetHandle,
630 XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
631 XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
634 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
635 #undef XCAST
636 #endif
639 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
640 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture.fun))
641 #else
642 # define XCAST(fun) (void*)
643 #endif
645 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
647 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
648 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
649 XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
650 XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
651 XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
652 XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
653 XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
654 XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
655 XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
658 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
659 #undef XCAST
660 #endif
662 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation,
663 IDirectDrawSurfaceImpl *main)
665 IDirect3DGLImpl *gl_d3d = (IDirect3DGLImpl *) d3d;
667 /* First, initialize the texture vtables... */
668 ICOM_INIT_INTERFACE(surf, IDirect3DTexture, VTABLE_IDirect3DTexture);
669 ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
671 /* Only create all the private stuff if we actually have an OpenGL context.. */
672 if (gl_d3d->current_device != NULL) {
673 IDirect3DTextureGLImpl *private;
675 private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
676 if (private == NULL) return DDERR_OUTOFMEMORY;
678 private->final_release = surf->final_release;
679 private->lock_update = surf->lock_update;
680 private->unlock_update = surf->unlock_update;
682 /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
683 Otherwise, it will be uploaded here (and may be invalid). */
684 if (at_creation == TRUE)
685 private->first_unlock = TRUE;
686 else
687 private->first_unlock = FALSE;
688 surf->final_release = gltex_final_release;
689 surf->lock_update = gltex_lock_update;
690 surf->unlock_update = gltex_unlock_update;
691 surf->tex_private = private;
692 surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
694 ENTER_GL();
695 if (surf->mipmap_level == 0) {
696 glGenTextures(1, &(private->tex_name));
697 if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
698 TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
699 } else {
700 private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
701 TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
702 surf, private, private->tex_name, main, main->tex_private);
705 if ((at_creation == FALSE) &&
706 ((surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) == 0))
708 gltex_upload_texture(surf, TRUE);
710 LEAVE_GL();
713 return D3D_OK;