1 /* Direct3D Common functions
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains all MESA common code
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
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
29 #include "wine/debug.h"
31 #include "mesa_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
35 GLenum convert_D3D_compare_to_GL(D3DCMPFUNC dwRenderState)
37 switch (dwRenderState) {
38 case D3DCMP_NEVER: return GL_NEVER;
39 case D3DCMP_LESS: return GL_LESS;
40 case D3DCMP_EQUAL: return GL_EQUAL;
41 case D3DCMP_LESSEQUAL: return GL_LEQUAL;
42 case D3DCMP_GREATER: return GL_GREATER;
43 case D3DCMP_NOTEQUAL: return GL_NOTEQUAL;
44 case D3DCMP_GREATEREQUAL: return GL_GEQUAL;
45 case D3DCMP_ALWAYS: return GL_ALWAYS;
46 default: ERR("Unexpected compare type %d !\n", dwRenderState);
51 GLenum convert_D3D_stencilop_to_GL(D3DSTENCILOP dwRenderState)
53 switch (dwRenderState) {
54 case D3DSTENCILOP_KEEP: return GL_KEEP;
55 case D3DSTENCILOP_ZERO: return GL_ZERO;
56 case D3DSTENCILOP_REPLACE: return GL_REPLACE;
57 case D3DSTENCILOP_INCRSAT: return GL_INCR;
58 case D3DSTENCILOP_DECRSAT: return GL_DECR;
59 case D3DSTENCILOP_INVERT: return GL_INVERT;
60 case D3DSTENCILOP_INCR: WARN("D3DSTENCILOP_INCR not properly handled !\n"); return GL_INCR;
61 case D3DSTENCILOP_DECR: WARN("D3DSTENCILOP_DECR not properly handled !\n"); return GL_DECR;
62 default: ERR("Unexpected compare type %d !\n", dwRenderState);
67 GLenum convert_D3D_blendop_to_GL(D3DBLEND dwRenderState)
69 switch ((D3DBLEND) dwRenderState) {
70 case D3DBLEND_ZERO: return GL_ZERO;
71 case D3DBLEND_ONE: return GL_ONE;
72 case D3DBLEND_SRCALPHA: return GL_SRC_ALPHA;
73 case D3DBLEND_INVSRCALPHA: return GL_ONE_MINUS_SRC_ALPHA;
74 case D3DBLEND_DESTALPHA: return GL_DST_ALPHA;
75 case D3DBLEND_INVDESTALPHA: return GL_ONE_MINUS_DST_ALPHA;
76 case D3DBLEND_DESTCOLOR: return GL_DST_COLOR;
77 case D3DBLEND_INVDESTCOLOR: return GL_ONE_MINUS_DST_COLOR;
78 case D3DBLEND_SRCALPHASAT: return GL_SRC_ALPHA_SATURATE;
79 case D3DBLEND_SRCCOLOR: return GL_SRC_COLOR;
80 case D3DBLEND_INVSRCCOLOR: return GL_ONE_MINUS_SRC_COLOR;
81 default: ERR("Unhandled blend mode %d !\n", dwRenderState); return GL_ZERO;
85 void set_render_state(IDirect3DDeviceImpl* This,
86 D3DRENDERSTATETYPE dwRenderStateType, STATEBLOCK *lpStateBlock)
88 DWORD dwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
89 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
92 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
94 /* First, all the stipple patterns */
95 if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
96 (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
97 ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
101 /* All others state variables */
102 switch (dwRenderStateType) {
103 case D3DRENDERSTATE_TEXTUREHANDLE: { /* 1 */
104 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
106 IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
108 ICOM_INTERFACE(tex, IDirectDrawSurface7));
111 case D3DRENDERSTATE_TEXTUREADDRESSU: /* 44 */
112 case D3DRENDERSTATE_TEXTUREADDRESSV: /* 45 */
113 case D3DRENDERSTATE_TEXTUREADDRESS: { /* 3 */
114 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType;
116 if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) d3dTexStageStateType = D3DTSS_ADDRESS;
117 else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) d3dTexStageStateType = D3DTSS_ADDRESSU;
118 else d3dTexStageStateType = D3DTSS_ADDRESSV;
120 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
121 0, d3dTexStageStateType,
125 case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
127 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
129 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
132 case D3DRENDERSTATE_WRAPU: /* 5 */
133 case D3DRENDERSTATE_WRAPV: /* 6 */
134 case D3DRENDERSTATE_WRAP0: /* 128 */
135 case D3DRENDERSTATE_WRAP1: /* 129 */
136 case D3DRENDERSTATE_WRAP2: /* 130 */
137 case D3DRENDERSTATE_WRAP3: /* 131 */
138 case D3DRENDERSTATE_WRAP4: /* 132 */
139 case D3DRENDERSTATE_WRAP5: /* 133 */
140 case D3DRENDERSTATE_WRAP6: /* 134 */
141 case D3DRENDERSTATE_WRAP7: /* 135 */
143 ERR("Texture WRAP modes unsupported by OpenGL.. Expect graphical glitches !\n");
146 case D3DRENDERSTATE_ZENABLE: /* 7 */
147 /* To investigate : in OpenGL, if we disable the depth test, the Z buffer will NOT be
148 updated either.. No idea about what happens in D3D.
150 Maybe replacing the Z function by ALWAYS would be a better idea. */
151 if (dwRenderState == D3DZB_TRUE)
152 glEnable(GL_DEPTH_TEST);
153 else if (dwRenderState == D3DZB_FALSE)
154 glDisable(GL_DEPTH_TEST);
156 glEnable(GL_DEPTH_TEST);
157 WARN(" w-buffering not supported.\n");
161 case D3DRENDERSTATE_FILLMODE: /* 8 */
162 switch ((D3DFILLMODE) dwRenderState) {
164 glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
166 case D3DFILL_WIREFRAME:
167 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
170 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
173 ERR("Unhandled fill mode %ld !\n",dwRenderState);
177 case D3DRENDERSTATE_SHADEMODE: /* 9 */
178 switch ((D3DSHADEMODE) dwRenderState) {
180 glShadeModel(GL_FLAT);
182 case D3DSHADE_GOURAUD:
183 glShadeModel(GL_SMOOTH);
186 ERR("Unhandled shade mode %ld !\n",dwRenderState);
190 case D3DRENDERSTATE_ZWRITEENABLE: /* 14 */
192 glDepthMask(GL_TRUE);
194 glDepthMask(GL_FALSE);
197 case D3DRENDERSTATE_ALPHATESTENABLE: /* 15 */
199 glEnable(GL_ALPHA_TEST);
201 glDisable(GL_ALPHA_TEST);
204 case D3DRENDERSTATE_TEXTUREMAG: { /* 17 */
205 DWORD tex_mag = 0xFFFFFFFF;
207 switch ((D3DTEXTUREFILTER) dwRenderState) {
208 case D3DFILTER_NEAREST:
209 tex_mag = D3DTFG_POINT;
211 case D3DFILTER_LINEAR:
212 tex_mag = D3DTFG_LINEAR;
215 ERR("Unhandled texture mag %ld !\n",dwRenderState);
218 if (tex_mag != 0xFFFFFFFF) {
219 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag);
223 case D3DRENDERSTATE_TEXTUREMIN: { /* 18 */
224 DWORD tex_min = 0xFFFFFFFF;
226 switch ((D3DTEXTUREFILTER) dwRenderState) {
227 case D3DFILTER_NEAREST:
228 tex_min = D3DTFN_POINT;
230 case D3DFILTER_LINEAR:
231 tex_min = D3DTFN_LINEAR;
234 ERR("Unhandled texture min %ld !\n",dwRenderState);
237 if (tex_min != 0xFFFFFFFF) {
238 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min);
242 case D3DRENDERSTATE_SRCBLEND: /* 19 */
243 case D3DRENDERSTATE_DESTBLEND: /* 20 */
244 glBlendFunc(convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1]),
245 convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1]));
248 case D3DRENDERSTATE_TEXTUREMAPBLEND: /* 21 */
249 switch ((D3DTEXTUREBLEND) dwRenderState) {
250 case D3DTBLEND_DECAL:
251 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
253 case D3DTBLEND_MODULATE:
254 case D3DTBLEND_MODULATEALPHA:
255 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
258 ERR("Unhandled texture environment %ld !\n",dwRenderState);
262 case D3DRENDERSTATE_CULLMODE: /* 22 */
263 switch ((D3DCULL) dwRenderState) {
265 glDisable(GL_CULL_FACE);
268 glEnable(GL_CULL_FACE);
273 glEnable(GL_CULL_FACE);
278 ERR("Unhandled cull mode %ld !\n",dwRenderState);
282 case D3DRENDERSTATE_ZFUNC: /* 23 */
283 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
286 case D3DRENDERSTATE_ALPHAREF: /* 24 */
287 case D3DRENDERSTATE_ALPHAFUNC: /* 25 */
288 glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
289 (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
292 case D3DRENDERSTATE_DITHERENABLE: /* 26 */
296 glDisable(GL_DITHER);
299 case D3DRENDERSTATE_ALPHABLENDENABLE: /* 27 */
307 case D3DRENDERSTATE_FOGENABLE: /* 28 */
308 /* Nothing to do here. Only the storage matters :-) */
311 case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
313 ERR(" Specular Lighting not supported yet.\n");
316 case D3DRENDERSTATE_SUBPIXEL: /* 31 */
317 case D3DRENDERSTATE_SUBPIXELX: /* 32 */
318 /* We do not support this anyway, so why protest :-) */
321 case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
323 ERR(" Stippled Alpha not supported yet.\n");
326 case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
328 color[0] = ((dwRenderState >> 16) & 0xFF)/255.0f;
329 color[1] = ((dwRenderState >> 8) & 0xFF)/255.0f;
330 color[2] = ((dwRenderState >> 0) & 0xFF)/255.0f;
331 color[3] = ((dwRenderState >> 24) & 0xFF)/255.0f;
332 glFogfv(GL_FOG_COLOR,color);
333 /* Note: glFogiv does not seem to work */
336 case D3DRENDERSTATE_FOGTABLEMODE: /* 35 */
337 case D3DRENDERSTATE_FOGVERTEXMODE: /* 140 */
338 case D3DRENDERSTATE_FOGSTART: /* 36 */
339 case D3DRENDERSTATE_FOGEND: /* 37 */
340 /* Nothing to do here. Only the storage matters :-) */
343 case D3DRENDERSTATE_FOGDENSITY: /* 38 */
344 glFogi(GL_FOG_DENSITY,*(float*)&dwRenderState);
347 case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */
348 /* This needs to be fixed. */
355 case D3DRENDERSTATE_ZBIAS: /* 47 */
356 /* This is a tad bit hacky.. But well, no idea how to do it better in OpenGL :-/ */
357 if (dwRenderState == 0) {
358 glDisable(GL_POLYGON_OFFSET_FILL);
359 glDisable(GL_POLYGON_OFFSET_LINE);
360 glDisable(GL_POLYGON_OFFSET_POINT);
362 glEnable(GL_POLYGON_OFFSET_FILL);
363 glEnable(GL_POLYGON_OFFSET_LINE);
364 glEnable(GL_POLYGON_OFFSET_POINT);
365 glPolygonOffset(1.0, dwRenderState * 1.0);
369 case D3DRENDERSTATE_FLUSHBATCH: /* 50 */
372 case D3DRENDERSTATE_STENCILENABLE: /* 52 */
374 glEnable(GL_STENCIL_TEST);
376 glDisable(GL_STENCIL_TEST);
379 case D3DRENDERSTATE_STENCILFAIL: /* 53 */
380 case D3DRENDERSTATE_STENCILZFAIL: /* 54 */
381 case D3DRENDERSTATE_STENCILPASS: /* 55 */
382 glStencilOp(convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFAIL - 1]),
383 convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILZFAIL - 1]),
384 convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILPASS - 1]));
387 case D3DRENDERSTATE_STENCILFUNC: /* 56 */
388 case D3DRENDERSTATE_STENCILREF: /* 57 */
389 case D3DRENDERSTATE_STENCILMASK: /* 58 */
390 glStencilFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFUNC - 1]),
391 lpStateBlock->render_state[D3DRENDERSTATE_STENCILREF - 1],
392 lpStateBlock->render_state[D3DRENDERSTATE_STENCILMASK - 1]);
395 case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
396 glStencilMask(dwRenderState);
399 case D3DRENDERSTATE_TEXTUREFACTOR: /* 60 */
400 /* Only the storage matters... */
403 case D3DRENDERSTATE_CLIPPING: /* 136 */
404 case D3DRENDERSTATE_CLIPPLANEENABLE: { /* 152 */
408 if (dwRenderStateType == D3DRENDERSTATE_CLIPPING) {
409 mask = ((dwRenderState) ?
410 (This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) : (0x00000000));
412 mask = dwRenderState;
414 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner = (runner << 1)) {
417 glGetIntegerv(GL_CLIP_PLANE0 + i, &enabled);
418 if (enabled == GL_FALSE) {
419 glEnable(GL_CLIP_PLANE0 + i);
420 /* Need to force a transform change so that this clipping plane parameters are sent
423 glThis->transform_state = GL_TRANSFORM_NONE;
426 glDisable(GL_CLIP_PLANE0 + i);
432 case D3DRENDERSTATE_LIGHTING: /* 137 */
434 glEnable(GL_LIGHTING);
436 glDisable(GL_LIGHTING);
439 case D3DRENDERSTATE_AMBIENT: { /* 139 */
442 light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0;
443 light[1] = ((dwRenderState >> 8) & 0xFF) / 255.0;
444 light[2] = ((dwRenderState >> 0) & 0xFF) / 255.0;
445 light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0;
446 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
449 case D3DRENDERSTATE_COLORVERTEX: /* 141 */
450 /* Nothing to do here.. Only storage matters */
453 case D3DRENDERSTATE_LOCALVIEWER: /* 142 */
455 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
457 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
460 case D3DRENDERSTATE_NORMALIZENORMALS: /* 143 */
462 glEnable(GL_NORMALIZE);
463 glEnable(GL_RESCALE_NORMAL);
465 glDisable(GL_NORMALIZE);
466 glDisable(GL_RESCALE_NORMAL);
470 case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE: /* 145 */
471 case D3DRENDERSTATE_SPECULARMATERIALSOURCE: /* 146 */
472 case D3DRENDERSTATE_AMBIENTMATERIALSOURCE: /* 147 */
473 case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE: /* 148 */
474 /* Nothing to do here. Only the storage matters :-) */
478 ERR("Unhandled dwRenderStateType %s (%08x) value : %08lx !\n",
479 _get_renderstate(dwRenderStateType), dwRenderStateType, dwRenderState);
485 void store_render_state(IDirect3DDeviceImpl *This,
486 D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, STATEBLOCK *lpStateBlock)
488 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
490 /* Some special cases first.. */
491 if (dwRenderStateType == D3DRENDERSTATE_SRCBLEND) {
492 if (dwRenderState == D3DBLEND_BOTHSRCALPHA) {
493 lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_SRCALPHA;
494 lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_SRCALPHA;
496 } else if (dwRenderState == D3DBLEND_BOTHINVSRCALPHA) {
497 lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_INVSRCALPHA;
498 lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_INVSRCALPHA;
501 } else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) {
502 lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSU - 1] = dwRenderState;
503 lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSV - 1] = dwRenderState;
504 } else if (dwRenderStateType == D3DRENDERSTATE_WRAPU) {
506 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_U;
508 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
509 } else if (dwRenderStateType == D3DRENDERSTATE_WRAPV) {
511 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_V;
513 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
517 lpStateBlock->render_state[dwRenderStateType - 1] = dwRenderState;
520 void get_render_state(IDirect3DDeviceImpl *This,
521 D3DRENDERSTATETYPE dwRenderStateType, LPDWORD lpdwRenderState, STATEBLOCK *lpStateBlock)
523 *lpdwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
525 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
528 void apply_render_state(IDirect3DDeviceImpl *This, STATEBLOCK *lpStateBlock)
531 TRACE("(%p,%p)\n", This, lpStateBlock);
532 for(i = 0; i < HIGHEST_RENDER_STATE; i++)
533 if (lpStateBlock->set_flags.render_state[i])
534 set_render_state(This, i + 1, lpStateBlock);
538 /* Texture management code.
540 - upload_surface_to_tex_memory_init initialize the code and computes the GL formats
541 according to the surface description.
543 - upload_surface_to_tex_memory does the real upload. If one buffer is split over
544 multiple textures, this can be called multiple times after the '_init' call. 'rect'
545 can be NULL if the whole buffer needs to be upload.
547 - upload_surface_to_tex_memory_release does the clean-up.
549 These functions are called in the following cases :
550 - texture management (ie to upload a D3D texture to GL when it changes).
551 - flush of the 'in-memory' frame buffer to the GL frame buffer using the texture
553 - use of the texture engine to simulate Blits to the 3D Device.
561 CONVERT_CK_4444_ARGB,
566 CONVERT_CK_8888_ARGB,
570 /* Note : we suppose that all the code calling this is protected by the GL lock... Otherwise bad things
572 static GLenum current_format;
573 static GLenum current_pixel_format;
574 static CONVERT_TYPES convert_type;
575 static IDirectDrawSurfaceImpl *current_surface;
576 static GLuint current_level;
578 HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLuint level, GLenum *current_internal_format,
579 BOOLEAN need_to_alloc, BOOLEAN need_alpha_ck, DWORD tex_width, DWORD tex_height)
581 const DDPIXELFORMAT * const src_pf = &(surf_ptr->surface_desc.u4.ddpfPixelFormat);
583 BOOL colorkey_active = need_alpha_ck && (surf_ptr->surface_desc.dwFlags & DDSD_CKSRCBLT);
584 GLenum internal_format = GL_LUMINANCE; /* A bogus value to be sure to have a nice Mesa warning :-) */
585 BYTE bpp = GET_BPP(surf_ptr->surface_desc);
587 current_surface = surf_ptr;
588 current_level = level;
590 /* First, do some sanity checks ... */
591 if ((surf_ptr->surface_desc.u1.lPitch % bpp) != 0) {
592 FIXME("Warning : pitch is not a multiple of BPP - not supported yet !\n");
595 /* Note: we only check width here as you cannot have width non-zero while height is set to zero */
596 if (tex_width != 0) {
597 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
599 if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
600 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
602 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
604 tex_width = surf_ptr->surface_desc.dwWidth;
605 tex_height = surf_ptr->surface_desc.dwHeight;
608 if (src_pf->dwFlags & DDPF_PALETTEINDEXED8) {
612 current_format = GL_RGBA;
613 internal_format = GL_RGBA;
614 current_pixel_format = GL_UNSIGNED_BYTE;
615 convert_type = CONVERT_PALETTED;
616 } else if (src_pf->dwFlags & DDPF_RGB) {
620 if (src_pf->u1.dwRGBBitCount == 8) {
621 if ((src_pf->u2.dwRBitMask == 0xE0) &&
622 (src_pf->u3.dwGBitMask == 0x1C) &&
623 (src_pf->u4.dwBBitMask == 0x03)) {
624 /* **********************
625 GL_UNSIGNED_BYTE_3_3_2
626 ********************** */
627 if (colorkey_active) {
628 /* This texture format will never be used.. So do not care about color keying
629 up until the point in time it will be needed :-) */
630 FIXME(" ColorKeying not supported in the RGB 332 format !");
632 current_format = GL_RGB;
633 internal_format = GL_RGB;
634 current_pixel_format = GL_UNSIGNED_BYTE_3_3_2;
635 convert_type = NO_CONVERSION;
639 } else if (src_pf->u1.dwRGBBitCount == 16) {
640 if ((src_pf->u2.dwRBitMask == 0xF800) &&
641 (src_pf->u3.dwGBitMask == 0x07E0) &&
642 (src_pf->u4.dwBBitMask == 0x001F) &&
643 (src_pf->u5.dwRGBAlphaBitMask == 0x0000)) {
644 if (colorkey_active) {
645 convert_type = CONVERT_CK_565;
646 current_format = GL_RGBA;
647 internal_format = GL_RGBA;
648 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
650 convert_type = NO_CONVERSION;
651 current_format = GL_RGB;
652 internal_format = GL_RGB;
653 current_pixel_format = GL_UNSIGNED_SHORT_5_6_5;
655 } else if ((src_pf->u2.dwRBitMask == 0xF800) &&
656 (src_pf->u3.dwGBitMask == 0x07C0) &&
657 (src_pf->u4.dwBBitMask == 0x003E) &&
658 (src_pf->u5.dwRGBAlphaBitMask == 0x0001)) {
659 current_format = GL_RGBA;
660 internal_format = GL_RGBA;
661 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
662 if (colorkey_active) {
663 convert_type = CONVERT_CK_5551;
665 convert_type = NO_CONVERSION;
667 } else if ((src_pf->u2.dwRBitMask == 0xF000) &&
668 (src_pf->u3.dwGBitMask == 0x0F00) &&
669 (src_pf->u4.dwBBitMask == 0x00F0) &&
670 (src_pf->u5.dwRGBAlphaBitMask == 0x000F)) {
671 current_format = GL_RGBA;
672 internal_format = GL_RGBA;
673 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
674 if (colorkey_active) {
675 convert_type = CONVERT_CK_4444;
677 convert_type = NO_CONVERSION;
679 } else if ((src_pf->u2.dwRBitMask == 0x0F00) &&
680 (src_pf->u3.dwGBitMask == 0x00F0) &&
681 (src_pf->u4.dwBBitMask == 0x000F) &&
682 (src_pf->u5.dwRGBAlphaBitMask == 0xF000)) {
683 if (colorkey_active) {
684 convert_type = CONVERT_CK_4444_ARGB;
685 current_format = GL_RGBA;
686 internal_format = GL_RGBA;
687 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
689 convert_type = NO_CONVERSION;
690 current_format = GL_BGRA;
691 internal_format = GL_RGBA;
692 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4_REV;
694 } else if ((src_pf->u2.dwRBitMask == 0x7C00) &&
695 (src_pf->u3.dwGBitMask == 0x03E0) &&
696 (src_pf->u4.dwBBitMask == 0x001F) &&
697 (src_pf->u5.dwRGBAlphaBitMask == 0x8000)) {
698 if (colorkey_active) {
699 convert_type = CONVERT_CK_1555;
700 current_format = GL_RGBA;
701 internal_format = GL_RGBA;
702 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
704 convert_type = NO_CONVERSION;
705 current_format = GL_BGRA;
706 internal_format = GL_RGBA;
707 current_pixel_format = GL_UNSIGNED_SHORT_1_5_5_5_REV;
709 } else if ((src_pf->u2.dwRBitMask == 0x7C00) &&
710 (src_pf->u3.dwGBitMask == 0x03E0) &&
711 (src_pf->u4.dwBBitMask == 0x001F) &&
712 (src_pf->u5.dwRGBAlphaBitMask == 0x0000)) {
713 convert_type = CONVERT_555;
714 current_format = GL_RGBA;
715 internal_format = GL_RGBA;
716 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
720 } else if (src_pf->u1.dwRGBBitCount == 24) {
721 if ((src_pf->u2.dwRBitMask == 0x00FF0000) &&
722 (src_pf->u3.dwGBitMask == 0x0000FF00) &&
723 (src_pf->u4.dwBBitMask == 0x000000FF) &&
724 (src_pf->u5.dwRGBAlphaBitMask == 0x00000000)) {
725 if (colorkey_active) {
726 convert_type = CONVERT_CK_RGB24;
727 current_format = GL_RGBA;
728 internal_format = GL_RGBA;
729 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
731 convert_type = NO_CONVERSION;
732 current_format = GL_BGR;
733 internal_format = GL_RGB;
734 current_pixel_format = GL_UNSIGNED_BYTE;
739 } else if (src_pf->u1.dwRGBBitCount == 32) {
740 if ((src_pf->u2.dwRBitMask == 0xFF000000) &&
741 (src_pf->u3.dwGBitMask == 0x00FF0000) &&
742 (src_pf->u4.dwBBitMask == 0x0000FF00) &&
743 (src_pf->u5.dwRGBAlphaBitMask == 0x000000FF)) {
744 if (colorkey_active) {
745 convert_type = CONVERT_CK_8888;
747 convert_type = NO_CONVERSION;
749 current_format = GL_RGBA;
750 internal_format = GL_RGBA;
751 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
752 } else if ((src_pf->u2.dwRBitMask == 0x00FF0000) &&
753 (src_pf->u3.dwGBitMask == 0x0000FF00) &&
754 (src_pf->u4.dwBBitMask == 0x000000FF) &&
755 (src_pf->u5.dwRGBAlphaBitMask == 0xFF000000)) {
756 if (colorkey_active) {
757 convert_type = CONVERT_CK_8888_ARGB;
758 current_format = GL_RGBA;
759 internal_format = GL_RGBA;
760 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
762 convert_type = NO_CONVERSION;
763 current_format = GL_BGRA;
764 internal_format = GL_RGBA;
765 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8_REV;
767 } else if ((src_pf->u2.dwRBitMask == 0x00FF0000) &&
768 (src_pf->u3.dwGBitMask == 0x0000FF00) &&
769 (src_pf->u4.dwBBitMask == 0x000000FF) &&
770 (src_pf->u5.dwRGBAlphaBitMask == 0x00000000)) {
772 convert_type = CONVERT_RGB32_888;
773 current_format = GL_RGBA;
774 internal_format = GL_RGBA;
775 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
777 convert_type = NO_CONVERSION;
778 current_format = GL_BGRA;
779 internal_format = GL_RGBA;
780 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8_REV;
794 ERR(" unsupported pixel format for textures : \n");
795 DDRAW_dump_pixelformat(src_pf);
797 return DDERR_INVALIDPIXELFORMAT;
799 if ((need_to_alloc) ||
800 (internal_format != *current_internal_format)) {
801 glTexImage2D(GL_TEXTURE_2D, level, internal_format,
802 tex_width, tex_height, 0,
803 current_format, current_pixel_format, NULL);
804 *current_internal_format = internal_format;
811 HRESULT upload_surface_to_tex_memory(RECT *rect, void **temp_buffer)
813 const DDSURFACEDESC * const src_d = (DDSURFACEDESC *)&(current_surface->surface_desc);
814 void *surf_buffer = NULL;
816 switch (convert_type) {
817 case CONVERT_PALETTED: {
818 IDirectDrawPaletteImpl* pal = current_surface->palette;
821 BYTE *src = (BYTE *) src_d->lpSurface, *dst;
824 /* Upload a black texture. The real one will be uploaded on palette change */
825 WARN("Palettized texture Loading with a NULL palette !\n");
826 memset(table, 0, 256 * 4);
828 /* Get the surface's palette */
829 for (i = 0; i < 256; i++) {
830 table[i][0] = pal->palents[i].peRed;
831 table[i][1] = pal->palents[i].peGreen;
832 table[i][2] = pal->palents[i].peBlue;
833 if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
834 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
835 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
836 /* We should maybe here put a more 'neutral' color than the standard bright purple
837 one often used by application to prevent the nice purple borders when bi-linear
845 if (*temp_buffer == NULL)
846 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
847 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
848 dst = (BYTE *) *temp_buffer;
850 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
852 *dst++ = table[color][0];
853 *dst++ = table[color][1];
854 *dst++ = table[color][2];
855 *dst++ = table[color][3];
859 case CONVERT_CK_565: {
860 /* Converting the 565 format in 5551 packed to emulate color-keying.
862 Note : in all these conversion, it would be best to average the averaging
863 pixels to get the color of the pixel that will be color-keyed to
864 prevent 'color bleeding'. This will be done later on if ever it is
867 Note2: when using color-keying + alpha, are the alpha bits part of the
871 WORD *src = (WORD *) src_d->lpSurface, *dst;
873 if (*temp_buffer != NULL)
874 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
875 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
876 dst = (WORD *) *temp_buffer;
878 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
880 *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
881 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
882 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
888 case CONVERT_CK_5551: {
889 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
891 WORD *src = (WORD *) src_d->lpSurface, *dst;
893 if (*temp_buffer != NULL)
894 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
895 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
896 dst = (WORD *) *temp_buffer;
898 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
900 *dst = color & 0xFFFE;
901 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
902 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
903 *dst |= color & 0x0001;
908 case CONVERT_CK_4444: {
909 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
911 WORD *src = (WORD *) src_d->lpSurface, *dst;
913 if (*temp_buffer != NULL)
914 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
915 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
916 dst = (WORD *) *temp_buffer;
918 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
920 *dst = color & 0xFFF0;
921 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
922 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
923 *dst |= color & 0x000F;
928 case CONVERT_CK_4444_ARGB: {
929 /* Move the four Alpha bits... */
931 WORD *src = (WORD *) src_d->lpSurface, *dst;
933 if (*temp_buffer != NULL)
934 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
935 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
936 dst = (WORD *) *temp_buffer;
938 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
940 *dst = (color & 0x0FFF) << 4;
941 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
942 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
943 *dst |= (color & 0xF000) >> 12;
948 case CONVERT_CK_1555: {
950 WORD *src = (WORD *) src_d->lpSurface, *dst;
952 if (*temp_buffer != NULL)
953 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
954 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
955 dst = (WORD *) *temp_buffer;
957 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
959 *dst = (color & 0x7FFF) << 1;
960 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
961 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
962 *dst |= (color & 0x8000) >> 15;
968 /* Converting the 0555 format in 5551 packed */
970 WORD *src = (WORD *) src_d->lpSurface, *dst;
972 if (*temp_buffer != NULL)
973 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
974 src_d->dwWidth * src_d->dwHeight * sizeof(WORD));
975 dst = (WORD *) *temp_buffer;
977 if (src_d->dwFlags & DDSD_CKSRCBLT) {
978 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
980 *dst = (color & 0x7FFF) << 1;
981 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
982 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
987 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
989 *dst++ = ((color & 0x7FFF) << 1) | 0x0001;
995 case CONVERT_CK_RGB24: {
996 /* This is a pain :-) */
998 BYTE *src = (BYTE *) src_d->lpSurface;
1001 if (*temp_buffer != NULL)
1002 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1003 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
1004 dst = (DWORD *) *temp_buffer;
1006 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1007 DWORD color = *((DWORD *) src) & 0x00FFFFFF;
1010 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1011 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1017 case CONVERT_CK_8888: {
1018 /* Just use the alpha component to handle color-keying... */
1020 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1022 if (*temp_buffer != NULL)
1023 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1024 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
1025 dst = (DWORD *) *temp_buffer;
1027 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1028 DWORD color = *src++;
1029 *dst = color & 0xFFFFFF00;
1030 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1031 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1032 *dst |= color & 0x000000FF;
1037 case CONVERT_CK_8888_ARGB: {
1039 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1041 if (*temp_buffer != NULL)
1042 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1043 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
1044 dst = (DWORD *) *temp_buffer;
1046 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1047 DWORD color = *src++;
1048 *dst = (color & 0x00FFFFFF) << 8;
1049 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1050 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1051 *dst |= (color & 0xFF000000) >> 24;
1056 case CONVERT_RGB32_888: {
1057 /* Just add an alpha component and handle color-keying... */
1059 DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1061 if (*temp_buffer != NULL)
1062 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1063 src_d->dwWidth * src_d->dwHeight * sizeof(DWORD));
1064 dst = (DWORD *) *temp_buffer;
1066 if (src_d->dwFlags & DDSD_CKSRCBLT) {
1067 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1068 DWORD color = *src++;
1070 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1071 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1076 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1077 *dst++ = (*src++ << 8) | 0xFF;
1083 /* Nothing to do here as the name suggests... This just prevents a compiler warning */
1084 surf_buffer = src_d->lpSurface;
1088 if (convert_type != NO_CONVERSION) {
1089 surf_buffer = *temp_buffer;
1092 glTexSubImage2D(GL_TEXTURE_2D,
1095 src_d->dwWidth, src_d->dwHeight,
1097 current_pixel_format,
1103 HRESULT upload_surface_to_tex_memory_release(void)
1105 current_surface = NULL;