Define NONAMELESS{STRUCT,UNION} explicitly in the files that need them.
[wine/wine-kai.git] / dlls / ddraw / d3dtexture.c
blob1cbe3ee60d395ce24062cf28a80985e607868fc2
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 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winerror.h"
29 #include "objbase.h"
30 #include "ddraw.h"
31 #include "d3d.h"
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
40 texture memory) */
41 #undef TEXTURE_SNOOP
43 #ifdef TEXTURE_SNOOP
44 #include <stdio.h>
46 static void
47 snoop_texture(IDirectDrawSurfaceImpl *This) {
48 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
49 char buf[128];
50 FILE *f;
52 sprintf(buf, "tex_%05d.pnm", glThis->tex_name);
53 f = fopen(buf, "wb");
54 DDRAW_dump_surface_to_disk(This, f);
57 #else
59 #define snoop_texture(a)
61 #endif
63 /*******************************************************************************
64 * IDirectSurface callback methods
66 HRESULT
67 gltex_upload_texture(IDirectDrawSurfaceImpl *This) {
68 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
69 #if 0
70 static BOOL color_table_queried = FALSE;
71 #endif
72 void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
73 GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
74 BOOL upload_done = FALSE;
75 BOOL error = FALSE;
76 GLenum format = GL_RGBA, pixel_format = GL_UNSIGNED_BYTE; /* This is only to prevent warnings.. */
77 VOID *surface = NULL;
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);
85 return DD_OK;
86 } else {
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 :-) */
91 snoop_texture(This);
93 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
94 /* ****************
95 Paletted Texture
96 **************** */
97 IDirectDrawPaletteImpl* pal = This->palette;
98 BYTE table[256][4];
99 int i;
101 #if 0
102 if (color_table_queried == FALSE) {
103 ptr_ColorTableEXT =
104 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
106 #endif
108 if (pal == NULL) {
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);
112 } else {
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
123 filtering is on */
124 table[i][3] = 0x00;
125 else
126 table[i][3] = 0xFF;
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 */
143 0, /* border */
144 GL_COLOR_INDEX, /* texture format */
145 GL_UNSIGNED_BYTE, /* texture type */
146 src_d->lpSurface); /* the texture */
148 upload_done = TRUE;
149 } else {
150 DWORD i;
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++) {
157 BYTE color = *src++;
158 *dst++ = table[color][0];
159 *dst++ = table[color][1];
160 *dst++ = table[color][2];
161 *dst++ = table[color][3];
164 format = GL_RGBA;
165 pixel_format = GL_UNSIGNED_BYTE;
167 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
168 /* ************
169 RGB Textures
170 ************ */
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 :-) */
181 error = TRUE;
182 } else {
183 format = GL_RGB;
184 pixel_format = GL_UNSIGNED_BYTE_3_3_2;
186 } else {
187 error = TRUE;
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
200 too visible.
202 Note2: when using color-keying + alpha, are the alpha bits part of the
203 color-space or not ?
205 DWORD i;
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++) {
211 WORD color = *src++;
212 *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
213 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
214 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
215 *dst |= 0x0001;
216 dst++;
219 format = GL_RGBA;
220 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
221 } else {
222 format = GL_RGB;
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)) {
229 format = GL_RGBA;
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. */
233 DWORD i;
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++) {
239 WORD color = *src++;
240 *dst = color & 0xFFFE;
241 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
242 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
243 *dst |= color & 0x0001;
244 dst++;
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)) {
251 format = GL_RGBA;
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. */
255 DWORD i;
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++) {
261 WORD color = *src++;
262 *dst = color & 0xFFF0;
263 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
264 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
265 *dst |= color & 0x000F;
266 dst++;
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... */
274 DWORD i;
275 WORD *src = (WORD *) src_d->lpSurface, *dst;
277 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
278 dst = surface;
280 if (src_d->dwFlags & DDSD_CKSRCBLT) {
281 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
282 WORD color = *src++;
283 *dst = (color & 0x0FFF) << 4;
284 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
285 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
286 *dst |= (color & 0xF000) >> 12;
287 dst++;
289 } else {
290 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
291 WORD color = *src++;
292 *dst++ = (((color & 0x0FFF) << 4) |
293 ((color & 0xF000) >> 12));
297 format = GL_RGBA;
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 */
304 DWORD i;
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++) {
312 WORD color = *src++;
313 *dst = (color & 0x7FFF) << 1;
314 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
315 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
316 *dst |= (color & 0x8000) >> 15;
317 dst++;
319 } else {
320 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
321 WORD color = *src++;
322 *dst++ = (((color & 0x7FFF) << 1) |
323 ((color & 0x8000) >> 15));
327 format = GL_RGBA;
328 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
329 } else {
330 error = TRUE;
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 :-) */
339 DWORD i;
340 BYTE *src = (BYTE *) src_d->lpSurface;
341 DWORD *dst;
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;
347 src += 3;
348 *dst = *src++ << 8;
349 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
350 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
351 *dst |= 0xFF;
352 dst++;
354 format = GL_RGBA;
355 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
356 } else {
357 format = GL_BGR;
358 pixel_format = GL_UNSIGNED_BYTE;
360 } else {
361 error = TRUE;
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... */
370 DWORD i;
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;
381 dst++;
384 format = GL_RGBA;
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 == 0x00000000)) {
390 /* Just add an alpha component and handle color-keying... */
391 DWORD i;
392 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
394 surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
395 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 << 8;
401 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
402 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
403 *dst |= 0xFF;
404 dst++;
406 } else {
407 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
408 *dst++ = (*src++ << 8) | 0xFF;
411 format = GL_RGBA;
412 pixel_format = GL_UNSIGNED_INT_8_8_8_8;
413 } else {
414 error = TRUE;
416 } else {
417 error = TRUE;
419 } else {
420 error = TRUE;
423 if ((upload_done == FALSE) && (error == FALSE)) {
424 if (glThis->initial_upload_done == FALSE) {
425 glTexImage2D(GL_TEXTURE_2D,
426 This->mipmap_level,
427 format,
428 src_d->dwWidth, src_d->dwHeight,
430 format,
431 pixel_format,
432 surface == NULL ? src_d->lpSurface : surface);
433 glThis->initial_upload_done = TRUE;
434 } else {
435 glTexSubImage2D(GL_TEXTURE_2D,
436 This->mipmap_level,
437 0, 0,
438 src_d->dwWidth, src_d->dwHeight,
439 format,
440 pixel_format,
441 surface == NULL ? src_d->lpSurface : surface);
444 if (surface) HeapFree(GetProcessHeap(), 0, surface);
445 } else if (error == TRUE) {
446 if (ERR_ON(ddraw)) {
447 ERR("Unsupported pixel format for textures : \n");
448 DDRAW_dump_pixelformat(&src_d->ddpfPixelFormat);
452 glThis->dirty_flag = FALSE;
454 return DD_OK;
457 HRESULT WINAPI
458 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
459 LPDIRECT3DDEVICE lpDirect3DDevice,
460 LPDIRECTDRAWSURFACE lpDDSurface)
462 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
463 FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
464 return DD_OK;
467 static HRESULT
468 gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY ckey )
470 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
472 glThis->dirty_flag = TRUE;
474 return DD_OK;
477 HRESULT WINAPI
478 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
479 DWORD dwStart,
480 DWORD dwCount)
482 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
483 FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
484 return DD_OK;
487 HRESULT WINAPI
488 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
490 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
491 FIXME("(%p/%p)->(): stub!\n", This, iface);
492 return DD_OK;
495 HRESULT WINAPI
496 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
497 LPDIRECT3DDEVICE2 lpDirect3DDevice2,
498 LPD3DTEXTUREHANDLE lpHandle)
500 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
501 IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
503 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
505 /* The handle is simply the pointer to the implementation structure */
506 *lpHandle = (D3DTEXTUREHANDLE) This;
508 TRACE(" returning handle %08lx.\n", *lpHandle);
510 /* Now set the device for this texture */
511 This->d3ddevice = lpDeviceImpl;
513 return D3D_OK;
516 HRESULT WINAPI
517 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
518 LPDIRECT3DTEXTURE2 lpD3DTexture2)
520 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
521 FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
522 return DD_OK;
525 static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal)
527 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
529 /* First call the previous set_palette function */
530 glThis->set_palette(This, pal);
532 /* And set the dirty flag */
533 glThis->dirty_flag = TRUE;
536 static void
537 gltex_final_release(IDirectDrawSurfaceImpl *This)
539 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
540 DWORD mem_used;
541 int i;
543 TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
545 /* And delete texture handle */
546 ENTER_GL();
547 if (glThis->tex_name != 0)
548 glDeleteTextures(1, &(glThis->tex_name));
549 LEAVE_GL();
551 /* And if this texture was the current one, remove it at the device level */
552 if (This->d3ddevice != NULL)
553 for (i = 0; i < MAX_TEXTURES; i++)
554 if (This->d3ddevice->current_texture[i] == This)
555 This->d3ddevice->current_texture[i] = NULL;
557 /* All this should be part of main surface management not just a hack for texture.. */
558 if (glThis->loaded) {
559 mem_used = This->surface_desc.dwHeight *
560 This->surface_desc.u1.lPitch;
561 This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
564 glThis->final_release(This);
567 static void
568 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
570 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
572 glThis->lock_update(This, pRect, dwFlags);
575 static void
576 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
578 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
580 glThis->unlock_update(This, pRect);
582 /* Set the dirty flag according to the lock type */
583 if ((This->lastlocktype & DDLOCK_READONLY) == 0)
584 glThis->dirty_flag = TRUE;
587 HRESULT WINAPI
588 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
589 LPDIRECT3DTEXTURE2 lpD3DTexture2)
591 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
592 IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
593 IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
594 DWORD mem_used;
595 DDSURFACEDESC *src_d, *dst_d;
596 HRESULT ret_value = D3D_OK;
598 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
600 if (glThis != NULL) {
601 if (glThis->loaded == FALSE) {
602 /* Only check memory for not already loaded texture... */
603 mem_used = This->surface_desc.dwHeight *
604 This->surface_desc.u1.lPitch;
605 if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
606 TRACE(" out of virtual memory... Warning application.\n");
607 return D3DERR_TEXTURE_LOAD_FAILED;
610 glThis->loaded = TRUE;
613 TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This);
615 if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
616 /* If the surface is not allocated and its location is not yet specified,
617 force it to video memory */
618 if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
619 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
621 /* Suppress the ALLOCONLOAD flag */
622 This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
624 /* After seeing some logs, not sure at all about this... */
625 if (This->palette == NULL) {
626 This->palette = lpD3DTextureImpl->palette;
627 if (lpD3DTextureImpl->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(lpD3DTextureImpl->palette,
628 IDirectDrawPalette));
629 } else {
630 if (lpD3DTextureImpl->palette != NULL) {
631 PALETTEENTRY palent[256];
632 IDirectDrawPalette *pal_int = ICOM_INTERFACE(lpD3DTextureImpl->palette, IDirectDrawPalette);
633 IDirectDrawPalette_GetEntries(pal_int, 0, 0, 256, palent);
634 IDirectDrawPalette_SetEntries(ICOM_INTERFACE(This->palette, IDirectDrawPalette),
635 0, 0, 256, palent);
639 /* Copy one surface on the other */
640 dst_d = (DDSURFACEDESC *)&(This->surface_desc);
641 src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc);
643 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
644 /* Should also check for same pixel format, u1.lPitch, ... */
645 ERR("Error in surface sizes\n");
646 return D3DERR_TEXTURE_LOAD_FAILED;
647 } else {
648 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
649 /* I should put a macro for the calculus of bpp */
651 /* Copy also the ColorKeying stuff */
652 if (src_d->dwFlags & DDSD_CKSRCBLT) {
653 dst_d->dwFlags |= DDSD_CKSRCBLT;
654 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
655 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
658 /* Copy the main memory texture into the surface that corresponds to the OpenGL
659 texture object. */
660 memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
662 if (glThis != NULL) {
663 /* If the GetHandle was not done, it is an error... */
664 if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
666 /* Set this texture as dirty */
667 glThis->dirty_flag = TRUE;
671 return ret_value;
674 HRESULT WINAPI
675 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
676 REFIID riid,
677 LPVOID* obp)
679 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
680 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
681 riid,
682 obp);
685 ULONG WINAPI
686 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
688 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
689 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
692 ULONG WINAPI
693 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
695 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
696 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
699 HRESULT WINAPI
700 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
701 REFIID riid,
702 LPVOID* obp)
704 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
705 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
706 riid,
707 obp);
710 ULONG WINAPI
711 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
713 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
714 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
717 ULONG WINAPI
718 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
720 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
721 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
724 HRESULT WINAPI
725 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
726 DWORD dwStart,
727 DWORD dwCount)
729 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
730 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
731 dwStart,
732 dwCount);
735 HRESULT WINAPI
736 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
737 LPDIRECT3DDEVICE lpDirect3DDevice,
738 LPD3DTEXTUREHANDLE lpHandle)
740 TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
741 return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
742 COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
743 lpHandle);
746 HRESULT WINAPI
747 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
748 LPDIRECT3DTEXTURE lpD3DTexture)
750 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
751 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
752 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
755 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
756 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture2.fun))
757 #else
758 # define XCAST(fun) (void*)
759 #endif
761 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
763 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
764 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
765 XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
766 XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
767 XCAST(GetHandle) Main_IDirect3DTextureImpl_2_1T_GetHandle,
768 XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
769 XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
772 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
773 #undef XCAST
774 #endif
777 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
778 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture.fun))
779 #else
780 # define XCAST(fun) (void*)
781 #endif
783 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
785 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
786 XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
787 XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
788 XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
789 XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
790 XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
791 XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
792 XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
793 XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
796 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
797 #undef XCAST
798 #endif
800 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation,
801 IDirectDrawSurfaceImpl *main)
803 /* First, initialize the texture vtables... */
804 ICOM_INIT_INTERFACE(surf, IDirect3DTexture, VTABLE_IDirect3DTexture);
805 ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
807 /* Only create all the private stuff if we actually have an OpenGL context.. */
808 if (d3d->current_device != NULL) {
809 IDirect3DTextureGLImpl *private;
811 private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
812 if (private == NULL) return DDERR_OUTOFMEMORY;
814 private->final_release = surf->final_release;
815 private->lock_update = surf->lock_update;
816 private->unlock_update = surf->unlock_update;
817 private->set_palette = surf->set_palette;
819 /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
820 Otherwise, it will be uploaded here (and may be invalid). */
821 surf->final_release = gltex_final_release;
822 surf->lock_update = gltex_lock_update;
823 surf->unlock_update = gltex_unlock_update;
824 surf->tex_private = private;
825 surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
826 surf->set_palette = gltex_set_palette;
828 ENTER_GL();
829 if (surf->mipmap_level == 0) {
830 glGenTextures(1, &(private->tex_name));
831 if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
832 TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
833 } else {
834 private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
835 TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
836 surf, private, private->tex_name, main, main->tex_private);
838 LEAVE_GL();
840 /* And set the dirty flag accordingly */
841 private->dirty_flag = (at_creation == FALSE);
842 private->initial_upload_done = FALSE;
845 return D3D_OK;