4 This files contains the implementation of interface Direct3DTexture2. */
13 #include "wine/obj_base.h"
16 #include "debugtools.h"
18 #include "mesa_private.h"
20 #define D3DDPRIVATE(x) mesa_d3dd_private*odev=(mesa_d3dd_private*)(x)->private
21 #define D3DTPRIVATE(x) mesa_d3dt_private*dtpriv=(mesa_d3dt_private*)(x)->private
23 DEFAULT_DEBUG_CHANNEL(ddraw);
25 /* Define this if you want to save to a file all the textures used by a game
26 (can be funny to see how they managed to cram all the pictures in
33 #define SNOOP_PALETTED() \
39 sprintf(buf, "%ld.pnm", dtpriv->tex_name); \
40 f = fopen(buf, "wb"); \
41 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
42 for (y = 0; y < src_d->dwHeight; y++) { \
43 for (x = 0; x < src_d->dwWidth; x++) { \
44 unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
45 fputc(table[c][0], f); \
46 fputc(table[c][1], f); \
47 fputc(table[c][2], f); \
53 #define SNOOP_5650() \
59 sprintf(buf, "%ld.pnm", dtpriv->tex_name); \
60 f = fopen(buf, "wb"); \
61 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
62 for (y = 0; y < src_d->dwHeight; y++) { \
63 for (x = 0; x < src_d->dwWidth; x++) { \
64 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
65 fputc((c & 0xF800) >> 8, f); \
66 fputc((c & 0x07E0) >> 3, f); \
67 fputc((c & 0x001F) << 3, f); \
73 #define SNOOP_5551() \
79 sprintf(buf, "%ld.pnm", dtpriv->tex_name); \
80 f = fopen(buf, "wb"); \
81 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
82 for (y = 0; y < src_d->dwHeight; y++) { \
83 for (x = 0; x < src_d->dwWidth; x++) { \
84 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
85 fputc((c & 0xF800) >> 8, f); \
86 fputc((c & 0x07C0) >> 3, f); \
87 fputc((c & 0x003E) << 2, f); \
93 #define SNOOP_PALETTED()
98 extern ICOM_VTABLE(IDirect3DTexture2) mesa_texture2_vtable;
99 extern ICOM_VTABLE(IDirect3DTexture) mesa_texture_vtable;
101 /*******************************************************************************
102 * Texture2 Creation functions
104 LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurfaceImpl* surf)
106 IDirect3DTexture2Impl* tex;
108 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
110 ICOM_VTBL(tex) = &mesa_texture2_vtable;
113 tex->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dt_private));
115 return (LPDIRECT3DTEXTURE2)tex;
118 /*******************************************************************************
119 * Texture Creation functions
121 LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurfaceImpl* surf)
123 IDirect3DTexture2Impl* tex;
125 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
127 ICOM_VTBL(tex) = (ICOM_VTABLE(IDirect3DTexture2)*)&mesa_texture_vtable;
130 tex->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(mesa_d3dt_private));
132 return (LPDIRECT3DTEXTURE)tex;
135 /*******************************************************************************
136 * IDirectSurface callback methods
138 HRESULT WINAPI SetColorKey_cb(IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
140 DDSURFACEDESC *tex_d;
141 D3DTPRIVATE(texture);
143 GLuint current_texture;
145 TRACE("(%p) : colorkey callback\n", texture);
147 /* Get the texture description */
148 tex_d = (DDSURFACEDESC *)&(texture->surface->surface_desc);
149 bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
150 1 /* 8 bit of palette index */:
151 tex_d->ddpfPixelFormat.u1.dwRGBBitCount / 8 /* RGB bits for each colors */ );
153 /* Now, save the current texture */
155 glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
157 /* If the GetHandle was not done yet, it's an error */
158 if (dtpriv->tex_name == 0) {
159 ERR("Unloaded texture !\n");
163 glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
165 if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
166 FIXME("Todo Paletted\n");
167 } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
168 if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
169 FIXME("Todo 3_3_2_0\n");
170 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
171 if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
172 /* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
173 unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
175 tex_d->dwWidth * tex_d->dwHeight * bpp);
176 unsigned short *src = (unsigned short *) tex_d->lpSurface;
179 for (y = 0; y < tex_d->dwHeight; y++) {
180 for (x = 0; x < tex_d->dwWidth; x++) {
181 unsigned short cpixel = src[x + y * tex_d->dwWidth];
183 if ((dwFlags & DDCKEY_SRCBLT) &&
184 (cpixel >= ckey->dwColorSpaceLowValue) &&
185 (cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
186 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
187 else /* Alpha bit is set => this pixel will be seen */
188 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001;
192 glTexImage2D(GL_TEXTURE_2D,
195 tex_d->dwWidth, tex_d->dwHeight,
198 GL_UNSIGNED_SHORT_5_5_5_1,
201 /* Frees the temporary surface */
202 HeapFree(GetProcessHeap(),0,dest);
203 } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
204 FIXME("Todo 5_5_5_1\n");
205 } else if (tex_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
206 FIXME("Todo 4_4_4_4\n");
208 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
210 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
211 FIXME("Todo 8_8_8_0\n");
212 } else if (tex_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
213 FIXME("Todo 8_8_8_8\n");
215 ERR("Unhandled texture format (bad RGB count)\n");
218 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
225 /*******************************************************************************
226 * IDirect3DTexture2 methods
229 HRESULT WINAPI IDirect3DTexture2Impl_QueryInterface(LPDIRECT3DTEXTURE2 iface,
233 ICOM_THIS(IDirect3DTexture2Impl,iface);
235 FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
242 ULONG WINAPI IDirect3DTexture2Impl_AddRef(LPDIRECT3DTEXTURE2 iface)
244 ICOM_THIS(IDirect3DTexture2Impl,iface);
245 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
247 return ++(This->ref);
252 ULONG WINAPI IDirect3DTexture2Impl_Release(LPDIRECT3DTEXTURE2 iface)
254 ICOM_THIS(IDirect3DTexture2Impl,iface);
256 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
258 if (!--(This->ref)) {
259 /* Delete texture from OpenGL */
261 glDeleteTextures(1, &(dtpriv->tex_name));
264 /* Release surface */
265 IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->surface);
267 HeapFree(GetProcessHeap(),0,This);
274 /*** IDirect3DTexture methods ***/
275 HRESULT WINAPI IDirect3DTextureImpl_GetHandle(LPDIRECT3DTEXTURE iface,
276 LPDIRECT3DDEVICE lpD3DDevice,
277 LPD3DTEXTUREHANDLE lpHandle)
279 ICOM_THIS(IDirect3DTexture2Impl,iface);
281 IDirect3DDeviceImpl* ilpD3DDevice=(IDirect3DDeviceImpl*)lpD3DDevice;
282 FIXME("(%p)->(%p,%p): stub\n", This, ilpD3DDevice, lpHandle);
284 *lpHandle = (D3DTEXTUREHANDLE) This;
286 /* Now, bind a new texture */
288 ilpD3DDevice->set_context(ilpD3DDevice);
289 This->D3Ddevice = (void *) ilpD3DDevice;
290 if (dtpriv->tex_name == 0)
291 glGenTextures(1, &(dtpriv->tex_name));
294 TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
299 HRESULT WINAPI IDirect3DTextureImpl_Initialize(LPDIRECT3DTEXTURE iface,
300 LPDIRECT3DDEVICE lpD3DDevice,
301 LPDIRECTDRAWSURFACE lpSurface)
303 ICOM_THIS(IDirect3DTexture2Impl,iface);
304 TRACE("(%p)->(%p,%p)\n", This, lpD3DDevice, lpSurface);
306 return DDERR_ALREADYINITIALIZED;
309 HRESULT WINAPI IDirect3DTextureImpl_Unload(LPDIRECT3DTEXTURE iface)
311 ICOM_THIS(IDirect3DTexture2Impl,iface);
312 FIXME("(%p)->(): stub\n", This);
317 /*** IDirect3DTexture2 methods ***/
318 HRESULT WINAPI IDirect3DTexture2Impl_GetHandle(LPDIRECT3DTEXTURE2 iface,
319 LPDIRECT3DDEVICE2 lpD3DDevice2,
320 LPD3DTEXTUREHANDLE lpHandle)
322 ICOM_THIS(IDirect3DTexture2Impl,iface);
324 IDirect3DDevice2Impl* ilpD3DDevice2=(IDirect3DDevice2Impl*)lpD3DDevice2;
325 TRACE("(%p)->(%p,%p)\n", This, ilpD3DDevice2, lpHandle);
327 /* For 32 bits OSes, handles = pointers */
328 *lpHandle = (D3DTEXTUREHANDLE) This;
330 /* Now, bind a new texture */
332 ilpD3DDevice2->set_context(ilpD3DDevice2);
333 This->D3Ddevice = (void *) ilpD3DDevice2;
334 if (dtpriv->tex_name == 0)
335 glGenTextures(1, &(dtpriv->tex_name));
338 TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
344 HRESULT WINAPI IDirect3DTexture2Impl_PaletteChanged(
345 LPDIRECT3DTEXTURE2 iface, DWORD dwStart, DWORD dwCount
347 ICOM_THIS(IDirect3DTexture2Impl,iface);
348 FIXME("(%p)->(%8ld,%8ld): stub\n", This, dwStart, dwCount);
353 /* NOTE : if you experience crashes in this function, you must have a buggy
354 version of Mesa. See the file d3dtexture.c for a cure */
355 HRESULT WINAPI IDirect3DTexture2Impl_Load(
356 LPDIRECT3DTEXTURE2 iface, LPDIRECT3DTEXTURE2 lpD3DTexture2
358 ICOM_THIS(IDirect3DTexture2Impl,iface);
360 IDirect3DTexture2Impl* ilpD3DTexture2=(IDirect3DTexture2Impl*)lpD3DTexture2;
361 DDSURFACEDESC *src_d, *dst_d;
362 static void (*ptr_ColorTableEXT) (GLenum target, GLenum internalformat,
363 GLsizei width, GLenum format, GLenum type, const GLvoid *table) = NULL;
365 static BOOL color_table_queried = FALSE;
368 TRACE("(%p)->(%p)\n", This, ilpD3DTexture2);
369 TRACE("Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
371 /* Suppress the ALLOCONLOAD flag */
372 This->surface->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
374 /* Copy one surface on the other */
375 dst_d = (DDSURFACEDESC *)&(This->surface->surface_desc);
376 src_d = (DDSURFACEDESC *)&(ilpD3DTexture2->surface->surface_desc);
378 /* Install the callbacks to the destination surface */
379 This->surface->texture = This;
380 This->surface->SetColorKey_cb = SetColorKey_cb;
382 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
383 /* Should also check for same pixel format, lPitch, ... */
384 ERR("Error in surface sizes\n");
385 return D3DERR_TEXTURE_LOAD_FAILED;
387 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
388 /* I should put a macro for the calculus of bpp */
389 int bpp = (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
390 1 /* 8 bit of palette index */:
391 src_d->ddpfPixelFormat.u1.dwRGBBitCount / 8 /* RGB bits for each colors */ );
392 GLuint current_texture;
394 /* Copy the main memry texture into the surface that corresponds to the OpenGL
396 memcpy(dst_d->lpSurface, src_d->lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
400 /* Now, load the texture */
401 /* d3dd->set_context(d3dd); We need to set the context somehow.... */
402 glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
404 /* If the GetHandle was not done, get the texture name here */
405 if (dtpriv->tex_name == 0)
406 glGenTextures(1, &(dtpriv->tex_name));
407 glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
409 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
413 IDirectDrawPaletteImpl* pal = This->surface->palette;
418 if (color_table_queried == FALSE) {
420 ((Mesa_DeviceCapabilities *) ((x11_dd_private *) This->surface->s.ddraw->d->private)->device_capabilities)->ptr_ColorTableEXT;
425 ERR("Palettized texture Loading with a NULL palette !\n");
427 return D3DERR_TEXTURE_LOAD_FAILED;
430 /* Get the surface's palette */
431 for (i = 0; i < 256; i++) {
432 table[i][0] = pal->palents[i].peRed;
433 table[i][1] = pal->palents[i].peGreen;
434 table[i][2] = pal->palents[i].peBlue;
435 if ((This->surface->surface_desc.dwFlags & DDSD_CKSRCBLT) &&
436 (i >= This->surface->surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
437 (i <= This->surface->surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
443 /* Texture snooping */
446 if (ptr_ColorTableEXT != NULL) {
447 /* use Paletted Texture Extension */
448 ptr_ColorTableEXT(GL_TEXTURE_2D, /* target */
449 GL_RGBA, /* internal format */
450 256, /* table size */
451 GL_RGBA, /* table format */
452 GL_UNSIGNED_BYTE, /* table type */
453 table); /* the color table */
455 glTexImage2D(GL_TEXTURE_2D, /* target */
457 GL_COLOR_INDEX8_EXT, /* internal format */
458 src_d->dwWidth, src_d->dwHeight, /* width, height */
460 GL_COLOR_INDEX, /* texture format */
461 GL_UNSIGNED_BYTE, /* texture type */
462 src_d->lpSurface); /* the texture */
464 DWORD *surface = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
466 BYTE *src = (BYTE *) src_d->lpSurface, *dst = (BYTE *) surface;
468 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
470 *dst++ = table[color][0];
471 *dst++ = table[color][1];
472 *dst++ = table[color][2];
473 *dst++ = table[color][3];
476 glTexImage2D(GL_TEXTURE_2D,
479 src_d->dwWidth, src_d->dwHeight,
485 HeapFree(GetProcessHeap(), 0, surface);
487 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
491 if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 8) {
492 /* **********************
493 GL_UNSIGNED_BYTE_3_3_2
494 ********************** */
495 glTexImage2D(GL_TEXTURE_2D,
498 src_d->dwWidth, src_d->dwHeight,
501 GL_UNSIGNED_BYTE_3_3_2,
503 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 16) {
504 if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000) {
506 /* Texture snooping */
509 glTexImage2D(GL_TEXTURE_2D,
512 src_d->dwWidth, src_d->dwHeight,
515 GL_UNSIGNED_SHORT_5_6_5,
517 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000001) {
518 /* Texture snooping */
521 glTexImage2D(GL_TEXTURE_2D,
524 src_d->dwWidth, src_d->dwHeight,
527 GL_UNSIGNED_SHORT_5_5_5_1,
529 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000000F) {
530 glTexImage2D(GL_TEXTURE_2D,
533 src_d->dwWidth, src_d->dwHeight,
536 GL_UNSIGNED_SHORT_4_4_4_4,
538 } else if (src_d->ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00008000) {
539 /* Converting the 1555 format in 5551 packed */
540 WORD *surface = (WORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
542 WORD *src = (WORD *) src_d->lpSurface, *dst = surface;
544 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
545 *dst++ = (((*src & 0x8000) >> 15) |
546 ((*src & 0x7FFF) << 1));
550 glTexImage2D(GL_TEXTURE_2D,
553 src_d->dwWidth, src_d->dwHeight,
556 GL_UNSIGNED_SHORT_5_5_5_1,
559 HeapFree(GetProcessHeap(), 0, surface);
561 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
563 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 24) {
564 glTexImage2D(GL_TEXTURE_2D,
567 src_d->dwWidth, src_d->dwHeight,
572 } else if (src_d->ddpfPixelFormat.u1.dwRGBBitCount == 32) {
573 glTexImage2D(GL_TEXTURE_2D,
576 src_d->dwWidth, src_d->dwHeight,
582 ERR("Unhandled texture format (bad RGB count)\n");
585 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
588 glBindTexture(GL_TEXTURE_2D, current_texture);
597 /*******************************************************************************
598 * IDirect3DTexture2 VTable
600 ICOM_VTABLE(IDirect3DTexture2) mesa_texture2_vtable =
602 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
603 /*** IUnknown methods ***/
604 IDirect3DTexture2Impl_QueryInterface,
605 IDirect3DTexture2Impl_AddRef,
606 IDirect3DTexture2Impl_Release,
607 /*** IDirect3DTexture methods ***/
608 IDirect3DTexture2Impl_GetHandle,
609 IDirect3DTexture2Impl_PaletteChanged,
610 IDirect3DTexture2Impl_Load
613 /*******************************************************************************
614 * IDirect3DTexture VTable
616 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
617 # define XCAST(fun) (typeof(mesa_texture_vtable.fun))
619 # define XCAST(fun) (void*)
622 ICOM_VTABLE(IDirect3DTexture) mesa_texture_vtable =
624 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
625 /*** IUnknown methods ***/
626 XCAST(QueryInterface)IDirect3DTexture2Impl_QueryInterface,
627 XCAST(AddRef)IDirect3DTexture2Impl_AddRef,
628 XCAST(Release)IDirect3DTexture2Impl_Release,
629 /*** IDirect3DTexture methods ***/
630 IDirect3DTextureImpl_Initialize,
631 IDirect3DTextureImpl_GetHandle,
632 XCAST(PaletteChanged)IDirect3DTexture2Impl_PaletteChanged,
633 XCAST(Load)IDirect3DTexture2Impl_Load,
634 IDirect3DTextureImpl_Unload
637 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)