Fixed texturing.
[wine] / dlls / ddraw / d3dtexture.c
1 /* Direct3D Texture
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains the implementation of interface Direct3DTexture2.
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
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"
31
32 #include "mesa_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
35
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
40
41 #ifdef TEXTURE_SNOOP
42 #include <stdio.h>
43
44 static void snoop_texture(IDirectDrawSurfaceImpl *This) {
45     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
46     char buf[128];
47     FILE *f;
48     
49     sprintf(buf, "tex_%05d.pnm", glThis->tex_name);
50     f = fopen(buf, "wb");
51     DDRAW_dump_surface_to_disk(This, f);
52 }
53
54 #else
55
56 #define snoop_texture(a)
57
58 #endif
59
60 /*******************************************************************************
61  *                         IDirectSurface callback methods
62  */
63 HRESULT gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
64 {
65     DDSURFACEDESC *tex_d;
66     GLuint current_texture;
67     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) texture->tex_private;
68     
69     TRACE("(%p) : colorkey callback\n", texture);
70
71     /* Get the texture description */
72     tex_d = (DDSURFACEDESC *)&(texture->surface_desc);
73
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);
79
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;
93                 
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];
97                         
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;
104                     }
105                 }
106
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);
114                 
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");
123             }
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");
130         }
131     } else {
132         ERR("Unhandled texture format (neither RGB nor INDEX)\n");
133     }
134     glBindTexture(GL_TEXTURE_2D, current_texture);
135     LEAVE_GL();
136
137     return DD_OK;
138 }
139
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;
153
154     DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc);
155
156     TRACE(" uploading texture to GL id %d (initial = %d).\n", glThis->tex_name, init_upload);
157
158     glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
159     glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
160
161     /* Texture snooping for the curious :-) */
162     snoop_texture(This);
163     
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;
171
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;
176         }
177 #endif
178         
179         if (pal == NULL) {
180             /* Upload a black texture. The real one will be uploaded on palette change */
181             WARN("Palettized texture Loading with a NULL palette !\n");
182             memset(table, 0, 256 * 4);
183         } else {
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;
195             }
196         }
197
198         if (ptr_ColorTableEXT != NULL) {
199             /* use Paletted Texture Extension */
200             ptr_ColorTableEXT(GL_TEXTURE_2D,    /* target */
201                               GL_RGBA,          /* internal format */
202                               256,              /* table size */
203                               GL_RGBA,          /* table format */
204                               GL_UNSIGNED_BYTE, /* table type */
205                               table);           /* the color table */
206             
207             glTexImage2D(GL_TEXTURE_2D,       /* target */
208                          This->mipmap_level,                   /* level */
209                          GL_COLOR_INDEX8_EXT, /* internal format */
210                          src_d->dwWidth, src_d->dwHeight, /* width, height */
211                          0,                   /* border */
212                          GL_COLOR_INDEX,      /* texture format */
213                          GL_UNSIGNED_BYTE,    /* texture type */
214                          src_d->lpSurface); /* the texture */
215
216             upload_done = TRUE;
217         } else {
218             DWORD i;
219             BYTE *src = (BYTE *) src_d->lpSurface, *dst;
220             
221             surface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
222             dst = (BYTE *) surface;
223             
224             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
225                 BYTE color = *src++;
226                 *dst++ = table[color][0];
227                 *dst++ = table[color][1];
228                 *dst++ = table[color][2];
229                 *dst++ = table[color][3];
230             }
231             
232             format = GL_RGBA;
233             pixel_format = GL_UNSIGNED_BYTE;
234         }
235     } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
236             /* ************
237                RGB Textures
238                ************ */
239         if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
240                 /* **********************
241                    GL_UNSIGNED_BYTE_3_3_2
242                    ********************** */
243             format = GL_RGB;
244             pixel_format = GL_UNSIGNED_BYTE_3_3_2;
245         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
246             if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
247                 format = GL_RGB;
248                 pixel_format = GL_UNSIGNED_SHORT_5_6_5;
249             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
250                 format = GL_RGBA;
251                 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
252             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
253                 format = GL_RGBA;
254                 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;             
255             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000F000) {
256                 /* Move the four Alpha bits... */
257                 DWORD i;
258                 WORD *src = (WORD *) src_d->lpSurface, *dst;
259                 
260                 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
261                 dst = surface;
262                 
263                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
264                     *dst++ = (((*src & 0xFFF0) >>  4) |
265                               ((*src & 0x000F) << 12));
266                     src++;
267                 }
268
269                 format = GL_RGBA;
270                 pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;               
271             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00008000) {
272                 /* Converting the 1555 format in 5551 packed */
273                 DWORD i;
274                 WORD *src = (WORD *) src_d->lpSurface, *dst;
275                 
276                 surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
277                 dst = (WORD *) surface;
278                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
279                     *dst++ = (((*src & 0x8000) >> 15) |
280                               ((*src & 0x7FFF) <<  1));
281                     src++;
282                 }
283                 
284                 format = GL_RGBA;
285                 pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
286             } else {
287                 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
288                 error = TRUE;
289             }
290         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
291             format = GL_RGB;
292             pixel_format = GL_UNSIGNED_BYTE;
293         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
294             format = GL_RGBA;
295             pixel_format = GL_UNSIGNED_BYTE;
296         } else {
297             ERR("Unhandled texture format (bad RGB count)\n");
298             error = TRUE;
299         }
300     } else {
301         ERR("Unhandled texture format (neither RGB nor INDEX)\n");
302         error = TRUE;
303     } 
304
305     if ((upload_done == FALSE) && (error == FALSE)) {
306         if (init_upload)
307             glTexImage2D(GL_TEXTURE_2D,
308                          This->mipmap_level,
309                          format,
310                          src_d->dwWidth, src_d->dwHeight,
311                          0,
312                          format,
313                          pixel_format,
314                          surface == NULL ? src_d->lpSurface : surface);
315         else
316             glTexSubImage2D(GL_TEXTURE_2D,
317                             This->mipmap_level,
318                             0, 0,
319                             src_d->dwWidth, src_d->dwHeight,
320                             format,
321                             pixel_format,
322                             surface == NULL ? src_d->lpSurface : surface);
323         if (surface) HeapFree(GetProcessHeap(), 0, surface);
324     }
325
326     glBindTexture(GL_TEXTURE_2D, current_texture);
327     return DD_OK;
328 }
329
330 HRESULT WINAPI
331 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
332                                        LPDIRECT3DDEVICE lpDirect3DDevice,
333                                        LPDIRECTDRAWSURFACE lpDDSurface)
334 {
335     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
336     FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
337     return DD_OK;
338 }
339
340 HRESULT WINAPI
341 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
342                                               DWORD dwStart,
343                                               DWORD dwCount)
344 {
345     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
346     FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
347     return DD_OK;
348 }
349
350 HRESULT WINAPI
351 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
352 {
353     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
354     FIXME("(%p/%p)->(): stub!\n", This, iface);
355     return DD_OK;
356 }
357
358 HRESULT WINAPI
359 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
360                                          LPDIRECT3DDEVICE2 lpDirect3DDevice2,
361                                          LPD3DTEXTUREHANDLE lpHandle)
362 {
363     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
364     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpDirect3DDevice2, lpHandle);
365     return DD_OK;
366 }
367
368 HRESULT WINAPI
369 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
370                                     LPDIRECT3DTEXTURE2 lpD3DTexture2)
371 {
372     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
373     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
374     return DD_OK;
375 }
376
377 static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteImpl* pal)
378 {
379     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
380     
381     /* First call the previous set_palette function */
382     glThis->set_palette(This, pal);
383
384     /* Then re-upload the texture to OpenGL */
385     ENTER_GL();
386     gltex_upload_texture(This, glThis->first_unlock);
387     LEAVE_GL();
388 }
389
390 static void
391 gltex_final_release(IDirectDrawSurfaceImpl *This)
392 {
393     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
394     DWORD mem_used;
395
396     TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
397       
398     /* And delete texture handle */
399     ENTER_GL();
400     if (glThis->tex_name != 0)
401         glDeleteTextures(1, &(glThis->tex_name));
402     LEAVE_GL(); 
403
404     /* And if this texture was the current one, remove it at the device level */
405     if (This->d3ddevice != NULL)
406         if (This->d3ddevice->current_texture[0] == This)
407             This->d3ddevice->current_texture[0] = NULL;
408
409     /* All this should be part of main surface management not just a hack for texture.. */
410     if (glThis->loaded) {
411         mem_used = This->surface_desc.dwHeight *
412                    This->surface_desc.u1.lPitch;
413         This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
414     }
415
416     glThis->final_release(This);
417 }
418
419 static void
420 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
421 {
422     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
423     
424     glThis->lock_update(This, pRect, dwFlags);
425 }
426
427 static void
428 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
429 {
430     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
431
432     glThis->unlock_update(This, pRect);
433     
434     ENTER_GL();
435     gltex_upload_texture(This, glThis->first_unlock);
436     LEAVE_GL();
437     glThis->first_unlock = FALSE;
438 }
439
440 HRESULT WINAPI
441 GL_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
442                                        LPDIRECT3DDEVICE2 lpDirect3DDevice2,
443                                        LPD3DTEXTUREHANDLE lpHandle)
444 {
445     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
446     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
447     IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
448     
449     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
450
451     /* The handle is simply the pointer to the implementation structure */
452     *lpHandle = (D3DTEXTUREHANDLE) This;
453
454     TRACE(" returning handle %08lx.\n", *lpHandle);
455     
456     /* Now, bind a new texture */
457     This->d3ddevice = lpDeviceImpl;
458
459     /* Associate the texture with the device and perform the appropriate AddRef/Release */
460     /* FIXME: Is there only one or several textures associated with the device ? */
461     if (lpDeviceImpl->current_texture[0] != NULL)
462         IDirectDrawSurface7_Release(ICOM_INTERFACE(lpDeviceImpl->current_texture[0], IDirectDrawSurface7));
463     IDirectDrawSurface7_AddRef(ICOM_INTERFACE(This, IDirectDrawSurface7));
464     lpDeviceImpl->current_texture[0] = This;
465
466     TRACE("OpenGL texture handle is : %d\n", glThis->tex_name);
467
468     return D3D_OK;
469 }
470
471 HRESULT WINAPI
472 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
473                                   LPDIRECT3DTEXTURE2 lpD3DTexture2)
474 {
475     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
476     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
477     IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
478     DWORD mem_used;
479     DDSURFACEDESC *src_d, *dst_d;
480     HRESULT ret_value = D3D_OK;
481     
482     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
483
484     if (glThis != NULL) {
485         if (glThis->loaded == FALSE) {
486             /* Only check memory for not already loaded texture... */
487             mem_used = This->surface_desc.dwHeight *
488                        This->surface_desc.u1.lPitch;
489             if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
490                 TRACE(" out of virtual memory... Warning application.\n");
491                 return D3DERR_TEXTURE_LOAD_FAILED;
492             }
493         }
494         glThis->loaded = TRUE;
495     }
496     
497     TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This);
498
499     if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
500         /* If the surface is not allocated and its location is not yet specified,
501            force it to video memory */ 
502         if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
503             This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
504
505     /* Suppress the ALLOCONLOAD flag */
506     This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
507     
508     /* After seeing some logs, not sure at all about this... */
509     if (This->palette == NULL) {
510         This->palette = lpD3DTextureImpl->palette;
511         if (lpD3DTextureImpl->palette != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(lpD3DTextureImpl->palette,
512                                                                                 IDirectDrawPalette));
513     } else {
514         if (lpD3DTextureImpl->palette != NULL) {
515             PALETTEENTRY palent[256];
516             IDirectDrawPalette *pal_int = ICOM_INTERFACE(lpD3DTextureImpl->palette, IDirectDrawPalette);
517             IDirectDrawPalette_AddRef(pal_int);
518             IDirectDrawPalette_GetEntries(pal_int, 0, 0, 256, palent);
519             IDirectDrawPalette_SetEntries(ICOM_INTERFACE(This->palette, IDirectDrawPalette),
520                                           0, 0, 256, palent);
521         }
522     }
523     
524     /* Copy one surface on the other */
525     dst_d = (DDSURFACEDESC *)&(This->surface_desc);
526     src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc);
527
528     if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
529         /* Should also check for same pixel format, u1.lPitch, ... */
530         ERR("Error in surface sizes\n");
531         return D3DERR_TEXTURE_LOAD_FAILED;
532     } else {
533         /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
534         /* I should put a macro for the calculus of bpp */
535
536         /* Copy also the ColorKeying stuff */
537         if (src_d->dwFlags & DDSD_CKSRCBLT) {
538             dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
539             dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
540         }
541
542         /* Copy the main memry texture into the surface that corresponds to the OpenGL
543            texture object. */
544         memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
545
546         if (glThis != NULL) {
547             /* If the GetHandle was not done, it is an error... */
548             if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
549
550             ENTER_GL();
551             
552             /* Now, load the texture */
553             /* d3dd->set_context(d3dd); We need to set the context somehow.... */
554             
555             ret_value = gltex_upload_texture(This, glThis->first_unlock);
556             glThis->first_unlock = FALSE;
557             
558             LEAVE_GL();
559         }
560     }
561
562     return ret_value;
563 }
564
565 HRESULT WINAPI
566 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
567                                             REFIID riid,
568                                             LPVOID* obp)
569 {
570     TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
571     return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
572                                               riid,
573                                               obp);
574 }
575
576 ULONG WINAPI
577 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
578 {
579     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
580     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
581 }
582
583 ULONG WINAPI
584 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
585 {
586     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
587     return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
588 }
589
590 HRESULT WINAPI
591 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
592                                             REFIID riid,
593                                             LPVOID* obp)
594 {
595     TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
596     return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
597                                               riid,
598                                               obp);
599 }
600
601 ULONG WINAPI
602 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
603 {
604     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
605     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
606 }
607
608 ULONG WINAPI
609 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
610 {
611     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
612     return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
613 }
614
615 HRESULT WINAPI
616 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
617                                             DWORD dwStart,
618                                             DWORD dwCount)
619 {
620     TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
621     return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
622                                             dwStart,
623                                             dwCount);
624 }
625
626 HRESULT WINAPI
627 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
628                                        LPDIRECT3DDEVICE lpDirect3DDevice,
629                                        LPD3DTEXTUREHANDLE lpHandle)
630 {
631     TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
632     return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
633                                        COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
634                                        lpHandle);
635 }
636
637 HRESULT WINAPI
638 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
639                                   LPDIRECT3DTEXTURE lpD3DTexture)
640 {
641     TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
642     return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
643                                   COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
644 }
645
646 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
647 # define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture2.fun))
648 #else
649 # define XCAST(fun)     (void*)
650 #endif
651
652 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
653 {
654     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
655     XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
656     XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
657     XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
658     XCAST(GetHandle) GL_IDirect3DTextureImpl_2_1T_GetHandle,
659     XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
660     XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
661 };
662
663 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
664 #undef XCAST
665 #endif
666
667
668 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
669 # define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture.fun))
670 #else
671 # define XCAST(fun)     (void*)
672 #endif
673
674 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
675 {
676     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
677     XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
678     XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
679     XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
680     XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
681     XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
682     XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
683     XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
684     XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
685 };
686
687 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
688 #undef XCAST
689 #endif
690
691 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation, 
692                           IDirectDrawSurfaceImpl *main)
693 {
694     /* First, initialize the texture vtables... */
695     ICOM_INIT_INTERFACE(surf, IDirect3DTexture,  VTABLE_IDirect3DTexture);
696     ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
697         
698     /* Only create all the private stuff if we actually have an OpenGL context.. */
699     if (d3d->current_device != NULL) {
700         IDirect3DTextureGLImpl *private;
701
702         private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
703         if (private == NULL) return DDERR_OUTOFMEMORY;
704
705         private->final_release = surf->final_release;
706         private->lock_update = surf->lock_update;
707         private->unlock_update = surf->unlock_update;
708         private->set_palette = surf->set_palette;
709         
710         /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
711            Otherwise, it will be uploaded here (and may be invalid). */
712         if (at_creation == TRUE)
713             private->first_unlock = TRUE;
714         else
715             private->first_unlock = FALSE;
716         surf->final_release = gltex_final_release;
717         surf->lock_update = gltex_lock_update;
718         surf->unlock_update = gltex_unlock_update;
719         surf->tex_private = private;
720         surf->aux_setcolorkey_cb = gltex_setcolorkey_cb;
721         surf->set_palette = gltex_set_palette;
722
723         ENTER_GL();
724         if (surf->mipmap_level == 0) {
725             glGenTextures(1, &(private->tex_name));
726             if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
727             TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
728         } else {
729             private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
730             TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
731                   surf, private, private->tex_name, main, main->tex_private);
732         }
733
734         if ((at_creation == FALSE) &&
735             ((surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) == 0))
736         {
737             gltex_upload_texture(surf, TRUE);
738         }
739         LEAVE_GL();
740     }
741
742     return D3D_OK;
743 }