Fixed warning.
[wine/wine-kai.git] / graphics / d3dtexture.c
blob5f4fea057e9786793c2e8961bc59e9a924f42da8
1 /* Direct3D Texture
2 (c) 1998 Lionel ULMER
4 This files contains the implementation of interface Direct3DTexture2. */
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 "debug.h"
17 #include "d3d_private.h"
19 #ifdef HAVE_MESAGL
21 /* Define this if you want to save to a file all the textures used by a game
22 (can be funny to see how they managed to cram all the pictures in
23 texture memory) */
24 #undef TEXTURE_SNOOP
26 #ifdef TEXTURE_SNOOP
27 #define SNOOP_PALETTED() \
28 { \
29 FILE *f; \
30 char buf[32]; \
31 int x, y; \
33 sprintf(buf, "%d.pnm", This->tex_name); \
34 f = fopen(buf, "wb"); \
35 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
36 for (y = 0; y < src_d->dwHeight; y++) { \
37 for (x = 0; x < src_d->dwWidth; x++) { \
38 unsigned char c = ((unsigned char *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
39 fputc(table[c][0], f); \
40 fputc(table[c][1], f); \
41 fputc(table[c][2], f); \
42 } \
43 } \
44 fclose(f); \
47 #define SNOOP_5650() \
48 { \
49 FILE *f; \
50 char buf[32]; \
51 int x, y; \
53 sprintf(buf, "%d.pnm", This->tex_name); \
54 f = fopen(buf, "wb"); \
55 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
56 for (y = 0; y < src_d->dwHeight; y++) { \
57 for (x = 0; x < src_d->dwWidth; x++) { \
58 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
59 fputc((c & 0xF800) >> 8, f); \
60 fputc((c & 0x07E0) >> 3, f); \
61 fputc((c & 0x001F) << 3, f); \
62 } \
63 } \
64 fclose(f); \
67 #define SNOOP_5551() \
68 { \
69 FILE *f; \
70 char buf[32]; \
71 int x, y; \
73 sprintf(buf, "%d.pnm", This->tex_name); \
74 f = fopen(buf, "wb"); \
75 fprintf(f, "P6\n%ld %ld\n255\n", src_d->dwWidth, src_d->dwHeight); \
76 for (y = 0; y < src_d->dwHeight; y++) { \
77 for (x = 0; x < src_d->dwWidth; x++) { \
78 unsigned short c = ((unsigned short *) src_d->y.lpSurface)[y * src_d->dwWidth + x]; \
79 fputc((c & 0xF800) >> 8, f); \
80 fputc((c & 0x07C0) >> 3, f); \
81 fputc((c & 0x003E) << 2, f); \
82 } \
83 } \
84 fclose(f); \
86 #else
87 #define SNOOP_PALETTED()
88 #define SNOOP_5650()
89 #define SNOOP_5551()
90 #endif
92 static ICOM_VTABLE(IDirect3DTexture2) texture2_vtable;
93 static ICOM_VTABLE(IDirect3DTexture) texture_vtable;
95 /*******************************************************************************
96 * Texture2 Creation functions
98 LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf)
100 IDirect3DTexture2Impl* tex;
102 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
103 tex->ref = 1;
104 tex->lpvtbl = &texture2_vtable;
105 tex->surface = surf;
107 return (LPDIRECT3DTEXTURE2)tex;
110 /*******************************************************************************
111 * Texture Creation functions
113 LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf)
115 IDirect3DTexture2Impl* tex;
117 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
118 tex->ref = 1;
119 tex->lpvtbl = (ICOM_VTABLE(IDirect3DTexture2)*)&texture_vtable;
120 tex->surface = surf;
122 return (LPDIRECT3DTEXTURE)tex;
125 /*******************************************************************************
126 * IDirectSurface callback methods
128 HRESULT WINAPI SetColorKey_cb(IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
130 DDSURFACEDESC *tex_d;
131 int bpp;
132 GLuint current_texture;
134 TRACE(ddraw, "(%p) : colorkey callback\n", texture);
136 /* Get the texture description */
137 tex_d = &(texture->surface->s.surface_desc);
138 bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
139 1 /* 8 bit of palette index */:
140 tex_d->ddpfPixelFormat.x.dwRGBBitCount / 8 /* RGB bits for each colors */ );
142 /* Now, save the current texture */
143 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
145 /* If the GetHandle was not done yet, it's an error */
146 if (texture->tex_name == 0) {
147 ERR(ddraw, "Unloaded texture !\n");
148 return DD_OK;
150 glBindTexture(GL_TEXTURE_2D, texture->tex_name);
152 if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
153 FIXME(ddraw, "Todo Paletted\n");
154 } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
155 if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 8) {
156 FIXME(ddraw, "Todo 3_3_2_0\n");
157 } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 16) {
158 if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000000) {
159 /* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
160 unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
161 HEAP_ZERO_MEMORY,
162 tex_d->dwWidth * tex_d->dwHeight * bpp);
163 unsigned short *src = (unsigned short *) tex_d->y.lpSurface;
164 int x, y;
166 for (y = 0; y < tex_d->dwHeight; y++) {
167 for (x = 0; x < tex_d->dwWidth; x++) {
168 unsigned short cpixel = src[x + y * tex_d->dwWidth];
170 if ((dwFlags & DDCKEY_SRCBLT) &&
171 (cpixel >= ckey->dwColorSpaceLowValue) &&
172 (cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
173 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
174 else /* Alpha bit is set => this pixel will be seen */
175 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001;
179 glTexImage2D(GL_TEXTURE_2D,
181 GL_RGBA,
182 tex_d->dwWidth, tex_d->dwHeight,
184 GL_RGBA,
185 GL_UNSIGNED_SHORT_5_5_5_1,
186 dest);
188 /* Frees the temporary surface */
189 HeapFree(GetProcessHeap(),0,dest);
190 } else if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000001) {
191 FIXME(ddraw, "Todo 5_5_5_1\n");
192 } else if (tex_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x0000000F) {
193 FIXME(ddraw, "Todo 4_4_4_4\n");
194 } else {
195 ERR(ddraw, "Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
197 } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 24) {
198 FIXME(ddraw, "Todo 8_8_8_0\n");
199 } else if (tex_d->ddpfPixelFormat.x.dwRGBBitCount == 32) {
200 FIXME(ddraw, "Todo 8_8_8_8\n");
201 } else {
202 ERR(ddraw, "Unhandled texture format (bad RGB count)\n");
204 } else {
205 ERR(ddraw, "Unhandled texture format (neither RGB nor INDEX)\n");
208 return DD_OK;
211 /*******************************************************************************
212 * IDirect3DTexture2 methods
215 static HRESULT WINAPI IDirect3DTexture2Impl_QueryInterface(LPDIRECT3DTEXTURE2 iface,
216 REFIID riid,
217 LPVOID* ppvObj)
219 ICOM_THIS(IDirect3DTexture2Impl,iface);
220 char xrefiid[50];
222 WINE_StringFromCLSID((LPCLSID)riid,xrefiid);
223 FIXME(ddraw, "(%p)->(%s,%p): stub\n", This, xrefiid,ppvObj);
225 return S_OK;
230 static ULONG WINAPI IDirect3DTexture2Impl_AddRef(LPDIRECT3DTEXTURE2 iface)
232 ICOM_THIS(IDirect3DTexture2Impl,iface);
233 TRACE(ddraw, "(%p)->()incrementing from %lu.\n", This, This->ref );
235 return ++(This->ref);
240 static ULONG WINAPI IDirect3DTexture2Impl_Release(LPDIRECT3DTEXTURE2 iface)
242 ICOM_THIS(IDirect3DTexture2Impl,iface);
243 FIXME( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
245 if (!--(This->ref)) {
246 /* Delete texture from OpenGL */
247 glDeleteTextures(1, &(This->tex_name));
249 /* Release surface */
250 IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->surface);
252 HeapFree(GetProcessHeap(),0,This);
253 return 0;
256 return This->ref;
259 /*** IDirect3DTexture methods ***/
260 static HRESULT WINAPI IDirect3DTextureImpl_GetHandle(LPDIRECT3DTEXTURE iface,
261 LPDIRECT3DDEVICE lpD3DDevice,
262 LPD3DTEXTUREHANDLE lpHandle)
264 ICOM_THIS(IDirect3DTexture2Impl,iface);
265 IDirect3DDeviceImpl* ilpD3DDevice=(IDirect3DDeviceImpl*)lpD3DDevice;
266 FIXME(ddraw, "(%p)->(%p,%p): stub\n", This, ilpD3DDevice, lpHandle);
268 *lpHandle = (D3DTEXTUREHANDLE) This;
270 /* Now, bind a new texture */
271 ilpD3DDevice->set_context(ilpD3DDevice);
272 This->D3Ddevice = (void *) ilpD3DDevice;
273 if (This->tex_name == 0)
274 glGenTextures(1, &(This->tex_name));
276 TRACE(ddraw, "OpenGL texture handle is : %d\n", This->tex_name);
278 return D3D_OK;
281 static HRESULT WINAPI IDirect3DTextureImpl_Initialize(LPDIRECT3DTEXTURE iface,
282 LPDIRECT3DDEVICE lpD3DDevice,
283 LPDIRECTDRAWSURFACE lpSurface)
285 ICOM_THIS(IDirect3DTexture2Impl,iface);
286 TRACE(ddraw, "(%p)->(%p,%p)\n", This, lpD3DDevice, lpSurface);
288 return DDERR_ALREADYINITIALIZED;
291 static HRESULT WINAPI IDirect3DTextureImpl_Unload(LPDIRECT3DTEXTURE iface)
293 ICOM_THIS(IDirect3DTexture2Impl,iface);
294 FIXME(ddraw, "(%p)->(): stub\n", This);
296 return D3D_OK;
299 /*** IDirect3DTexture2 methods ***/
300 static HRESULT WINAPI IDirect3DTexture2Impl_GetHandle(LPDIRECT3DTEXTURE2 iface,
301 LPDIRECT3DDEVICE2 lpD3DDevice2,
302 LPD3DTEXTUREHANDLE lpHandle)
304 ICOM_THIS(IDirect3DTexture2Impl,iface);
305 IDirect3DDevice2Impl* ilpD3DDevice2=(IDirect3DDevice2Impl*)lpD3DDevice2;
306 TRACE(ddraw, "(%p)->(%p,%p)\n", This, ilpD3DDevice2, lpHandle);
308 /* For 32 bits OSes, handles = pointers */
309 *lpHandle = (D3DTEXTUREHANDLE) This;
311 /* Now, bind a new texture */
312 ilpD3DDevice2->set_context(ilpD3DDevice2);
313 This->D3Ddevice = (void *) ilpD3DDevice2;
314 if (This->tex_name == 0)
315 glGenTextures(1, &(This->tex_name));
317 TRACE(ddraw, "OpenGL texture handle is : %d\n", This->tex_name);
319 return D3D_OK;
322 /* Common methods */
323 static HRESULT WINAPI IDirect3DTexture2Impl_PaletteChanged(LPDIRECT3DTEXTURE2 iface,
324 DWORD dwStart,
325 DWORD dwCount)
327 ICOM_THIS(IDirect3DTexture2Impl,iface);
328 FIXME(ddraw, "(%p)->(%8ld,%8ld): stub\n", This, dwStart, dwCount);
330 return D3D_OK;
333 /* NOTE : if you experience crashes in this function, you must have a buggy
334 version of Mesa. See the file d3dtexture.c for a cure */
335 static HRESULT WINAPI IDirect3DTexture2Impl_Load(LPDIRECT3DTEXTURE2 iface,
336 LPDIRECT3DTEXTURE2 lpD3DTexture2)
338 ICOM_THIS(IDirect3DTexture2Impl,iface);
339 IDirect3DTexture2Impl* ilpD3DTexture2=(IDirect3DTexture2Impl*)lpD3DTexture2;
340 DDSURFACEDESC *src_d, *dst_d;
341 TRACE(ddraw, "(%p)->(%p)\n", This, ilpD3DTexture2);
343 TRACE(ddraw, "Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
345 /* Suppress the ALLOCONLOAD flag */
346 This->surface->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
348 /* Copy one surface on the other */
349 dst_d = &(This->surface->s.surface_desc);
350 src_d = &(ilpD3DTexture2->surface->s.surface_desc);
352 /* Install the callbacks to the destination surface */
353 This->surface->s.texture = This;
354 This->surface->s.SetColorKey_cb = SetColorKey_cb;
356 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
357 /* Should also check for same pixel format, lPitch, ... */
358 ERR(ddraw, "Error in surface sizes\n");
359 return D3DERR_TEXTURE_LOAD_FAILED;
360 } else {
361 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
362 /* I should put a macro for the calculus of bpp */
363 int bpp = (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
364 1 /* 8 bit of palette index */:
365 src_d->ddpfPixelFormat.x.dwRGBBitCount / 8 /* RGB bits for each colors */ );
366 GLuint current_texture;
368 /* Copy the main memry texture into the surface that corresponds to the OpenGL
369 texture object. */
370 memcpy(dst_d->y.lpSurface, src_d->y.lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
372 /* Now, load the texture */
373 /* d3dd->set_context(d3dd); We need to set the context somehow.... */
374 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
376 /* If the GetHandle was not done, get the texture name here */
377 if (This->tex_name == 0)
378 glGenTextures(1, &(This->tex_name));
379 glBindTexture(GL_TEXTURE_2D, This->tex_name);
381 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
382 /* ****************
383 Paletted Texture
384 **************** */
385 IDirectDrawPaletteImpl* pal = This->surface->s.palette;
386 BYTE table[256][4];
387 int i;
389 if (pal == NULL) {
390 ERR(ddraw, "Palettized texture Loading with a NULL palette !\n");
391 return D3DERR_TEXTURE_LOAD_FAILED;
394 /* Get the surface's palette */
395 for (i = 0; i < 256; i++) {
396 table[i][0] = pal->palents[i].peRed;
397 table[i][1] = pal->palents[i].peGreen;
398 table[i][2] = pal->palents[i].peBlue;
399 if ((This->surface->s.surface_desc.dwFlags & DDSD_CKSRCBLT) &&
400 (i >= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
401 (i <= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
402 table[i][3] = 0x00;
403 else
404 table[i][3] = 0xFF;
407 /* Texture snooping */
408 SNOOP_PALETTED();
410 /* Use Paletted Texture Extension */
411 glColorTableEXT(GL_TEXTURE_2D, /* target */
412 GL_RGBA, /* internal format */
413 256, /* table size */
414 GL_RGBA, /* table format */
415 GL_UNSIGNED_BYTE, /* table type */
416 table); /* the color table */
418 glTexImage2D(GL_TEXTURE_2D, /* target */
419 0, /* level */
420 GL_COLOR_INDEX8_EXT, /* internal format */
421 src_d->dwWidth, src_d->dwHeight, /* width, height */
422 0, /* border */
423 GL_COLOR_INDEX, /* texture format */
424 GL_UNSIGNED_BYTE, /* texture type */
425 src_d->y.lpSurface); /* the texture */
426 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
427 /* ************
428 RGB Textures
429 ************ */
430 if (src_d->ddpfPixelFormat.x.dwRGBBitCount == 8) {
431 /* **********************
432 GL_UNSIGNED_BYTE_3_3_2
433 ********************** */
434 glTexImage2D(GL_TEXTURE_2D,
436 GL_RGB,
437 src_d->dwWidth, src_d->dwHeight,
439 GL_RGB,
440 GL_UNSIGNED_BYTE_3_3_2,
441 src_d->y.lpSurface);
442 } else if (src_d->ddpfPixelFormat.x.dwRGBBitCount == 16) {
443 if (src_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000000) {
445 /* Texture snooping */
446 SNOOP_5650();
448 glTexImage2D(GL_TEXTURE_2D,
450 GL_RGB,
451 src_d->dwWidth, src_d->dwHeight,
453 GL_RGB,
454 GL_UNSIGNED_SHORT_5_6_5,
455 src_d->y.lpSurface);
456 } else if (src_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x00000001) {
457 /* Texture snooping */
458 SNOOP_5551();
460 glTexImage2D(GL_TEXTURE_2D,
462 GL_RGBA,
463 src_d->dwWidth, src_d->dwHeight,
465 GL_RGBA,
466 GL_UNSIGNED_SHORT_5_5_5_1,
467 src_d->y.lpSurface);
468 } else if (src_d->ddpfPixelFormat.xy.dwRGBAlphaBitMask == 0x0000000F) {
469 glTexImage2D(GL_TEXTURE_2D,
471 GL_RGBA,
472 src_d->dwWidth, src_d->dwHeight,
474 GL_RGBA,
475 GL_UNSIGNED_SHORT_4_4_4_4,
476 src_d->y.lpSurface);
477 } else {
478 ERR(ddraw, "Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
480 } else if (src_d->ddpfPixelFormat.x.dwRGBBitCount == 24) {
481 glTexImage2D(GL_TEXTURE_2D,
483 GL_RGB,
484 src_d->dwWidth, src_d->dwHeight,
486 GL_RGB,
487 GL_UNSIGNED_BYTE,
488 src_d->y.lpSurface);
489 } else if (src_d->ddpfPixelFormat.x.dwRGBBitCount == 32) {
490 glTexImage2D(GL_TEXTURE_2D,
492 GL_RGBA,
493 src_d->dwWidth, src_d->dwHeight,
495 GL_RGBA,
496 GL_UNSIGNED_BYTE,
497 src_d->y.lpSurface);
498 } else {
499 ERR(ddraw, "Unhandled texture format (bad RGB count)\n");
501 } else {
502 ERR(ddraw, "Unhandled texture format (neither RGB nor INDEX)\n");
505 glBindTexture(GL_TEXTURE_2D, current_texture);
508 return D3D_OK;
512 /*******************************************************************************
513 * IDirect3DTexture2 VTable
515 static ICOM_VTABLE(IDirect3DTexture2) texture2_vtable = {
516 /*** IUnknown methods ***/
517 IDirect3DTexture2Impl_QueryInterface,
518 IDirect3DTexture2Impl_AddRef,
519 IDirect3DTexture2Impl_Release,
520 /*** IDirect3DTexture methods ***/
521 IDirect3DTexture2Impl_GetHandle,
522 IDirect3DTexture2Impl_PaletteChanged,
523 IDirect3DTexture2Impl_Load
526 /*******************************************************************************
527 * IDirect3DTexture VTable
529 static ICOM_VTABLE(IDirect3DTexture) texture_vtable = {
530 /*** IUnknown methods ***/
531 IDirect3DTexture2Impl_QueryInterface,
532 IDirect3DTexture2Impl_AddRef,
533 IDirect3DTexture2Impl_Release,
534 /*** IDirect3DTexture methods ***/
535 IDirect3DTextureImpl_Initialize,
536 IDirect3DTextureImpl_GetHandle,
537 IDirect3DTexture2Impl_PaletteChanged,
538 IDirect3DTexture2Impl_Load,
539 IDirect3DTextureImpl_Unload
542 #else /* HAVE_MESAGL */
544 /* These function should never be called if MesaGL is not present */
545 LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf) {
546 ERR(ddraw, "Should not be called...\n");
547 return NULL;
550 LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf) {
551 ERR(ddraw, "Should not be called...\n");
552 return NULL;
555 #endif /* HAVE_MESAGL */