Avoid calls to SetFocus when they are unnecessary.
[wine/testsucceed.git] / dlls / ddraw / d3dtexture.c
blobb05570c045bf16634ec80abf5b808e02fe67698b
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 "debugtools.h"
17 #include "mesa_private.h"
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
22 DEFAULT_DEBUG_CHANNEL(ddraw)
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
29 #ifdef TEXTURE_SNOOP
30 #include <stdio.h>
32 #define SNOOP_PALETTED() \
33 { \
34 FILE *f; \
35 char buf[32]; \
36 int x, y; \
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); \
52 #define SNOOP_5650() \
53 { \
54 FILE *f; \
55 char buf[32]; \
56 int x, y; \
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); \
72 #define SNOOP_5551() \
73 { \
74 FILE *f; \
75 char buf[32]; \
76 int x, y; \
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); \
91 #else
92 #define SNOOP_PALETTED()
93 #define SNOOP_5650()
94 #define SNOOP_5551()
95 #endif
97 static ICOM_VTABLE(IDirect3DTexture2) texture2_vtable;
98 static ICOM_VTABLE(IDirect3DTexture) texture_vtable;
100 /*******************************************************************************
101 * Texture2 Creation functions
103 LPDIRECT3DTEXTURE2 d3dtexture2_create(IDirectDrawSurface4Impl* surf)
105 IDirect3DTexture2Impl* tex;
107 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
108 tex->ref = 1;
109 ICOM_VTBL(tex) = &texture2_vtable;
110 tex->surface = surf;
112 return (LPDIRECT3DTEXTURE2)tex;
115 /*******************************************************************************
116 * Texture Creation functions
118 LPDIRECT3DTEXTURE d3dtexture_create(IDirectDrawSurface4Impl* surf)
120 IDirect3DTexture2Impl* tex;
122 tex = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirect3DTexture2Impl));
123 tex->ref = 1;
124 ICOM_VTBL(tex) = (ICOM_VTABLE(IDirect3DTexture2)*)&texture_vtable;
125 tex->surface = surf;
127 return (LPDIRECT3DTEXTURE)tex;
130 /*******************************************************************************
131 * IDirectSurface callback methods
133 HRESULT WINAPI SetColorKey_cb(IDirect3DTexture2Impl *texture, DWORD dwFlags, LPDDCOLORKEY ckey )
135 DDSURFACEDESC *tex_d;
136 D3DTPRIVATE(texture);
137 int bpp;
138 GLuint current_texture;
140 TRACE("(%p) : colorkey callback\n", texture);
142 /* Get the texture description */
143 tex_d = &(texture->surface->s.surface_desc);
144 bpp = (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
145 1 /* 8 bit of palette index */:
146 tex_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
148 /* Now, save the current texture */
149 ENTER_GL();
150 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
152 /* If the GetHandle was not done yet, it's an error */
153 if (dtpriv->tex_name == 0) {
154 ERR("Unloaded texture !\n");
155 LEAVE_GL();
156 return DD_OK;
158 glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
160 if (tex_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
161 FIXME("Todo Paletted\n");
162 } else if (tex_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
163 if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
164 FIXME("Todo 3_3_2_0\n");
165 } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
166 if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
167 /* Now transform the 5_6_5 into a 5_5_5_1 surface to support color keying */
168 unsigned short *dest = (unsigned short *) HeapAlloc(GetProcessHeap(),
169 HEAP_ZERO_MEMORY,
170 tex_d->dwWidth * tex_d->dwHeight * bpp);
171 unsigned short *src = (unsigned short *) tex_d->u1.lpSurface;
172 int x, y;
174 for (y = 0; y < tex_d->dwHeight; y++) {
175 for (x = 0; x < tex_d->dwWidth; x++) {
176 unsigned short cpixel = src[x + y * tex_d->dwWidth];
178 if ((dwFlags & DDCKEY_SRCBLT) &&
179 (cpixel >= ckey->dwColorSpaceLowValue) &&
180 (cpixel <= ckey->dwColorSpaceHighValue)) /* No alpha bit => this pixel is transparent */
181 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0000;
182 else /* Alpha bit is set => this pixel will be seen */
183 dest[x + y * tex_d->dwWidth] = (cpixel & ~0x003F) | ((cpixel & 0x001F) << 1) | 0x0001;
187 glTexImage2D(GL_TEXTURE_2D,
189 GL_RGBA,
190 tex_d->dwWidth, tex_d->dwHeight,
192 GL_RGBA,
193 GL_UNSIGNED_SHORT_5_5_5_1,
194 dest);
196 /* Frees the temporary surface */
197 HeapFree(GetProcessHeap(),0,dest);
198 } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
199 FIXME("Todo 5_5_5_1\n");
200 } else if (tex_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
201 FIXME("Todo 4_4_4_4\n");
202 } else {
203 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
205 } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
206 FIXME("Todo 8_8_8_0\n");
207 } else if (tex_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
208 FIXME("Todo 8_8_8_8\n");
209 } else {
210 ERR("Unhandled texture format (bad RGB count)\n");
212 } else {
213 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
215 LEAVE_GL();
217 return DD_OK;
220 /*******************************************************************************
221 * IDirect3DTexture2 methods
224 HRESULT WINAPI IDirect3DTexture2Impl_QueryInterface(LPDIRECT3DTEXTURE2 iface,
225 REFIID riid,
226 LPVOID* ppvObj)
228 ICOM_THIS(IDirect3DTexture2Impl,iface);
230 FIXME("(%p)->(%s,%p): stub\n", This, debugstr_guid(riid),ppvObj);
232 return S_OK;
237 ULONG WINAPI IDirect3DTexture2Impl_AddRef(LPDIRECT3DTEXTURE2 iface)
239 ICOM_THIS(IDirect3DTexture2Impl,iface);
240 TRACE("(%p)->()incrementing from %lu.\n", This, This->ref );
242 return ++(This->ref);
247 ULONG WINAPI IDirect3DTexture2Impl_Release(LPDIRECT3DTEXTURE2 iface)
249 ICOM_THIS(IDirect3DTexture2Impl,iface);
250 D3DTPRIVATE(This);
251 FIXME("(%p)->() decrementing from %lu.\n", This, This->ref );
253 if (!--(This->ref)) {
254 /* Delete texture from OpenGL */
255 ENTER_GL();
256 glDeleteTextures(1, &(dtpriv->tex_name));
257 LEAVE_GL();
259 /* Release surface */
260 IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->surface);
262 HeapFree(GetProcessHeap(),0,This);
263 return 0;
266 return This->ref;
269 /*** IDirect3DTexture methods ***/
270 HRESULT WINAPI IDirect3DTextureImpl_GetHandle(LPDIRECT3DTEXTURE iface,
271 LPDIRECT3DDEVICE lpD3DDevice,
272 LPD3DTEXTUREHANDLE lpHandle)
274 ICOM_THIS(IDirect3DTexture2Impl,iface);
275 D3DTPRIVATE(This);
276 IDirect3DDeviceImpl* ilpD3DDevice=(IDirect3DDeviceImpl*)lpD3DDevice;
277 FIXME("(%p)->(%p,%p): stub\n", This, ilpD3DDevice, lpHandle);
279 *lpHandle = (D3DTEXTUREHANDLE) This;
281 /* Now, bind a new texture */
282 ENTER_GL();
283 ilpD3DDevice->set_context(ilpD3DDevice);
284 This->D3Ddevice = (void *) ilpD3DDevice;
285 if (dtpriv->tex_name == 0)
286 glGenTextures(1, &(dtpriv->tex_name));
287 LEAVE_GL();
289 TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
291 return D3D_OK;
294 HRESULT WINAPI IDirect3DTextureImpl_Initialize(LPDIRECT3DTEXTURE iface,
295 LPDIRECT3DDEVICE lpD3DDevice,
296 LPDIRECTDRAWSURFACE lpSurface)
298 ICOM_THIS(IDirect3DTexture2Impl,iface);
299 TRACE("(%p)->(%p,%p)\n", This, lpD3DDevice, lpSurface);
301 return DDERR_ALREADYINITIALIZED;
304 HRESULT WINAPI IDirect3DTextureImpl_Unload(LPDIRECT3DTEXTURE iface)
306 ICOM_THIS(IDirect3DTexture2Impl,iface);
307 FIXME("(%p)->(): stub\n", This);
309 return D3D_OK;
312 /*** IDirect3DTexture2 methods ***/
313 HRESULT WINAPI IDirect3DTexture2Impl_GetHandle(LPDIRECT3DTEXTURE2 iface,
314 LPDIRECT3DDEVICE2 lpD3DDevice2,
315 LPD3DTEXTUREHANDLE lpHandle)
317 ICOM_THIS(IDirect3DTexture2Impl,iface);
318 D3DTPRIVATE(This);
319 IDirect3DDevice2Impl* ilpD3DDevice2=(IDirect3DDevice2Impl*)lpD3DDevice2;
320 TRACE("(%p)->(%p,%p)\n", This, ilpD3DDevice2, lpHandle);
322 /* For 32 bits OSes, handles = pointers */
323 *lpHandle = (D3DTEXTUREHANDLE) This;
325 /* Now, bind a new texture */
326 ENTER_GL();
327 ilpD3DDevice2->set_context(ilpD3DDevice2);
328 This->D3Ddevice = (void *) ilpD3DDevice2;
329 if (dtpriv->tex_name == 0)
330 glGenTextures(1, &(dtpriv->tex_name));
331 LEAVE_GL();
333 TRACE("OpenGL texture handle is : %d\n", dtpriv->tex_name);
335 return D3D_OK;
338 /* Common methods */
339 HRESULT WINAPI IDirect3DTexture2Impl_PaletteChanged(
340 LPDIRECT3DTEXTURE2 iface, DWORD dwStart, DWORD dwCount
342 ICOM_THIS(IDirect3DTexture2Impl,iface);
343 FIXME("(%p)->(%8ld,%8ld): stub\n", This, dwStart, dwCount);
345 return D3D_OK;
348 /* NOTE : if you experience crashes in this function, you must have a buggy
349 version of Mesa. See the file d3dtexture.c for a cure */
350 HRESULT WINAPI IDirect3DTexture2Impl_Load(
351 LPDIRECT3DTEXTURE2 iface, LPDIRECT3DTEXTURE2 lpD3DTexture2
353 ICOM_THIS(IDirect3DTexture2Impl,iface);
354 D3DTPRIVATE(This);
355 IDirect3DTexture2Impl* ilpD3DTexture2=(IDirect3DTexture2Impl*)lpD3DTexture2;
356 DDSURFACEDESC *src_d, *dst_d;
357 TRACE("(%p)->(%p)\n", This, ilpD3DTexture2);
359 TRACE("Copied surface %p to surface %p\n", ilpD3DTexture2->surface, This->surface);
361 /* Suppress the ALLOCONLOAD flag */
362 This->surface->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
364 /* Copy one surface on the other */
365 dst_d = &(This->surface->s.surface_desc);
366 src_d = &(ilpD3DTexture2->surface->s.surface_desc);
368 /* Install the callbacks to the destination surface */
369 This->surface->s.texture = This;
370 This->surface->s.SetColorKey_cb = SetColorKey_cb;
372 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight)) {
373 /* Should also check for same pixel format, lPitch, ... */
374 ERR("Error in surface sizes\n");
375 return D3DERR_TEXTURE_LOAD_FAILED;
376 } else {
377 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
378 /* I should put a macro for the calculus of bpp */
379 int bpp = (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ?
380 1 /* 8 bit of palette index */:
381 src_d->ddpfPixelFormat.u.dwRGBBitCount / 8 /* RGB bits for each colors */ );
382 GLuint current_texture;
384 /* Copy the main memry texture into the surface that corresponds to the OpenGL
385 texture object. */
386 memcpy(dst_d->u1.lpSurface, src_d->u1.lpSurface, src_d->dwWidth * src_d->dwHeight * bpp);
388 ENTER_GL();
390 /* Now, load the texture */
391 /* d3dd->set_context(d3dd); We need to set the context somehow.... */
392 glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
394 /* If the GetHandle was not done, get the texture name here */
395 if (dtpriv->tex_name == 0)
396 glGenTextures(1, &(dtpriv->tex_name));
397 glBindTexture(GL_TEXTURE_2D, dtpriv->tex_name);
399 if (src_d->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
400 /* ****************
401 Paletted Texture
402 **************** */
403 IDirectDrawPaletteImpl* pal = This->surface->s.palette;
404 BYTE table[256][4];
405 int i;
407 if (pal == NULL) {
408 ERR("Palettized texture Loading with a NULL palette !\n");
409 LEAVE_GL();
410 return D3DERR_TEXTURE_LOAD_FAILED;
413 /* Get the surface's palette */
414 for (i = 0; i < 256; i++) {
415 table[i][0] = pal->palents[i].peRed;
416 table[i][1] = pal->palents[i].peGreen;
417 table[i][2] = pal->palents[i].peBlue;
418 if ((This->surface->s.surface_desc.dwFlags & DDSD_CKSRCBLT) &&
419 (i >= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) &&
420 (i <= This->surface->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
421 table[i][3] = 0x00;
422 else
423 table[i][3] = 0xFF;
426 /* Texture snooping */
427 SNOOP_PALETTED();
429 #if defined(HAVE_GL_COLOR_TABLE) && defined(HAVE_GL_PALETTED_TEXTURE)
430 /* use Paletted Texture Extension */
431 glColorTableEXT(GL_TEXTURE_2D, /* target */
432 GL_RGBA, /* internal format */
433 256, /* table size */
434 GL_RGBA, /* table format */
435 GL_UNSIGNED_BYTE, /* table type */
436 table); /* the color table */
438 glTexImage2D(GL_TEXTURE_2D, /* target */
439 0, /* level */
440 GL_COLOR_INDEX8_EXT, /* internal format */
441 src_d->dwWidth, src_d->dwHeight, /* width, height */
442 0, /* border */
443 GL_COLOR_INDEX, /* texture format */
444 GL_UNSIGNED_BYTE, /* texture type */
445 src_d->u1.lpSurface); /* the texture */
446 #endif
447 } else if (src_d->ddpfPixelFormat.dwFlags & DDPF_RGB) {
448 /* ************
449 RGB Textures
450 ************ */
451 if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 8) {
452 /* **********************
453 GL_UNSIGNED_BYTE_3_3_2
454 ********************** */
455 glTexImage2D(GL_TEXTURE_2D,
457 GL_RGB,
458 src_d->dwWidth, src_d->dwHeight,
460 GL_RGB,
461 GL_UNSIGNED_BYTE_3_3_2,
462 src_d->u1.lpSurface);
463 } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 16) {
464 if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000000) {
466 /* Texture snooping */
467 SNOOP_5650();
469 glTexImage2D(GL_TEXTURE_2D,
471 GL_RGB,
472 src_d->dwWidth, src_d->dwHeight,
474 GL_RGB,
475 GL_UNSIGNED_SHORT_5_6_5,
476 src_d->u1.lpSurface);
477 } else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x00000001) {
478 /* Texture snooping */
479 SNOOP_5551();
481 glTexImage2D(GL_TEXTURE_2D,
483 GL_RGBA,
484 src_d->dwWidth, src_d->dwHeight,
486 GL_RGBA,
487 GL_UNSIGNED_SHORT_5_5_5_1,
488 src_d->u1.lpSurface);
489 } else if (src_d->ddpfPixelFormat.u4.dwRGBAlphaBitMask == 0x0000000F) {
490 glTexImage2D(GL_TEXTURE_2D,
492 GL_RGBA,
493 src_d->dwWidth, src_d->dwHeight,
495 GL_RGBA,
496 GL_UNSIGNED_SHORT_4_4_4_4,
497 src_d->u1.lpSurface);
498 } else {
499 ERR("Unhandled texture format (bad Aplha channel for a 16 bit texture)\n");
501 } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 24) {
502 glTexImage2D(GL_TEXTURE_2D,
504 GL_RGB,
505 src_d->dwWidth, src_d->dwHeight,
507 GL_RGB,
508 GL_UNSIGNED_BYTE,
509 src_d->u1.lpSurface);
510 } else if (src_d->ddpfPixelFormat.u.dwRGBBitCount == 32) {
511 glTexImage2D(GL_TEXTURE_2D,
513 GL_RGBA,
514 src_d->dwWidth, src_d->dwHeight,
516 GL_RGBA,
517 GL_UNSIGNED_BYTE,
518 src_d->u1.lpSurface);
519 } else {
520 ERR("Unhandled texture format (bad RGB count)\n");
522 } else {
523 ERR("Unhandled texture format (neither RGB nor INDEX)\n");
526 glBindTexture(GL_TEXTURE_2D, current_texture);
528 LEAVE_GL();
531 return D3D_OK;
535 /*******************************************************************************
536 * IDirect3DTexture2 VTable
538 ICOM_VTABLE(IDirect3DTexture2) mesa_texture2_vtable =
540 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
541 /*** IUnknown methods ***/
542 IDirect3DTexture2Impl_QueryInterface,
543 IDirect3DTexture2Impl_AddRef,
544 IDirect3DTexture2Impl_Release,
545 /*** IDirect3DTexture methods ***/
546 IDirect3DTexture2Impl_GetHandle,
547 IDirect3DTexture2Impl_PaletteChanged,
548 IDirect3DTexture2Impl_Load
551 /*******************************************************************************
552 * IDirect3DTexture VTable
554 ICOM_VTABLE(IDirect3DTexture) mesa_texture_vtable =
556 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
557 /*** IUnknown methods ***/
558 IDirect3DTexture2Impl_QueryInterface,
559 IDirect3DTexture2Impl_AddRef,
560 IDirect3DTexture2Impl_Release,
561 /*** IDirect3DTexture methods ***/
562 IDirect3DTextureImpl_Initialize,
563 IDirect3DTextureImpl_GetHandle,
564 IDirect3DTexture2Impl_PaletteChanged,
565 IDirect3DTexture2Impl_Load,
566 IDirect3DTextureImpl_Unload