Added better support for Unicode:
[wine] / dlls / ddraw / d3dtexture.c
1 /* Direct3D Texture
2    (c) 1998 Lionel ULMER
3    
4    This files contains the implementation of interface Direct3DTexture2. */
5
6
7 #include <string.h>
8 #include "config.h"
9 #include "windef.h"
10 #include "winerror.h"
11 #include "wine/obj_base.h"
12 #include "heap.h"
13 #include "ddraw.h"
14 #include "d3d.h"
15 #include "debugtools.h"
16
17 #include "mesa_private.h"
18
19 #define D3DDPRIVATE(x) mesa_d3dd_private*odev=(mesa_d3dd_private*)(x)->private
20 #define D3DTPRIVATE(x) mesa_d3dt_private*dtpriv=(mesa_d3dt_private*)(x)->private
21
22 DEFAULT_DEBUG_CHANNEL(ddraw);
23
24 /* Define this if you want to save to a file all the textures used by a game
25    (can be funny to see how they managed to cram all the pictures in
26    texture memory) */
27 #undef TEXTURE_SNOOP
28
29 #ifdef TEXTURE_SNOOP
30 #include <stdio.h>
31      
32 #define SNOOP_PALETTED()                                                                        \
33       {                                                                                         \
34         FILE *f;                                                                                \
35         char buf[32];                                                                           \
36         int x, y;                                                                               \
37                                                                                                 \
38         sprintf(buf, "%ld.pnm", dtpriv->tex_name);                                                      \
39         f = fopen(buf, "wb");                                                                   \
40         fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);                      \
41         for (y = 0; y < src_d->dwHeight; y++) {                                                 \
42           for (x = 0; x < src_d->dwWidth; x++) {                                                \
43             unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x];   \
44             fputc(table[c][0], f);                                                              \
45             fputc(table[c][1], f);                                                              \
46             fputc(table[c][2], f);                                                              \
47           }                                                                                     \
48         }                                                                                       \
49         fclose(f);                                                                              \
50       }
51
52 #define SNOOP_5650()                                                                                    \
53           {                                                                                             \
54             FILE *f;                                                                                    \
55             char buf[32];                                                                               \
56             int x, y;                                                                                   \
57                                                                                                         \
58             sprintf(buf, "%ld.pnm", dtpriv->tex_name);                                                  \
59             f = fopen(buf, "wb");                                                                       \
60             fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);                          \
61             for (y = 0; y < src_d->dwHeight; y++) {                                                     \
62               for (x = 0; x < src_d->dwWidth; x++) {                                                    \
63                 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];     \
64                 fputc((c & 0xF800) >> 8, f);                                                            \
65                 fputc((c & 0x07E0) >> 3, f);                                                            \
66                 fputc((c & 0x001F) << 3, f);                                                            \
67               }                                                                                         \
68             }                                                                                           \
69             fclose(f);                                                                                  \
70           }
71
72 #define SNOOP_5551()                                                                                    \
73           {                                                                                             \
74             FILE *f;                                                                                    \
75             char buf[32];                                                                               \
76             int x, y;                                                                                   \
77                                                                                                         \
78             sprintf(buf, "%ld.pnm", dtpriv->tex_name);                                                  \
79             f = fopen(buf, "wb");                                                                       \
80             fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight);                          \
81             for (y = 0; y < src_d->dwHeight; y++) {                                                     \
82               for (x = 0; x < src_d->dwWidth; x++) {                                                    \
83                 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x];     \
84                 fputc((c & 0xF800) >> 8, f);                                                            \
85                 fputc((c & 0x07C0) >> 3, f);                                                            \
86                 fputc((c & 0x003E) << 2, f);                                                            \
87               }                                                                                         \
88             }                                                                                           \
89             fclose(f);                                                                                  \
90           }
91 #else
92 #define SNOOP_PALETTED()
93 #define SNOOP_5650()
94 #define SNOOP_5551()
95 #endif
96
97 extern ICOM_VTABLE(IDirect3DTexture2) mesa_texture2_vtable;
98 extern ICOM_VTABLE(IDirect3DTexture) mesa_texture_vtable;
99
100 /*******************************************************************************
101  *                              Texture2 Creation functions
102  */
103 LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf)
104 {
105   IDirect3DTexture2Impl* tex;
106   
107   tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
108   tex->ref = 1;
109   ICOM_VTBL(tex) = &mesa_texture2_vtable;
110   tex->surface = surf;
111
112   tex->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dt_private));
113   
114   return (LPDIRECT3DTEXTURE2)tex;
115 }
116
117 /*******************************************************************************
118  *                              Texture Creation functions
119  */
120 LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf)
121 {
122   IDirect3DTexture2Impl* tex;
123   
124   tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
125   tex->ref = 1;
126   ICOM_VTBL(tex) = (ICOM_VTABLE(IDirect3DTexture2)*)&mesa_texture_vtable;
127   tex->surface = surf;
128
129   tex->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dt_private));
130   
131   return (LPDIRECT3DTEXTURE)tex;
132 }
133
134 /*******************************************************************************
135  *                         IDirectSurface callback methods
136  */
137 HRESULT WINAPI  SetColorKey_cb(IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
138 {
139   DDSURFACEDESC *tex_d;
140   D3DTPRIVATE(texture);
141   int bpp;
142   GLuint current_texture;
143   
144   TRACE("(%p) : colorkey callback\n", texture);
145
146   /* Get the texture description */
147   tex_d = &(texture->surface->s.surface_desc);
148   bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
149          1 /* 8 bit of palette index */:
150          tex_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
151   
152   /* Now, save the current texture */
153   ENTER_GL();
154   glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
155
156   /* If the GetHandle was not done yet, it's an error */
157   if (dtpriv->tex_name == 0) {
158     ERR("Unloaded texture !\n");
159     LEAVE_GL();
160     return DD_OK;
161   }
162   glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
163
164   if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
165     FIXME("Todo Paletted\n");
166   } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
167     if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
168       FIXME("Todo 3_3_2_0\n");
169     } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
170       if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
171         /* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
172         unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
173                                                             HEAP_ZERO_MEMORY,
174                                                             tex_d->dwWidth * tex_d->dwHeight * bpp);
175         unsigned short *src = (unsigned short *) tex_d->u1.lpSurface;
176         int x, y;
177
178         for (y = 0; y < tex_d->dwHeight; y++) {
179           for (x = 0; x < tex_d->dwWidth; x++) {
180             unsigned short cpixel = src[x + y * tex_d->dwWidth];
181             
182             if ((dwFlags & DDCKEY_SRCBLT) &&
183                 (cpixel >= ckey->dwColorSpaceLowValue) &&
184                 (cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
185               dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
186             else                                         /* Alpha bit is set => this pixel will be seen */
187               dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001; 
188           }
189         }
190
191         glTexImage2D(GL_TEXTURE_2D,
192                      0,
193                      GL_RGBA,
194                      tex_d->dwWidth, tex_d->dwHeight,
195                      0,
196                      GL_RGBA,
197                      GL_UNSIGNED_SHORT_5_5_5_1,
198                      dest);
199
200         /* Frees the temporary surface */
201         HeapFree(GetProcessHeap(),0,dest);
202       } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
203         FIXME("Todo 5_5_5_1\n");
204       } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
205         FIXME("Todo 4_4_4_4\n");
206       } else {
207         ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
208       }
209     } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
210       FIXME("Todo 8_8_8_0\n");
211     } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
212       FIXME("Todo 8_8_8_8\n");
213     } else {
214       ERR("Unhandled texture format (bad RGB count)\n");
215     }
216   } else {
217     ERR("Unhandled texture format (neither RGB nor INDEX)\n");
218   }
219   LEAVE_GL();
220
221   return DD_OK;
222 }
223
224 /*******************************************************************************
225  *                              IDirect3DTexture2 methods
226  */
227
228 HRESULT WINAPI IDirect3DTexture2Impl_QueryInterface(LPDIRECT3DTEXTURE2 iface,
229                                                         REFIID riid,
230                                                         LPVOID* ppvObj)
231 {
232   ICOM_THIS(IDirect3DTexture2Impl,iface);
233   
234   FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
235   
236   return S_OK;
237 }
238
239
240
241 ULONG WINAPI IDirect3DTexture2Impl_AddRef(LPDIRECT3DTEXTURE2 iface)
242 {
243   ICOM_THIS(IDirect3DTexture2Impl,iface);
244   TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
245   
246   return ++(This->ref);
247 }
248
249
250
251 ULONG WINAPI IDirect3DTexture2Impl_Release(LPDIRECT3DTEXTURE2 iface)
252 {
253   ICOM_THIS(IDirect3DTexture2Impl,iface);
254   D3DTPRIVATE(This);
255   FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
256   
257   if (!--(This->ref)) {
258     /* Delete texture from OpenGL */
259     ENTER_GL();
260     glDeleteTextures(1, &(dtpriv->tex_name));
261     LEAVE_GL();
262     
263     /* Release surface */
264     IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->surface);
265     
266     HeapFree(GetProcessHeap(),0,This);
267     return 0;
268   }
269   
270   return This->ref;
271 }
272
273 /*** IDirect3DTexture methods ***/
274 HRESULT WINAPI IDirect3DTextureImpl_GetHandle(LPDIRECT3DTEXTURE iface,
275                                                  LPDIRECT3DDEVICE lpD3DDevice,
276                                                  LPD3DTEXTUREHANDLE lpHandle)
277 {
278     ICOM_THIS(IDirect3DTexture2Impl,iface);
279     D3DTPRIVATE(This);
280     IDirect3DDeviceImpl* ilpD3DDevice=(IDirect3DDeviceImpl*)lpD3DDevice;
281     FIXME("(%p)->(%p,%p): stub\n", This, ilpD3DDevice, lpHandle);
282
283     *lpHandle = (D3DTEXTUREHANDLE) This;
284
285     /* Now, bind a new texture */
286     ENTER_GL();
287     ilpD3DDevice->set_context(ilpD3DDevice);
288     This->D3Ddevice = (void *) ilpD3DDevice;
289     if (dtpriv->tex_name == 0)
290         glGenTextures(1, &(dtpriv->tex_name));
291     LEAVE_GL();
292
293     TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
294
295     return D3D_OK;
296 }
297
298 HRESULT WINAPI IDirect3DTextureImpl_Initialize(LPDIRECT3DTEXTURE iface,
299                                                   LPDIRECT3DDEVICE lpD3DDevice,
300                                                   LPDIRECTDRAWSURFACE lpSurface)
301 {
302   ICOM_THIS(IDirect3DTexture2Impl,iface);
303   TRACE("(%p)->(%p,%p)\n", This, lpD3DDevice, lpSurface);
304
305   return DDERR_ALREADYINITIALIZED;
306 }
307
308 HRESULT WINAPI IDirect3DTextureImpl_Unload(LPDIRECT3DTEXTURE iface)
309 {
310   ICOM_THIS(IDirect3DTexture2Impl,iface);
311   FIXME("(%p)->(): stub\n", This);
312
313   return D3D_OK;
314 }
315
316 /*** IDirect3DTexture2 methods ***/
317 HRESULT WINAPI IDirect3DTexture2Impl_GetHandle(LPDIRECT3DTEXTURE2 iface,
318                                                   LPDIRECT3DDEVICE2 lpD3DDevice2,
319                                                   LPD3DTEXTUREHANDLE lpHandle)
320 {
321     ICOM_THIS(IDirect3DTexture2Impl,iface);
322     D3DTPRIVATE(This);
323     IDirect3DDevice2Impl* ilpD3DDevice2=(IDirect3DDevice2Impl*)lpD3DDevice2;
324     TRACE("(%p)->(%p,%p)\n", This, ilpD3DDevice2, lpHandle);
325
326     /* For 32 bits OSes, handles = pointers */
327     *lpHandle = (D3DTEXTUREHANDLE) This;
328
329     /* Now, bind a new texture */
330     ENTER_GL();
331     ilpD3DDevice2->set_context(ilpD3DDevice2);
332     This->D3Ddevice = (void *) ilpD3DDevice2;
333     if (dtpriv->tex_name == 0)
334         glGenTextures(1, &(dtpriv->tex_name));
335     LEAVE_GL();
336
337     TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
338
339     return D3D_OK;
340 }
341
342 /* Common methods */
343 HRESULT WINAPI IDirect3DTexture2Impl_PaletteChanged(
344     LPDIRECT3DTEXTURE2 iface, DWORD dwStart, DWORD dwCount
345 ) {
346   ICOM_THIS(IDirect3DTexture2Impl,iface);
347   FIXME("(%p)->(%8ld,%8ld): stub\n", This, dwStart, dwCount);
348
349   return D3D_OK;
350 }
351
352 /* NOTE : if you experience crashes in this function, you must have a buggy
353           version of Mesa. See the file d3dtexture.c for a cure */
354 HRESULT WINAPI IDirect3DTexture2Impl_Load(
355     LPDIRECT3DTEXTURE2 iface, LPDIRECT3DTEXTURE2 lpD3DTexture2
356 ) {
357   ICOM_THIS(IDirect3DTexture2Impl,iface);
358   D3DTPRIVATE(This);
359   IDirect3DTexture2Impl* ilpD3DTexture2=(IDirect3DTexture2Impl*)lpD3DTexture2;
360   DDSURFACEDESC *src_d, *dst_d;
361   static void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
362                                     GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
363   static BOOL color_table_queried = FALSE;
364   
365   TRACE("(%p)->(%p)\n", This, ilpD3DTexture2);
366   TRACE("Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
367
368   /* Suppress the ALLOCONLOAD flag */
369   This->surface->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
370
371   /* Copy one surface on the other */
372   dst_d = &(This->surface->s.surface_desc);
373   src_d = &(ilpD3DTexture2->surface->s.surface_desc);
374
375   /* Install the callbacks to the destination surface */
376   This->surface->s.texture = This;
377   This->surface->s.SetColorKey_cb = SetColorKey_cb;
378   
379   if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
380     /* Should also check for same pixel format, lPitch, ... */
381     ERR("Error in surface sizes\n");
382     return D3DERR_TEXTURE_LOAD_FAILED;
383   } else {
384     /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
385     /* I should put a macro for the calculus of bpp */
386     int bpp = (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
387                1 /* 8 bit of palette index */:
388                src_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
389     GLuint current_texture;
390
391     /* Copy the main memry texture into the surface that corresponds to the OpenGL
392        texture object. */
393     memcpy(dst_d->u1.lpSurface, src_d->u1.lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
394
395     ENTER_GL();
396     
397     /* Now, load the texture */
398     /* d3dd->set_context(d3dd); We need to set the context somehow.... */
399     glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
400
401     /* If the GetHandle was not done, get the texture name here */
402     if (dtpriv->tex_name == 0)
403       glGenTextures(1, &(dtpriv->tex_name));
404     glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
405
406     if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
407       /* ****************
408          Paletted Texture
409          **************** */
410       IDirectDrawPaletteImpl* pal = This->surface->s.palette;
411       BYTE table[256][4];
412       int i;
413
414       if (color_table_queried == FALSE) {
415         ptr_ColorTableEXT =
416           ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
417       }
418       
419       if (pal == NULL) {
420         ERR("Palettized texture Loading with a NULL palette !\n");
421         LEAVE_GL();
422         return D3DERR_TEXTURE_LOAD_FAILED;
423       }
424
425       /* Get the surface's palette */
426       for (i = 0; i < 256; i++) {
427         table[i][0] = pal->palents[i].peRed;
428         table[i][1] = pal->palents[i].peGreen;
429         table[i][2] = pal->palents[i].peBlue;
430         if ((This->surface->s.surface_desc.dwFlags & DDSD_CKSRCBLT) &&
431             (i >= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
432             (i <= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
433           table[i][3] = 0x00;
434         else
435         table[i][3] = 0xFF;
436       }
437       
438       /* Texture snooping */
439       SNOOP_PALETTED();
440
441       if (ptr_ColorTableEXT != NULL) {
442         /* use Paletted Texture Extension */
443         ptr_ColorTableEXT(GL_TEXTURE_2D,    /* target */
444                           GL_RGBA,          /* internal format */
445                           256,              /* table size */
446                           GL_RGBA,          /* table format */
447                           GL_UNSIGNED_BYTE, /* table type */
448                           table);           /* the color table */
449         
450         glTexImage2D(GL_TEXTURE_2D,       /* target */
451                      0,                   /* level */
452                      GL_COLOR_INDEX8_EXT, /* internal format */
453                      src_d->dwWidth, src_d->dwHeight, /* width, height */
454                      0,                   /* border */
455                      GL_COLOR_INDEX,      /* texture format */
456                      GL_UNSIGNED_BYTE,    /* texture type */
457                      src_d->u1.lpSurface); /* the texture */
458       } else {
459         DWORD *surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
460         DWORD i;
461         BYTE *src = (BYTE *) src_d->u1.lpSurface, *dst = (BYTE *) surface;
462         
463         for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
464           BYTE color = *src++;
465           *dst++ = table[color][0];
466           *dst++ = table[color][1];
467           *dst++ = table[color][2];
468           *dst++ = table[color][3];
469         }
470         
471         glTexImage2D(GL_TEXTURE_2D,
472                      0,
473                      GL_RGBA,
474                      src_d->dwWidth, src_d->dwHeight,
475                      0,
476                      GL_RGBA,
477                      GL_UNSIGNED_BYTE,
478                      surface);
479         
480         HeapFree(GetProcessHeap(), 0, surface);
481       }
482     } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
483       /* ************
484          RGB Textures
485          ************ */
486       if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
487         /* **********************
488            GL_UNSIGNED_BYTE_3_3_2 
489            ********************** */
490         glTexImage2D(GL_TEXTURE_2D,
491                      0,
492                      GL_RGB,
493                      src_d->dwWidth, src_d->dwHeight,
494                      0,
495                      GL_RGB,
496                      GL_UNSIGNED_BYTE_3_3_2,
497                      src_d->u1.lpSurface);
498       } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
499         if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
500             
501           /* Texture snooping */
502           SNOOP_5650();
503           
504           glTexImage2D(GL_TEXTURE_2D,
505                        0,
506                        GL_RGB,
507                        src_d->dwWidth, src_d->dwHeight,
508                        0,
509                        GL_RGB,
510                        GL_UNSIGNED_SHORT_5_6_5,
511                        src_d->u1.lpSurface);
512         } else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
513           /* Texture snooping */
514           SNOOP_5551();
515           
516           glTexImage2D(GL_TEXTURE_2D,
517                        0,
518                        GL_RGBA,
519                        src_d->dwWidth, src_d->dwHeight,
520                        0,
521                        GL_RGBA,
522                        GL_UNSIGNED_SHORT_5_5_5_1,
523                        src_d->u1.lpSurface);
524         } else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
525           glTexImage2D(GL_TEXTURE_2D,
526                        0,
527                        GL_RGBA,
528                        src_d->dwWidth, src_d->dwHeight,
529                        0,
530                        GL_RGBA,
531                        GL_UNSIGNED_SHORT_4_4_4_4,
532                        src_d->u1.lpSurface);
533         } else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00008000) {
534           /* Converting the 1555 format in 5551 packed */
535           WORD *surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
536           DWORD i;
537           WORD *src = (WORD *) src_d->u1.lpSurface, *dst = surface;
538
539           for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
540             *dst++ = (((*src & 0x8000) >> 15) |
541                       ((*src & 0x7FFF) <<  1));
542             src++;
543           }
544           
545           glTexImage2D(GL_TEXTURE_2D,
546                        0,
547                        GL_RGBA,
548                        src_d->dwWidth, src_d->dwHeight,
549                        0,
550                        GL_RGBA,
551                        GL_UNSIGNED_SHORT_5_5_5_1,
552                        surface);
553           
554           HeapFree(GetProcessHeap(), 0, surface);         
555         } else {
556           ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
557         }
558       } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
559         glTexImage2D(GL_TEXTURE_2D,
560                      0,
561                      GL_RGB,
562                      src_d->dwWidth, src_d->dwHeight,
563                      0,
564                      GL_RGB,
565                      GL_UNSIGNED_BYTE,
566                      src_d->u1.lpSurface);
567       } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
568         glTexImage2D(GL_TEXTURE_2D,
569                      0,
570                      GL_RGBA,
571                      src_d->dwWidth, src_d->dwHeight,
572                      0,
573                      GL_RGBA,
574                      GL_UNSIGNED_BYTE,
575                      src_d->u1.lpSurface);
576       } else {
577         ERR("Unhandled texture format (bad RGB count)\n");
578       }
579     } else {
580       ERR("Unhandled texture format (neither RGB nor INDEX)\n");
581     }
582
583     glBindTexture(GL_TEXTURE_2D, current_texture);
584
585     LEAVE_GL();
586   }
587   
588   return D3D_OK;
589 }
590
591
592 /*******************************************************************************
593  *                              IDirect3DTexture2 VTable
594  */
595 ICOM_VTABLE(IDirect3DTexture2) mesa_texture2_vtable = 
596 {
597   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
598   /*** IUnknown methods ***/
599   IDirect3DTexture2Impl_QueryInterface,
600   IDirect3DTexture2Impl_AddRef,
601   IDirect3DTexture2Impl_Release,
602   /*** IDirect3DTexture methods ***/
603   IDirect3DTexture2Impl_GetHandle,
604   IDirect3DTexture2Impl_PaletteChanged,
605   IDirect3DTexture2Impl_Load
606 };
607
608 /*******************************************************************************
609  *                              IDirect3DTexture VTable
610  */
611 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
612 # define XCAST(fun)     (typeof(mesa_texture_vtable.fn##fun))
613 #else
614 # define XCAST(fun)     (void*)
615 #endif
616
617 ICOM_VTABLE(IDirect3DTexture) mesa_texture_vtable = 
618 {
619   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
620   /*** IUnknown methods ***/
621   XCAST(QueryInterface)IDirect3DTexture2Impl_QueryInterface,
622   XCAST(AddRef)IDirect3DTexture2Impl_AddRef,
623   XCAST(Release)IDirect3DTexture2Impl_Release,
624   /*** IDirect3DTexture methods ***/
625   IDirect3DTextureImpl_Initialize,
626   IDirect3DTextureImpl_GetHandle,
627   XCAST(PaletteChanged)IDirect3DTexture2Impl_PaletteChanged,
628   XCAST(Load)IDirect3DTexture2Impl_Load,
629   IDirect3DTextureImpl_Unload
630 };
631
632 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
633 #undef XCAST
634 #endif