2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the implementation of interface Direct3DTexture2.
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.
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.
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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 #include "mesa_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
38 /* Define this if you want to save to a file all the textures used by a game
39 (can be funny to see how they managed to cram all the pictures in
47 snoop_texture(IDirectDrawSurfaceImpl
*This
) {
48 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
52 sprintf(buf
, "tex_%05d.pnm", glThis
->tex_name
);
54 DDRAW_dump_surface_to_disk(This
, f
);
59 #define snoop_texture(a)
63 /*******************************************************************************
64 * IDirectSurface callback methods
67 gltex_upload_texture(IDirectDrawSurfaceImpl
*This
) {
68 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
70 static BOOL color_table_queried
= FALSE
;
72 void (*ptr_ColorTableEXT
) (GLenum target
, GLenum internalformat
,
73 GLsizei width
, GLenum format
, GLenum type
, const GLvoid
*table
) = NULL
;
74 BOOL upload_done
= FALSE
;
76 GLenum format
= GL_RGBA
, pixel_format
= GL_UNSIGNED_BYTE
; /* This is only to prevent warnings.. */
79 DDSURFACEDESC
*src_d
= (DDSURFACEDESC
*)&(This
->surface_desc
);
81 glBindTexture(GL_TEXTURE_2D
, glThis
->tex_name
);
83 if (glThis
->dirty_flag
== FALSE
) {
84 TRACE(" activating OpenGL texture id %d.\n", glThis
->tex_name
);
87 TRACE(" activating and uploading texture id %d (initial done = %d).\n", glThis
->tex_name
, glThis
->initial_upload_done
);
90 /* Texture snooping for the curious :-) */
93 if (src_d
->ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
97 IDirectDrawPaletteImpl
* pal
= This
->palette
;
102 if (color_table_queried
== FALSE
) {
104 ((Mesa_DeviceCapabilities
*) ((x11_dd_private
*) This
->surface
->s
.ddraw
->d
->private)->device_capabilities
)->ptr_ColorTableEXT
;
109 /* Upload a black texture. The real one will be uploaded on palette change */
110 WARN("Palettized texture Loading with a NULL palette !\n");
111 memset(table
, 0, 256 * 4);
113 /* Get the surface's palette */
114 for (i
= 0; i
< 256; i
++) {
115 table
[i
][0] = pal
->palents
[i
].peRed
;
116 table
[i
][1] = pal
->palents
[i
].peGreen
;
117 table
[i
][2] = pal
->palents
[i
].peBlue
;
118 if ((src_d
->dwFlags
& DDSD_CKSRCBLT
) &&
119 (i
>= src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) &&
120 (i
<= src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
121 /* We should maybe here put a more 'neutral' color than the standard bright purple
122 one often used by application to prevent the nice purple borders when bi-linear
130 if (ptr_ColorTableEXT
!= NULL
) {
131 /* use Paletted Texture Extension */
132 ptr_ColorTableEXT(GL_TEXTURE_2D
, /* target */
133 GL_RGBA
, /* internal format */
134 256, /* table size */
135 GL_RGBA
, /* table format */
136 GL_UNSIGNED_BYTE
, /* table type */
137 table
); /* the color table */
139 glTexImage2D(GL_TEXTURE_2D
, /* target */
140 This
->mipmap_level
, /* level */
141 GL_COLOR_INDEX8_EXT
, /* internal format */
142 src_d
->dwWidth
, src_d
->dwHeight
, /* width, height */
144 GL_COLOR_INDEX
, /* texture format */
145 GL_UNSIGNED_BYTE
, /* texture type */
146 src_d
->lpSurface
); /* the texture */
151 BYTE
*src
= (BYTE
*) src_d
->lpSurface
, *dst
;
153 surface
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(DWORD
));
154 dst
= (BYTE
*) surface
;
156 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
158 *dst
++ = table
[color
][0];
159 *dst
++ = table
[color
][1];
160 *dst
++ = table
[color
][2];
161 *dst
++ = table
[color
][3];
165 pixel_format
= GL_UNSIGNED_BYTE
;
167 } else if (src_d
->ddpfPixelFormat
.dwFlags
& DDPF_RGB
) {
171 if (src_d
->ddpfPixelFormat
.u1
.dwRGBBitCount
== 8) {
172 if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0xE0) &&
173 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x1C) &&
174 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x03)) {
175 /* **********************
176 GL_UNSIGNED_BYTE_3_3_2
177 ********************** */
178 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
179 /* This texture format will never be used.. So do not care about color keying
180 up until the point in time it will be needed :-) */
184 pixel_format
= GL_UNSIGNED_BYTE_3_3_2
;
189 } else if (src_d
->ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) {
190 if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
191 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
192 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F) &&
193 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x0000)) {
194 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
195 /* Converting the 565 format in 5551 packed to emulate color-keying.
197 Note : in all these conversion, it would be best to average the averaging
198 pixels to get the color of the pixel that will be color-keyed to
199 prevent 'color bleeding'. This will be done later on if ever it is
202 Note2: when using color-keying + alpha, are the alpha bits part of the
206 WORD
*src
= (WORD
*) src_d
->lpSurface
, *dst
;
208 surface
= (WORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(WORD
));
209 dst
= (WORD
*) surface
;
210 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
212 *dst
= ((color
& 0xFFC0) | ((color
& 0x1F) << 1));
213 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
214 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
220 pixel_format
= GL_UNSIGNED_SHORT_5_5_5_1
;
223 pixel_format
= GL_UNSIGNED_SHORT_5_6_5
;
225 } else if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
226 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x07C0) &&
227 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x003E) &&
228 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x0001)) {
230 pixel_format
= GL_UNSIGNED_SHORT_5_5_5_1
;
231 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
232 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
234 WORD
*src
= (WORD
*) src_d
->lpSurface
, *dst
;
236 surface
= (WORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(WORD
));
237 dst
= (WORD
*) surface
;
238 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
240 *dst
= color
& 0xFFFE;
241 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
242 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
243 *dst
|= color
& 0x0001;
247 } else if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0xF000) &&
248 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x0F00) &&
249 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x00F0) &&
250 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x000F)) {
252 pixel_format
= GL_UNSIGNED_SHORT_4_4_4_4
;
253 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
254 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
256 WORD
*src
= (WORD
*) src_d
->lpSurface
, *dst
;
258 surface
= (WORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(WORD
));
259 dst
= (WORD
*) surface
;
260 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
262 *dst
= color
& 0xFFF0;
263 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
264 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
265 *dst
|= color
& 0x000F;
269 } else if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0x0F00) &&
270 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x00F0) &&
271 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x000F) &&
272 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0xF000)) {
273 /* Move the four Alpha bits... */
275 WORD
*src
= (WORD
*) src_d
->lpSurface
, *dst
;
277 surface
= (WORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(WORD
));
280 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
281 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
283 *dst
= (color
& 0x0FFF) << 4;
284 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
285 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
286 *dst
|= (color
& 0xF000) >> 12;
290 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
292 *dst
++ = (((color
& 0x0FFF) << 4) |
293 ((color
& 0xF000) >> 12));
298 pixel_format
= GL_UNSIGNED_SHORT_4_4_4_4
;
299 } else if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0x7C00) &&
300 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x03E0) &&
301 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F) &&
302 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x8000)) {
303 /* Converting the 1555 format in 5551 packed */
305 WORD
*src
= (WORD
*) src_d
->lpSurface
, *dst
;
307 surface
= (WORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(WORD
));
308 dst
= (WORD
*) surface
;
310 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
311 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
313 *dst
= (color
& 0x7FFF) << 1;
314 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
315 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
316 *dst
|= (color
& 0x8000) >> 15;
320 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
322 *dst
++ = (((color
& 0x7FFF) << 1) |
323 ((color
& 0x8000) >> 15));
328 pixel_format
= GL_UNSIGNED_SHORT_5_5_5_1
;
332 } else if (src_d
->ddpfPixelFormat
.u1
.dwRGBBitCount
== 24) {
333 if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
334 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
335 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF) &&
336 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000)) {
337 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
338 /* This is a pain :-) */
340 BYTE
*src
= (BYTE
*) src_d
->lpSurface
;
343 surface
= (DWORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(DWORD
));
344 dst
= (DWORD
*) surface
;
345 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
346 DWORD color
= *((DWORD
*) src
) & 0x00FFFFFF;
349 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
350 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
355 pixel_format
= GL_UNSIGNED_INT_8_8_8_8
;
358 pixel_format
= GL_UNSIGNED_BYTE
;
363 } else if (src_d
->ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) {
364 if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0xFF000000) &&
365 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x00FF0000) &&
366 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x0000FF00) &&
367 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x000000FF)) {
368 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
369 /* Just use the alpha component to handle color-keying... */
371 DWORD
*src
= (DWORD
*) src_d
->lpSurface
, *dst
;
373 surface
= (DWORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(DWORD
));
374 dst
= (DWORD
*) surface
;
375 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
376 DWORD color
= *src
++;
377 *dst
= color
& 0xFFFFFF00;
378 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
379 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
380 *dst
|= color
& 0x000000FF;
385 pixel_format
= GL_UNSIGNED_INT_8_8_8_8
;
386 } else if ((src_d
->ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
387 (src_d
->ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
388 (src_d
->ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF) &&
389 (src_d
->ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000)) {
390 /* Just add an alpha component and handle color-keying... */
392 DWORD
*src
= (DWORD
*) src_d
->lpSurface
, *dst
;
394 surface
= (DWORD
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, src_d
->dwWidth
* src_d
->dwHeight
* sizeof(DWORD
));
395 dst
= (DWORD
*) surface
;
397 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
398 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
399 DWORD color
= *src
++;
401 if ((color
< src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
) ||
402 (color
> src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
))
407 for (i
= 0; i
< src_d
->dwHeight
* src_d
->dwWidth
; i
++) {
408 *dst
++ = (*src
++ << 8) | 0xFF;
412 pixel_format
= GL_UNSIGNED_INT_8_8_8_8
;
423 if ((upload_done
== FALSE
) && (error
== FALSE
)) {
424 if (glThis
->initial_upload_done
== FALSE
) {
425 glTexImage2D(GL_TEXTURE_2D
,
428 src_d
->dwWidth
, src_d
->dwHeight
,
432 surface
== NULL
? src_d
->lpSurface
: surface
);
433 glThis
->initial_upload_done
= TRUE
;
435 glTexSubImage2D(GL_TEXTURE_2D
,
438 src_d
->dwWidth
, src_d
->dwHeight
,
441 surface
== NULL
? src_d
->lpSurface
: surface
);
444 if (surface
) HeapFree(GetProcessHeap(), 0, surface
);
445 } else if (error
== TRUE
) {
447 ERR("Unsupported pixel format for textures : \n");
448 DDRAW_dump_pixelformat(&src_d
->ddpfPixelFormat
);
452 glThis
->dirty_flag
= FALSE
;
458 Main_IDirect3DTextureImpl_1_Initialize(LPDIRECT3DTEXTURE iface
,
459 LPDIRECT3DDEVICE lpDirect3DDevice
,
460 LPDIRECTDRAWSURFACE lpDDSurface
)
462 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture
, iface
);
463 FIXME("(%p/%p)->(%p,%p) no-op...\n", This
, iface
, lpDirect3DDevice
, lpDDSurface
);
468 gltex_setcolorkey_cb(IDirectDrawSurfaceImpl
*This
, DWORD dwFlags
, LPDDCOLORKEY ckey
)
470 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
472 glThis
->dirty_flag
= TRUE
;
478 Main_IDirect3DTextureImpl_2_1T_PaletteChanged(LPDIRECT3DTEXTURE2 iface
,
482 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, iface
);
483 FIXME("(%p/%p)->(%08lx,%08lx): stub!\n", This
, iface
, dwStart
, dwCount
);
488 Main_IDirect3DTextureImpl_1_Unload(LPDIRECT3DTEXTURE iface
)
490 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture
, iface
);
491 FIXME("(%p/%p)->(): stub!\n", This
, iface
);
496 Main_IDirect3DTextureImpl_2_1T_GetHandle(LPDIRECT3DTEXTURE2 iface
,
497 LPDIRECT3DDEVICE2 lpDirect3DDevice2
,
498 LPD3DTEXTUREHANDLE lpHandle
)
500 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, iface
);
501 IDirect3DDeviceImpl
*lpDeviceImpl
= ICOM_OBJECT(IDirect3DDeviceImpl
, IDirect3DDevice2
, lpDirect3DDevice2
);
503 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpDirect3DDevice2
, lpHandle
);
505 /* The handle is simply the pointer to the implementation structure */
506 *lpHandle
= (D3DTEXTUREHANDLE
) This
;
508 TRACE(" returning handle %08lx.\n", *lpHandle
);
510 /* Now set the device for this texture */
511 This
->d3ddevice
= lpDeviceImpl
;
517 Main_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface
,
518 LPDIRECT3DTEXTURE2 lpD3DTexture2
)
520 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, iface
);
521 FIXME("(%p/%p)->(%p): stub!\n", This
, iface
, lpD3DTexture2
);
525 static void gltex_set_palette(IDirectDrawSurfaceImpl
* This
, IDirectDrawPaletteImpl
* pal
)
527 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
529 /* First call the previous set_palette function */
530 glThis
->set_palette(This
, pal
);
532 /* And set the dirty flag */
533 glThis
->dirty_flag
= TRUE
;
537 gltex_final_release(IDirectDrawSurfaceImpl
*This
)
539 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
543 TRACE(" deleting texture with GL id %d.\n", glThis
->tex_name
);
545 /* And delete texture handle */
547 if (glThis
->tex_name
!= 0)
548 glDeleteTextures(1, &(glThis
->tex_name
));
551 /* And if this texture was the current one, remove it at the device level */
552 if (This
->d3ddevice
!= NULL
)
553 for (i
= 0; i
< MAX_TEXTURES
; i
++)
554 if (This
->d3ddevice
->current_texture
[i
] == This
)
555 This
->d3ddevice
->current_texture
[i
] = NULL
;
557 /* All this should be part of main surface management not just a hack for texture.. */
558 if (glThis
->loaded
) {
559 mem_used
= This
->surface_desc
.dwHeight
*
560 This
->surface_desc
.u1
.lPitch
;
561 This
->ddraw_owner
->free_memory(This
->ddraw_owner
, mem_used
);
564 glThis
->final_release(This
);
568 gltex_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
570 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
572 glThis
->lock_update(This
, pRect
, dwFlags
);
576 gltex_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
578 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
580 glThis
->unlock_update(This
, pRect
);
582 /* Set the dirty flag according to the lock type */
583 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0)
584 glThis
->dirty_flag
= TRUE
;
588 GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface
,
589 LPDIRECT3DTEXTURE2 lpD3DTexture2
)
591 ICOM_THIS_FROM(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, iface
);
592 IDirect3DTextureGLImpl
*glThis
= (IDirect3DTextureGLImpl
*) This
->tex_private
;
593 IDirectDrawSurfaceImpl
*lpD3DTextureImpl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, lpD3DTexture2
);
595 DDSURFACEDESC
*src_d
, *dst_d
;
596 HRESULT ret_value
= D3D_OK
;
598 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpD3DTexture2
);
600 if (glThis
!= NULL
) {
601 if (glThis
->loaded
== FALSE
) {
602 /* Only check memory for not already loaded texture... */
603 mem_used
= This
->surface_desc
.dwHeight
*
604 This
->surface_desc
.u1
.lPitch
;
605 if (This
->ddraw_owner
->allocate_memory(This
->ddraw_owner
, mem_used
) < 0) {
606 TRACE(" out of virtual memory... Warning application.\n");
607 return D3DERR_TEXTURE_LOAD_FAILED
;
610 glThis
->loaded
= TRUE
;
613 TRACE("Copied surface %p to surface %p\n", lpD3DTextureImpl
, This
);
615 if ( This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_ALLOCONLOAD
)
616 /* If the surface is not allocated and its location is not yet specified,
617 force it to video memory */
618 if ( !(This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_SYSTEMMEMORY
|DDSCAPS_VIDEOMEMORY
)) )
619 This
->surface_desc
.ddsCaps
.dwCaps
|= DDSCAPS_VIDEOMEMORY
;
621 /* Suppress the ALLOCONLOAD flag */
622 This
->surface_desc
.ddsCaps
.dwCaps
&= ~DDSCAPS_ALLOCONLOAD
;
624 /* After seeing some logs, not sure at all about this... */
625 if (This
->palette
== NULL
) {
626 This
->palette
= lpD3DTextureImpl
->palette
;
627 if (lpD3DTextureImpl
->palette
!= NULL
) IDirectDrawPalette_AddRef(ICOM_INTERFACE(lpD3DTextureImpl
->palette
,
628 IDirectDrawPalette
));
630 if (lpD3DTextureImpl
->palette
!= NULL
) {
631 PALETTEENTRY palent
[256];
632 IDirectDrawPalette
*pal_int
= ICOM_INTERFACE(lpD3DTextureImpl
->palette
, IDirectDrawPalette
);
633 IDirectDrawPalette_GetEntries(pal_int
, 0, 0, 256, palent
);
634 IDirectDrawPalette_SetEntries(ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
),
639 /* Copy one surface on the other */
640 dst_d
= (DDSURFACEDESC
*)&(This
->surface_desc
);
641 src_d
= (DDSURFACEDESC
*)&(lpD3DTextureImpl
->surface_desc
);
643 if ((src_d
->dwWidth
!= dst_d
->dwWidth
) || (src_d
->dwHeight
!= dst_d
->dwHeight
)) {
644 /* Should also check for same pixel format, u1.lPitch, ... */
645 ERR("Error in surface sizes\n");
646 return D3DERR_TEXTURE_LOAD_FAILED
;
648 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
649 /* I should put a macro for the calculus of bpp */
651 /* Copy also the ColorKeying stuff */
652 if (src_d
->dwFlags
& DDSD_CKSRCBLT
) {
653 dst_d
->dwFlags
|= DDSD_CKSRCBLT
;
654 dst_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
= src_d
->ddckCKSrcBlt
.dwColorSpaceLowValue
;
655 dst_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
= src_d
->ddckCKSrcBlt
.dwColorSpaceHighValue
;
658 /* Copy the main memory texture into the surface that corresponds to the OpenGL
660 memcpy(dst_d
->lpSurface
, src_d
->lpSurface
, src_d
->u1
.lPitch
* src_d
->dwHeight
);
662 if (glThis
!= NULL
) {
663 /* If the GetHandle was not done, it is an error... */
664 if (glThis
->tex_name
== 0) ERR("Unbound GL texture !!!\n");
666 /* Set this texture as dirty */
667 glThis
->dirty_flag
= TRUE
;
675 Thunk_IDirect3DTextureImpl_2_QueryInterface(LPDIRECT3DTEXTURE2 iface
,
679 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface
, debugstr_guid(riid
), obp
);
680 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, IDirectDrawSurface7
, iface
),
686 Thunk_IDirect3DTextureImpl_2_AddRef(LPDIRECT3DTEXTURE2 iface
)
688 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface
);
689 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, IDirectDrawSurface7
, iface
));
693 Thunk_IDirect3DTextureImpl_2_Release(LPDIRECT3DTEXTURE2 iface
)
695 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface
);
696 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture2
, IDirectDrawSurface7
, iface
));
700 Thunk_IDirect3DTextureImpl_1_QueryInterface(LPDIRECT3DTEXTURE iface
,
704 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", iface
, debugstr_guid(riid
), obp
);
705 return IDirectDrawSurface7_QueryInterface(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirectDrawSurface7
, iface
),
711 Thunk_IDirect3DTextureImpl_1_AddRef(LPDIRECT3DTEXTURE iface
)
713 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface
);
714 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirectDrawSurface7
, iface
));
718 Thunk_IDirect3DTextureImpl_1_Release(LPDIRECT3DTEXTURE iface
)
720 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", iface
);
721 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirectDrawSurface7
, iface
));
725 Thunk_IDirect3DTextureImpl_1_PaletteChanged(LPDIRECT3DTEXTURE iface
,
729 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", iface
, dwStart
, dwCount
);
730 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirect3DTexture2
, iface
),
736 Thunk_IDirect3DTextureImpl_1_GetHandle(LPDIRECT3DTEXTURE iface
,
737 LPDIRECT3DDEVICE lpDirect3DDevice
,
738 LPD3DTEXTUREHANDLE lpHandle
)
740 TRACE("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", iface
, lpDirect3DDevice
, lpHandle
);
741 return IDirect3DTexture2_GetHandle(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirect3DTexture2
, iface
),
742 COM_INTERFACE_CAST(IDirect3DDeviceImpl
, IDirect3DDevice
, IDirect3DDevice2
, lpDirect3DDevice
),
747 Thunk_IDirect3DTextureImpl_1_Load(LPDIRECT3DTEXTURE iface
,
748 LPDIRECT3DTEXTURE lpD3DTexture
)
750 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", iface
, lpD3DTexture
);
751 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirect3DTexture2
, iface
),
752 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl
, IDirect3DTexture
, IDirect3DTexture2
, lpD3DTexture
));
755 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
756 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture2.fun))
758 # define XCAST(fun) (void*)
761 ICOM_VTABLE(IDirect3DTexture2
) VTABLE_IDirect3DTexture2
=
763 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
764 XCAST(QueryInterface
) Thunk_IDirect3DTextureImpl_2_QueryInterface
,
765 XCAST(AddRef
) Thunk_IDirect3DTextureImpl_2_AddRef
,
766 XCAST(Release
) Thunk_IDirect3DTextureImpl_2_Release
,
767 XCAST(GetHandle
) Main_IDirect3DTextureImpl_2_1T_GetHandle
,
768 XCAST(PaletteChanged
) Main_IDirect3DTextureImpl_2_1T_PaletteChanged
,
769 XCAST(Load
) GL_IDirect3DTextureImpl_2_1T_Load
,
772 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
777 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
778 # define XCAST(fun) (typeof(VTABLE_IDirect3DTexture.fun))
780 # define XCAST(fun) (void*)
783 ICOM_VTABLE(IDirect3DTexture
) VTABLE_IDirect3DTexture
=
785 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
786 XCAST(QueryInterface
) Thunk_IDirect3DTextureImpl_1_QueryInterface
,
787 XCAST(AddRef
) Thunk_IDirect3DTextureImpl_1_AddRef
,
788 XCAST(Release
) Thunk_IDirect3DTextureImpl_1_Release
,
789 XCAST(Initialize
) Main_IDirect3DTextureImpl_1_Initialize
,
790 XCAST(GetHandle
) Thunk_IDirect3DTextureImpl_1_GetHandle
,
791 XCAST(PaletteChanged
) Thunk_IDirect3DTextureImpl_1_PaletteChanged
,
792 XCAST(Load
) Thunk_IDirect3DTextureImpl_1_Load
,
793 XCAST(Unload
) Main_IDirect3DTextureImpl_1_Unload
,
796 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
800 HRESULT
d3dtexture_create(IDirect3DImpl
*d3d
, IDirectDrawSurfaceImpl
*surf
, BOOLEAN at_creation
,
801 IDirectDrawSurfaceImpl
*main
)
803 /* First, initialize the texture vtables... */
804 ICOM_INIT_INTERFACE(surf
, IDirect3DTexture
, VTABLE_IDirect3DTexture
);
805 ICOM_INIT_INTERFACE(surf
, IDirect3DTexture2
, VTABLE_IDirect3DTexture2
);
807 /* Only create all the private stuff if we actually have an OpenGL context.. */
808 if (d3d
->current_device
!= NULL
) {
809 IDirect3DTextureGLImpl
*private;
811 private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DTextureGLImpl
));
812 if (private == NULL
) return DDERR_OUTOFMEMORY
;
814 private->final_release
= surf
->final_release
;
815 private->lock_update
= surf
->lock_update
;
816 private->unlock_update
= surf
->unlock_update
;
817 private->set_palette
= surf
->set_palette
;
819 /* If at creation, we can optimize stuff and wait the first 'unlock' to upload a valid stuff to OpenGL.
820 Otherwise, it will be uploaded here (and may be invalid). */
821 surf
->final_release
= gltex_final_release
;
822 surf
->lock_update
= gltex_lock_update
;
823 surf
->unlock_update
= gltex_unlock_update
;
824 surf
->tex_private
= private;
825 surf
->aux_setcolorkey_cb
= gltex_setcolorkey_cb
;
826 surf
->set_palette
= gltex_set_palette
;
829 if (surf
->mipmap_level
== 0) {
830 glGenTextures(1, &(private->tex_name
));
831 if (private->tex_name
== 0) ERR("Error at creation of OpenGL texture ID !\n");
832 TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf
, private, private->tex_name
);
834 private->tex_name
= ((IDirect3DTextureGLImpl
*) (main
->tex_private
))->tex_name
;
835 TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
836 surf
, private, private->tex_name
, main
, main
->tex_private
);
840 /* And set the dirty flag accordingly */
841 private->dirty_flag
= (at_creation
== FALSE
);
842 private->initial_upload_done
= FALSE
;