Fixed some issues found by winapi_check.
[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 WINAPI 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                                 glThis->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 void
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
150     DDSURFACEDESC *src_d = (DDSURFACEDESC *)&(This->surface_desc);
151
152     TRACE(" uploading texture to GL id %d (initial = %d).\n", glThis->tex_name, init_upload);
153
154     glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
155     glBindTexture(GL_TEXTURE_2D, glThis->tex_name);
156
157     /* Texture snooping for the curious :-) */
158     snoop_texture(This);
159     
160     if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
161           /* ****************
162              Paletted Texture
163              **************** */
164         IDirectDrawPaletteImpl* pal = This->palette;
165         BYTE table[256][4];
166         int i;
167
168 #if 0
169         if (color_table_queried == FALSE) {
170             ptr_ColorTableEXT =
171                 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
172         }
173 #endif
174         
175         if (pal == NULL) {
176             ERR("Palettized texture Loading with a NULL palette !\n");
177             LEAVE_GL();
178             return;
179         }
180         /* Get the surface's palette */
181         for (i = 0; i < 256; i++) {
182             table[i][0] = pal->palents[i].peRed;
183             table[i][1] = pal->palents[i].peGreen;
184             table[i][2] = pal->palents[i].peBlue;
185             if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
186                 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
187                 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
188                 table[i][3] = 0x00;
189             else
190                 table[i][3] = 0xFF;
191         }
192
193         if (ptr_ColorTableEXT != NULL) {
194             /* use Paletted Texture Extension */
195             ptr_ColorTableEXT(GL_TEXTURE_2D,    /* target */
196                               GL_RGBA,          /* internal format */
197                               256,              /* table size */
198                               GL_RGBA,          /* table format */
199                               GL_UNSIGNED_BYTE, /* table type */
200                               table);           /* the color table */
201             
202             glTexImage2D(GL_TEXTURE_2D,       /* target */
203                          glThis->mipmap_level,                   /* level */
204                          GL_COLOR_INDEX8_EXT, /* internal format */
205                          src_d->dwWidth, src_d->dwHeight, /* width, height */
206                          0,                   /* border */
207                          GL_COLOR_INDEX,      /* texture format */
208                          GL_UNSIGNED_BYTE,    /* texture type */
209                          src_d->lpSurface); /* the texture */
210         } else {
211             DWORD *surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
212             DWORD i;
213             BYTE *src = (BYTE *) src_d->lpSurface, *dst = (BYTE *) surface;
214             
215             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
216                 BYTE color = *src++;
217                 *dst++ = table[color][0];
218                 *dst++ = table[color][1];
219                 *dst++ = table[color][2];
220                 *dst++ = table[color][3];
221             }
222             
223             if (init_upload)
224                 glTexImage2D(GL_TEXTURE_2D,
225                              glThis->mipmap_level,
226                              GL_RGBA,
227                              src_d->dwWidth, src_d->dwHeight,
228                              0,
229                              GL_RGBA,
230                              GL_UNSIGNED_BYTE,
231                              surface);
232             else
233                 glTexSubImage2D(GL_TEXTURE_2D,
234                                 glThis->mipmap_level,
235                                 0, 0,
236                                 src_d->dwWidth, src_d->dwHeight,
237                                 GL_RGBA,
238                                 GL_UNSIGNED_BYTE,
239                                 surface);
240             
241             HeapFree(GetProcessHeap(), 0, surface);
242         }
243     } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
244             /* ************
245                RGB Textures
246                ************ */
247         if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
248                 /* **********************
249                    GL_UNSIGNED_BYTE_3_3_2
250                    ********************** */
251             if (init_upload)
252                 glTexImage2D(GL_TEXTURE_2D,
253                              glThis->mipmap_level,
254                              GL_RGB,
255                              src_d->dwWidth, src_d->dwHeight,
256                              0,
257                              GL_RGB,
258                              GL_UNSIGNED_BYTE_3_3_2,
259                              src_d->lpSurface);
260             else
261                 glTexSubImage2D(GL_TEXTURE_2D,
262                                 glThis->mipmap_level,
263                                 0, 0,
264                                 src_d->dwWidth, src_d->dwHeight,
265                                 GL_RGB,
266                                 GL_UNSIGNED_BYTE_3_3_2,
267                                 src_d->lpSurface);
268         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
269             if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
270                 if (init_upload)
271                     glTexImage2D(GL_TEXTURE_2D,
272                                  glThis->mipmap_level,
273                                  GL_RGB,
274                                  src_d->dwWidth, src_d->dwHeight,
275                                  0,
276                                  GL_RGB,
277                                  GL_UNSIGNED_SHORT_5_6_5,
278                                  src_d->lpSurface);
279                 else
280                     glTexSubImage2D(GL_TEXTURE_2D,
281                                     glThis->mipmap_level,
282                                     0, 0,
283                                     src_d->dwWidth, src_d->dwHeight,
284                                     GL_RGB,
285                                     GL_UNSIGNED_SHORT_5_6_5,
286                                     src_d->lpSurface);
287
288             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
289                 if (init_upload)
290                     glTexImage2D(GL_TEXTURE_2D,
291                                  glThis->mipmap_level,
292                                  GL_RGBA,
293                                  src_d->dwWidth, src_d->dwHeight,
294                                  0,
295                                  GL_RGBA,
296                                  GL_UNSIGNED_SHORT_5_5_5_1,
297                                  src_d->lpSurface);
298                 else
299                     glTexSubImage2D(GL_TEXTURE_2D,
300                                     glThis->mipmap_level,
301                                     0, 0,
302                                     src_d->dwWidth, src_d->dwHeight,
303                                     GL_RGBA,
304                                     GL_UNSIGNED_SHORT_5_5_5_1,
305                                     src_d->lpSurface);
306             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
307                 if (init_upload)
308                     glTexImage2D(GL_TEXTURE_2D,
309                                  glThis->mipmap_level,
310                                  GL_RGBA,
311                                  src_d->dwWidth, src_d->dwHeight,
312                                  0,
313                                  GL_RGBA,
314                                  GL_UNSIGNED_SHORT_4_4_4_4,
315                                  src_d->lpSurface);
316                 else
317                     glTexSubImage2D(GL_TEXTURE_2D,
318                                     glThis->mipmap_level,
319                                     0, 0,
320                                     src_d->dwWidth, src_d->dwHeight,
321                                     GL_RGBA,
322                                     GL_UNSIGNED_SHORT_4_4_4_4,
323                                     src_d->lpSurface);
324             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000F000) {
325                 /* Move the four Alpha bits... */
326                 WORD *surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
327                 DWORD i;
328                 WORD *src = (WORD *) src_d->lpSurface, *dst = surface;
329                 
330                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
331                     *dst++ = (((*src & 0xFFF0) >>  4) |
332                               ((*src & 0x000F) << 12));
333                     src++;
334                 }
335                 
336                 if (init_upload)
337                     glTexImage2D(GL_TEXTURE_2D,
338                                  glThis->mipmap_level,
339                                  GL_RGBA,
340                                  src_d->dwWidth, src_d->dwHeight,
341                                  0,
342                                  GL_RGBA,
343                                  GL_UNSIGNED_SHORT_4_4_4_4,
344                                  surface);
345                 else
346                     glTexSubImage2D(GL_TEXTURE_2D,
347                                     glThis->mipmap_level,
348                                     0, 0,
349                                     src_d->dwWidth, src_d->dwHeight,
350                                     GL_RGBA,
351                                     GL_UNSIGNED_SHORT_4_4_4_4,
352                                     surface);
353                 
354                 HeapFree(GetProcessHeap(), 0, surface);
355             } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00008000) {
356                 /* Converting the 1555 format in 5551 packed */
357                 WORD *surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
358                 DWORD i;
359                 WORD *src = (WORD *) src_d->lpSurface, *dst = surface;
360                 
361                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
362                     *dst++ = (((*src & 0x8000) >> 15) |
363                               ((*src & 0x7FFF) <<  1));
364                     src++;
365                 }
366                 
367                 if (init_upload)
368                     glTexImage2D(GL_TEXTURE_2D,
369                                  glThis->mipmap_level,
370                                  GL_RGBA,
371                                  src_d->dwWidth, src_d->dwHeight,
372                                  0,
373                                  GL_RGBA,
374                                  GL_UNSIGNED_SHORT_5_5_5_1,
375                                  surface);
376                 else
377                     glTexSubImage2D(GL_TEXTURE_2D,
378                                     glThis->mipmap_level,
379                                     0, 0,
380                                     src_d->dwWidth, src_d->dwHeight,
381                                     GL_RGBA,
382                                     GL_UNSIGNED_SHORT_5_5_5_1,
383                                     surface);
384
385                 HeapFree(GetProcessHeap(), 0, surface);
386             } else {
387                 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
388             }
389         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
390             if (init_upload)
391                 glTexImage2D(GL_TEXTURE_2D,
392                              glThis->mipmap_level,
393                              GL_RGB,
394                              src_d->dwWidth, src_d->dwHeight,
395                              0,
396                              GL_RGB,
397                              GL_UNSIGNED_BYTE,
398                              src_d->lpSurface);
399             else
400                 glTexSubImage2D(GL_TEXTURE_2D,
401                                 glThis->mipmap_level,
402                                 0, 0,
403                                 src_d->dwWidth, src_d->dwHeight,
404                                 GL_RGB,
405                                 GL_UNSIGNED_BYTE,
406                                 src_d->lpSurface);
407         } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
408             if (init_upload)
409                 glTexImage2D(GL_TEXTURE_2D,
410                              glThis->mipmap_level,
411                              GL_RGBA,
412                              src_d->dwWidth, src_d->dwHeight,
413                              0,
414                              GL_RGBA,
415                              GL_UNSIGNED_BYTE,
416                              src_d->lpSurface);
417             else
418                 glTexSubImage2D(GL_TEXTURE_2D,
419                                 glThis->mipmap_level,
420                                 0, 0,
421                                 src_d->dwWidth, src_d->dwHeight,
422                                 GL_RGBA,
423                                 GL_UNSIGNED_BYTE,
424                                 src_d->lpSurface);
425         } else {
426             ERR("Unhandled texture format (bad RGB count)\n");
427         }
428     } else {
429         ERR("Unhandled texture format (neither RGB nor INDEX)\n");
430     }    
431     glBindTexture(GL_TEXTURE_2D, current_texture);
432 }
433
434 HRESULT WINAPI
435 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface,
436                                        LPDIRECT3DDEVICE lpDirect3DDevice,
437                                        LPDIRECTDRAWSURFACE lpDDSurface)
438 {
439     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
440     FIXME("(%p/%p)->(%p,%p) no-op...\n", This, iface, lpDirect3DDevice, lpDDSurface);
441     return DD_OK;
442 }
443
444 HRESULT WINAPI
445 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
446                                               DWORD dwStart,
447                                               DWORD dwCount)
448 {
449     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
450     FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This, iface, dwStart, dwCount);
451     return DD_OK;
452 }
453
454 HRESULT WINAPI
455 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface)
456 {
457     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
458     FIXME("(%p/%p)->(): stub!\n", This, iface);
459     return DD_OK;
460 }
461
462 HRESULT WINAPI
463 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
464                                          LPDIRECT3DDEVICE2 lpDirect3DDevice2,
465                                          LPD3DTEXTUREHANDLE lpHandle)
466 {
467     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
468     FIXME("(%p/%p)->(%p,%p): stub!\n", This, iface, lpDirect3DDevice2, lpHandle);
469     return DD_OK;
470 }
471
472 HRESULT WINAPI
473 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
474                                     LPDIRECT3DTEXTURE2 lpD3DTexture2)
475 {
476     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
477     FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpD3DTexture2);
478     return DD_OK;
479 }
480
481 static void
482 gltex_final_release(IDirectDrawSurfaceImpl *This)
483 {
484     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
485     DWORD mem_used;
486
487     TRACE(" deleting texture with GL id %d.\n", glThis->tex_name);
488       
489     /* And delete texture handle */
490     ENTER_GL();
491     if (glThis->tex_name != 0)
492         glDeleteTextures(1, &(glThis->tex_name));
493     LEAVE_GL(); 
494
495     /* And if this texture was the current one, remove it at the device level */
496     if (This->d3ddevice != NULL)
497         if (This->d3ddevice->current_texture[0] == This)
498             This->d3ddevice->current_texture[0] = NULL;
499
500     /* All this should be part of main surface management not just a hack for texture.. */
501     if (glThis->loaded) {
502         mem_used = This->surface_desc.dwHeight *
503                    This->surface_desc.u1.lPitch;
504         This->ddraw_owner->free_memory(This->ddraw_owner, mem_used);
505     }
506
507     glThis->final_release(This);
508 }
509
510 static void
511 gltex_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
512 {
513     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
514     
515     glThis->lock_update(This, pRect, dwFlags);
516 }
517
518 static void
519 gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
520 {
521     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
522
523     ENTER_GL();
524     gltex_upload_texture(This, glThis->first_unlock);
525     LEAVE_GL();
526     glThis->first_unlock = FALSE;
527
528     glThis->unlock_update(This, pRect);
529 }
530
531 HRESULT WINAPI
532 GL_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface,
533                                        LPDIRECT3DDEVICE2 lpDirect3DDevice2,
534                                        LPD3DTEXTUREHANDLE lpHandle)
535 {
536     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
537     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
538     IDirect3DDeviceImpl *lpDeviceImpl = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, lpDirect3DDevice2);
539     
540     TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpDirect3DDevice2, lpHandle);
541
542     /* The handle is simply the pointer to the implementation structure */
543     *lpHandle = (D3DTEXTUREHANDLE) This;
544
545     TRACE(" returning handle %08lx.\n", *lpHandle);
546     
547     /* Now, bind a new texture */
548     This->d3ddevice = lpDeviceImpl;
549
550     /* Associate the texture with the device and perform the appropriate AddRef/Release */
551     /* FIXME: Is there only one or several textures associated with the device ? */
552     if (lpDeviceImpl->current_texture[0] != NULL)
553         IDirectDrawSurface7_Release(ICOM_INTERFACE(lpDeviceImpl->current_texture[0], IDirectDrawSurface7));
554     IDirectDrawSurface7_AddRef(ICOM_INTERFACE(This, IDirectDrawSurface7));
555     lpDeviceImpl->current_texture[0] = This;
556
557     TRACE("OpenGL texture handle is : %d\n", glThis->tex_name);
558
559     return D3D_OK;
560 }
561
562 HRESULT WINAPI
563 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
564                                   LPDIRECT3DTEXTURE2 lpD3DTexture2)
565 {
566     ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
567     IDirect3DTextureGLImpl *glThis = (IDirect3DTextureGLImpl *) This->tex_private;
568     IDirectDrawSurfaceImpl *lpD3DTextureImpl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpD3DTexture2);
569     DWORD mem_used;
570     DDSURFACEDESC *src_d, *dst_d;
571     
572     TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DTexture2);
573
574     if (glThis->loaded == FALSE) {
575         /* Only check memory for not already loaded texture... */
576         mem_used = This->surface_desc.dwHeight *
577                    This->surface_desc.u1.lPitch;
578         if (This->ddraw_owner->allocate_memory(This->ddraw_owner, mem_used) < 0) {
579             TRACE(" out of virtual memory... Warning application.\n");
580             return D3DERR_TEXTURE_LOAD_FAILED;
581         }
582     }
583     glThis->loaded = TRUE;
584     
585     TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl, This);
586
587     if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
588         /* If the surface is not allocated and its location is not yet specified,
589            force it to video memory */ 
590         if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
591             This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
592
593     /* Suppress the ALLOCONLOAD flag */
594     This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
595     This->palette = lpD3DTextureImpl->palette;
596     
597     /* Copy one surface on the other */
598     dst_d = (DDSURFACEDESC *)&(This->surface_desc);
599     src_d = (DDSURFACEDESC *)&(lpD3DTextureImpl->surface_desc);
600
601     if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
602         /* Should also check for same pixel format, u1.lPitch, ... */
603         ERR("Error in surface sizes\n");
604         return D3DERR_TEXTURE_LOAD_FAILED;
605     } else {
606         /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
607         /* I should put a macro for the calculus of bpp */
608
609         /* Copy also the ColorKeying stuff */
610         if (src_d->dwFlags & DDSD_CKSRCBLT) {
611             dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
612             dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
613         }
614
615         /* Copy the main memry texture into the surface that corresponds to the OpenGL
616            texture object. */
617         memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->u1.lPitch * src_d->dwHeight);
618
619         /* If the GetHandle was not done, it is an error... */
620         if (glThis->tex_name == 0) ERR("Unbound GL texture !!!\n");
621
622         ENTER_GL();
623
624         /* Now, load the texture */
625         /* d3dd->set_context(d3dd); We need to set the context somehow.... */
626
627         gltex_upload_texture(This, glThis->first_unlock);
628         glThis->first_unlock = FALSE;
629         
630         LEAVE_GL();
631     }
632
633     return D3D_OK;
634 }
635
636 HRESULT WINAPI
637 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface,
638                                             REFIID riid,
639                                             LPVOID* obp)
640 {
641     TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
642     return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface),
643                                               riid,
644                                               obp);
645 }
646
647 ULONG WINAPI
648 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface)
649 {
650     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
651     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
652 }
653
654 ULONG WINAPI
655 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface)
656 {
657     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
658     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture2, IDirectDrawSurface7, iface));
659 }
660
661 HRESULT WINAPI
662 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface,
663                                             REFIID riid,
664                                             LPVOID* obp)
665 {
666     TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface, debugstr_guid(riid), obp);
667     return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface),
668                                               riid,
669                                               obp);
670 }
671
672 ULONG WINAPI
673 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface)
674 {
675     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
676     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
677 }
678
679 ULONG WINAPI
680 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface)
681 {
682     TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface);
683     return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
684 }
685
686 HRESULT WINAPI
687 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface,
688                                             DWORD dwStart,
689                                             DWORD dwCount)
690 {
691     TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface, dwStart, dwCount);
692     return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
693                                             dwStart,
694                                             dwCount);
695 }
696
697 HRESULT WINAPI
698 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface,
699                                        LPDIRECT3DDEVICE lpDirect3DDevice,
700                                        LPD3DTEXTUREHANDLE lpHandle)
701 {
702     TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface, lpDirect3DDevice, lpHandle);
703     return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
704                                        COM_INTERFACE_CAST(IDirect3DDeviceImpl, IDirect3DDevice, IDirect3DDevice2, lpDirect3DDevice),
705                                        lpHandle);
706 }
707
708 HRESULT WINAPI
709 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface,
710                                   LPDIRECT3DTEXTURE lpD3DTexture)
711 {
712     TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface, lpD3DTexture);
713     return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
714                                   COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, lpD3DTexture));
715 }
716
717 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
718 # define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture2.fun))
719 #else
720 # define XCAST(fun)     (void*)
721 #endif
722
723 ICOM_VTABLE(IDirect3DTexture2) VTABLE_IDirect3DTexture2 =
724 {
725     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
726     XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_2_QueryInterface,
727     XCAST(AddRef) Thunk_IDirect3DTextureImpl_2_AddRef,
728     XCAST(Release) Thunk_IDirect3DTextureImpl_2_Release,
729     XCAST(GetHandle) GL_IDirect3DTextureImpl_2_1T_GetHandle,
730     XCAST(PaletteChanged) Main_IDirect3DTextureImpl_2_1T_PaletteChanged,
731     XCAST(Load) GL_IDirect3DTextureImpl_2_1T_Load,
732 };
733
734 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
735 #undef XCAST
736 #endif
737
738
739 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
740 # define XCAST(fun)     (typeof(VTABLE_IDirect3DTexture.fun))
741 #else
742 # define XCAST(fun)     (void*)
743 #endif
744
745 ICOM_VTABLE(IDirect3DTexture) VTABLE_IDirect3DTexture =
746 {
747     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
748     XCAST(QueryInterface) Thunk_IDirect3DTextureImpl_1_QueryInterface,
749     XCAST(AddRef) Thunk_IDirect3DTextureImpl_1_AddRef,
750     XCAST(Release) Thunk_IDirect3DTextureImpl_1_Release,
751     XCAST(Initialize) Main_IDirect3DTextureImpl_1_Initialize,
752     XCAST(GetHandle) Thunk_IDirect3DTextureImpl_1_GetHandle,
753     XCAST(PaletteChanged) Thunk_IDirect3DTextureImpl_1_PaletteChanged,
754     XCAST(Load) Thunk_IDirect3DTextureImpl_1_Load,
755     XCAST(Unload) Main_IDirect3DTextureImpl_1_Unload,
756 };
757
758 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
759 #undef XCAST
760 #endif
761
762 HRESULT d3dtexture_create(IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation, 
763                           IDirectDrawSurfaceImpl *main, DWORD mipmap_level)
764 {
765     IDirect3DTextureGLImpl *private;
766
767     private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTextureGLImpl));
768     if (private == NULL) return DDERR_OUTOFMEMORY;
769
770     private->final_release = surf->final_release;
771     private->lock_update = surf->lock_update;
772     private->unlock_update = surf->unlock_update;
773     private->mipmap_level = mipmap_level;
774     
775     /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
776        Otherwise, it will be uploaded here (and may be invalid). */
777     if (at_creation == TRUE)
778         private->first_unlock = TRUE;
779     else
780         private->first_unlock = FALSE;
781     surf->final_release = gltex_final_release;
782     surf->lock_update = gltex_lock_update;
783     surf->unlock_update = gltex_unlock_update;
784     surf->tex_private = private;
785     surf->SetColorKey_cb = gltex_setcolorkey_cb;
786     
787     ICOM_INIT_INTERFACE(surf, IDirect3DTexture,  VTABLE_IDirect3DTexture);
788     ICOM_INIT_INTERFACE(surf, IDirect3DTexture2, VTABLE_IDirect3DTexture2);
789
790     ENTER_GL();
791     if (mipmap_level == 0) {
792         glGenTextures(1, &(private->tex_name));
793         if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
794         TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
795     } else {
796         private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
797         TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
798               surf, private, private->tex_name, main, main->tex_private);
799     }
800
801     if ((at_creation == FALSE) &&
802         ((surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) == 0))
803     {
804         gltex_upload_texture(surf, TRUE);
805     }
806     LEAVE_GL();
807
808     return D3D_OK;
809 }