Support the mimap lod bias extension.
[wine/wine-kai.git] / dlls / ddraw / mesa.c
blobe144e928c20e5834fd25e30a8a1568b5aff44817
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
21 #include "config.h"
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
25 #include "windef.h"
26 #include "objbase.h"
27 #include "ddraw.h"
28 #include "d3d.h"
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);
48 return GL_ALWAYS;
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);
64 return GL_KEEP;
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;
91 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
93 /* First, all the stipple patterns */
94 if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
95 (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
96 ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
97 } else {
98 ENTER_GL();
100 /* All others state variables */
101 switch (dwRenderStateType) {
102 case D3DRENDERSTATE_TEXTUREHANDLE: { /* 1 */
103 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
105 IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
107 ICOM_INTERFACE(tex, IDirectDrawSurface7));
108 } break;
110 case D3DRENDERSTATE_ANTIALIAS: /* 2 */
111 if (dwRenderState)
112 ERR("D3DRENDERSTATE_ANTIALIAS not supported yet !\n");
113 break;
115 case D3DRENDERSTATE_TEXTUREADDRESSU: /* 44 */
116 case D3DRENDERSTATE_TEXTUREADDRESSV: /* 45 */
117 case D3DRENDERSTATE_TEXTUREADDRESS: { /* 3 */
118 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType;
120 if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) d3dTexStageStateType = D3DTSS_ADDRESS;
121 else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) d3dTexStageStateType = D3DTSS_ADDRESSU;
122 else d3dTexStageStateType = D3DTSS_ADDRESSV;
124 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
125 0, d3dTexStageStateType,
126 dwRenderState);
127 } break;
129 case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
130 if (dwRenderState)
131 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
132 else
133 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
134 break;
136 case D3DRENDERSTATE_WRAPU: /* 5 */
137 case D3DRENDERSTATE_WRAPV: /* 6 */
138 case D3DRENDERSTATE_WRAP0: /* 128 */
139 case D3DRENDERSTATE_WRAP1: /* 129 */
140 case D3DRENDERSTATE_WRAP2: /* 130 */
141 case D3DRENDERSTATE_WRAP3: /* 131 */
142 case D3DRENDERSTATE_WRAP4: /* 132 */
143 case D3DRENDERSTATE_WRAP5: /* 133 */
144 case D3DRENDERSTATE_WRAP6: /* 134 */
145 case D3DRENDERSTATE_WRAP7: /* 135 */
146 if (dwRenderState)
147 ERR("Texture WRAP modes unsupported by OpenGL.. Expect graphical glitches !\n");
148 break;
150 case D3DRENDERSTATE_ZENABLE: /* 7 */
151 /* To investigate : in OpenGL, if we disable the depth test, the Z buffer will NOT be
152 updated either.. No idea about what happens in D3D.
154 Maybe replacing the Z function by ALWAYS would be a better idea. */
155 if (dwRenderState == D3DZB_TRUE) {
156 if (glThis->depth_test == FALSE) {
157 glEnable(GL_DEPTH_TEST);
158 glThis->depth_test = TRUE;
160 } else if (dwRenderState == D3DZB_FALSE) {
161 if (glThis->depth_test == TRUE) {
162 glDisable(GL_DEPTH_TEST);
163 glThis->depth_test = FALSE;
165 } else {
166 if (glThis->depth_test == FALSE) {
167 glEnable(GL_DEPTH_TEST);
168 glThis->depth_test = TRUE;
170 WARN(" w-buffering not supported.\n");
172 break;
174 case D3DRENDERSTATE_FILLMODE: /* 8 */
175 switch ((D3DFILLMODE) dwRenderState) {
176 case D3DFILL_POINT:
177 glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);
178 break;
179 case D3DFILL_WIREFRAME:
180 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
181 break;
182 case D3DFILL_SOLID:
183 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
184 break;
185 default:
186 ERR("Unhandled fill mode %ld !\n",dwRenderState);
188 break;
190 case D3DRENDERSTATE_SHADEMODE: /* 9 */
191 switch ((D3DSHADEMODE) dwRenderState) {
192 case D3DSHADE_FLAT:
193 glShadeModel(GL_FLAT);
194 break;
195 case D3DSHADE_GOURAUD:
196 glShadeModel(GL_SMOOTH);
197 break;
198 default:
199 ERR("Unhandled shade mode %ld !\n",dwRenderState);
201 break;
203 case D3DRENDERSTATE_ZWRITEENABLE: /* 14 */
204 if ((dwRenderState != FALSE) && (glThis->depth_mask == FALSE))
205 glDepthMask(GL_TRUE);
206 else if ((dwRenderState == FALSE) && (glThis->depth_mask != FALSE))
207 glDepthMask(GL_FALSE);
208 glThis->depth_mask = dwRenderState;
209 break;
211 case D3DRENDERSTATE_ALPHATESTENABLE: /* 15 */
212 if ((dwRenderState != 0) && (glThis->alpha_test == FALSE))
213 glEnable(GL_ALPHA_TEST);
214 else if ((dwRenderState == 0) && (glThis->alpha_test != FALSE))
215 glDisable(GL_ALPHA_TEST);
216 glThis->alpha_test = dwRenderState;
217 break;
219 case D3DRENDERSTATE_TEXTUREMAG: { /* 17 */
220 DWORD tex_mag = 0xFFFFFFFF;
222 switch ((D3DTEXTUREFILTER) dwRenderState) {
223 case D3DFILTER_NEAREST:
224 tex_mag = D3DTFG_POINT;
225 break;
226 case D3DFILTER_LINEAR:
227 tex_mag = D3DTFG_LINEAR;
228 break;
229 default:
230 ERR("Unhandled texture mag %ld !\n",dwRenderState);
233 if (tex_mag != 0xFFFFFFFF) {
234 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag);
236 } break;
238 case D3DRENDERSTATE_TEXTUREMIN: { /* 18 */
239 DWORD tex_min = 0xFFFFFFFF;
241 switch ((D3DTEXTUREFILTER) dwRenderState) {
242 case D3DFILTER_NEAREST:
243 tex_min = D3DTFN_POINT;
244 break;
245 case D3DFILTER_LINEAR:
246 tex_min = D3DTFN_LINEAR;
247 break;
248 default:
249 ERR("Unhandled texture min %ld !\n",dwRenderState);
252 if (tex_min != 0xFFFFFFFF) {
253 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min);
255 } break;
257 case D3DRENDERSTATE_SRCBLEND: /* 19 */
258 case D3DRENDERSTATE_DESTBLEND: /* 20 */
259 glBlendFunc(convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1]),
260 convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1]));
261 break;
263 case D3DRENDERSTATE_TEXTUREMAPBLEND: { /* 21 */
264 IDirect3DDevice7 *d3ddev = ICOM_INTERFACE(This, IDirect3DDevice7);
266 switch ((D3DTEXTUREBLEND) dwRenderState) {
267 case D3DTBLEND_DECAL:
268 if (glThis->current_tex_env != GL_REPLACE) {
269 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
270 glThis->current_tex_env = GL_REPLACE;
272 break;
273 case D3DTBLEND_DECALALPHA:
274 if (glThis->current_tex_env != GL_REPLACE) {
275 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
276 glThis->current_tex_env = GL_DECAL;
278 break;
279 case D3DTBLEND_MODULATE:
280 if (glThis->current_tex_env != GL_MODULATE) {
281 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
282 glThis->current_tex_env = GL_MODULATE;
284 break;
285 case D3DTBLEND_MODULATEALPHA:
286 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
287 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
288 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_COLORARG2, D3DTA_CURRENT);
289 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
290 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
291 IDirect3DDevice7_SetTextureStageState(d3ddev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
292 break;
293 default:
294 ERR("Unhandled texture environment %ld !\n",dwRenderState);
296 } break;
298 case D3DRENDERSTATE_CULLMODE: /* 22 */
299 switch ((D3DCULL) dwRenderState) {
300 case D3DCULL_NONE:
301 if (glThis->cull_face != 0) {
302 glDisable(GL_CULL_FACE);
303 glThis->cull_face = 0;
305 break;
306 case D3DCULL_CW:
307 if (glThis->cull_face == 0) {
308 glEnable(GL_CULL_FACE);
309 glThis->cull_face = 1;
311 glFrontFace(GL_CCW);
312 glCullFace(GL_BACK);
313 break;
314 case D3DCULL_CCW:
315 if (glThis->cull_face == 0) {
316 glEnable(GL_CULL_FACE);
317 glThis->cull_face = 1;
319 glFrontFace(GL_CW);
320 glCullFace(GL_BACK);
321 break;
322 default:
323 ERR("Unhandled cull mode %ld !\n",dwRenderState);
325 break;
327 case D3DRENDERSTATE_ZFUNC: /* 23 */
328 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
329 break;
331 case D3DRENDERSTATE_ALPHAREF: /* 24 */
332 case D3DRENDERSTATE_ALPHAFUNC: /* 25 */
333 glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
334 (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
335 break;
337 case D3DRENDERSTATE_DITHERENABLE: /* 26 */
338 if (dwRenderState)
339 glEnable(GL_DITHER);
340 else
341 glDisable(GL_DITHER);
342 break;
344 case D3DRENDERSTATE_ALPHABLENDENABLE: /* 27 */
345 if ((dwRenderState != 0) && (glThis->blending == 0)) {
346 glEnable(GL_BLEND);
347 } else if ((dwRenderState == 0) && (glThis->blending != 0)) {
348 glDisable(GL_BLEND);
350 glThis->blending = dwRenderState;
351 break;
353 case D3DRENDERSTATE_FOGENABLE: /* 28 */
354 /* Nothing to do here. Only the storage matters :-) */
355 break;
357 case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
358 if (dwRenderState)
359 ERR(" Specular Lighting not supported yet.\n");
360 break;
362 case D3DRENDERSTATE_SUBPIXEL: /* 31 */
363 case D3DRENDERSTATE_SUBPIXELX: /* 32 */
364 /* We do not support this anyway, so why protest :-) */
365 break;
367 case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
368 if (dwRenderState)
369 ERR(" Stippled Alpha not supported yet.\n");
370 break;
372 case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
373 GLfloat color[4];
374 color[0] = ((dwRenderState >> 16) & 0xFF)/255.0f;
375 color[1] = ((dwRenderState >> 8) & 0xFF)/255.0f;
376 color[2] = ((dwRenderState >> 0) & 0xFF)/255.0f;
377 color[3] = ((dwRenderState >> 24) & 0xFF)/255.0f;
378 glFogfv(GL_FOG_COLOR,color);
379 /* Note: glFogiv does not seem to work */
380 } break;
382 case D3DRENDERSTATE_FOGTABLEMODE: /* 35 */
383 case D3DRENDERSTATE_FOGVERTEXMODE: /* 140 */
384 case D3DRENDERSTATE_FOGSTART: /* 36 */
385 case D3DRENDERSTATE_FOGEND: /* 37 */
386 /* Nothing to do here. Only the storage matters :-) */
387 break;
389 case D3DRENDERSTATE_FOGDENSITY: /* 38 */
390 glFogi(GL_FOG_DENSITY,*(float*)&dwRenderState);
391 break;
393 case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */
394 /* This needs to be fixed. */
395 if ((dwRenderState != 0) && (glThis->blending == 0)) {
396 glEnable(GL_BLEND);
397 } else if ((dwRenderState == 0) && (glThis->blending != 0)) {
398 glDisable(GL_BLEND);
400 glThis->blending = dwRenderState;
401 break;
403 case D3DRENDERSTATE_MIPMAPLODBIAS: /* 46 */
404 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
405 0, D3DTSS_MIPMAPLODBIAS,
406 dwRenderState);
407 break;
409 case D3DRENDERSTATE_ZBIAS: /* 47 */
410 /* This is a tad bit hacky.. But well, no idea how to do it better in OpenGL :-/ */
411 if (dwRenderState == 0) {
412 glDisable(GL_POLYGON_OFFSET_FILL);
413 glDisable(GL_POLYGON_OFFSET_LINE);
414 glDisable(GL_POLYGON_OFFSET_POINT);
415 } else {
416 glEnable(GL_POLYGON_OFFSET_FILL);
417 glEnable(GL_POLYGON_OFFSET_LINE);
418 glEnable(GL_POLYGON_OFFSET_POINT);
419 glPolygonOffset(1.0, dwRenderState * 1.0);
421 break;
423 case D3DRENDERSTATE_FLUSHBATCH: /* 50 */
424 break;
426 case D3DRENDERSTATE_STENCILENABLE: /* 52 */
427 if ((dwRenderState != 0) && (glThis->stencil_test == 0))
428 glEnable(GL_STENCIL_TEST);
429 else if ((dwRenderState == 0) && (glThis->stencil_test != 0))
430 glDisable(GL_STENCIL_TEST);
431 glThis->stencil_test = dwRenderState;
432 break;
434 case D3DRENDERSTATE_STENCILFAIL: /* 53 */
435 case D3DRENDERSTATE_STENCILZFAIL: /* 54 */
436 case D3DRENDERSTATE_STENCILPASS: /* 55 */
437 glStencilOp(convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFAIL - 1]),
438 convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILZFAIL - 1]),
439 convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILPASS - 1]));
440 break;
442 case D3DRENDERSTATE_STENCILFUNC: /* 56 */
443 case D3DRENDERSTATE_STENCILREF: /* 57 */
444 case D3DRENDERSTATE_STENCILMASK: /* 58 */
445 glStencilFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFUNC - 1]),
446 lpStateBlock->render_state[D3DRENDERSTATE_STENCILREF - 1],
447 lpStateBlock->render_state[D3DRENDERSTATE_STENCILMASK - 1]);
448 break;
450 case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
451 glStencilMask(dwRenderState);
452 break;
454 case D3DRENDERSTATE_TEXTUREFACTOR: /* 60 */
455 /* Only the storage matters... */
456 break;
458 case D3DRENDERSTATE_CLIPPING: /* 136 */
459 case D3DRENDERSTATE_CLIPPLANEENABLE: { /* 152 */
460 GLint i;
461 DWORD mask, runner;
463 if (dwRenderStateType == D3DRENDERSTATE_CLIPPING) {
464 mask = ((dwRenderState) ?
465 (This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) : (0x00000000));
466 } else {
467 mask = dwRenderState;
469 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner = (runner << 1)) {
470 if (mask & runner) {
471 GLint enabled;
472 glGetIntegerv(GL_CLIP_PLANE0 + i, &enabled);
473 if (enabled == GL_FALSE) {
474 glEnable(GL_CLIP_PLANE0 + i);
475 /* Need to force a transform change so that this clipping plane parameters are sent
476 * properly to GL.
478 glThis->transform_state = GL_TRANSFORM_NONE;
480 } else {
481 glDisable(GL_CLIP_PLANE0 + i);
485 break;
487 case D3DRENDERSTATE_LIGHTING: /* 137 */
488 /* Nothing to do, only storage matters... */
489 break;
491 case D3DRENDERSTATE_AMBIENT: { /* 139 */
492 float light[4];
494 light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0;
495 light[1] = ((dwRenderState >> 8) & 0xFF) / 255.0;
496 light[2] = ((dwRenderState >> 0) & 0xFF) / 255.0;
497 light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0;
498 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
499 } break;
501 case D3DRENDERSTATE_COLORVERTEX: /* 141 */
502 /* Nothing to do here.. Only storage matters */
503 break;
505 case D3DRENDERSTATE_LOCALVIEWER: /* 142 */
506 if (dwRenderState)
507 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
508 else
509 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
510 break;
512 case D3DRENDERSTATE_NORMALIZENORMALS: /* 143 */
513 if (dwRenderState) {
514 glEnable(GL_NORMALIZE);
515 glEnable(GL_RESCALE_NORMAL);
516 } else {
517 glDisable(GL_NORMALIZE);
518 glDisable(GL_RESCALE_NORMAL);
520 break;
522 case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE: /* 145 */
523 case D3DRENDERSTATE_SPECULARMATERIALSOURCE: /* 146 */
524 case D3DRENDERSTATE_AMBIENTMATERIALSOURCE: /* 147 */
525 case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE: /* 148 */
526 /* Nothing to do here. Only the storage matters :-) */
527 break;
529 default:
530 ERR("Unhandled dwRenderStateType %s (%08x) value : %08lx !\n",
531 _get_renderstate(dwRenderStateType), dwRenderStateType, dwRenderState);
533 LEAVE_GL();
537 void store_render_state(IDirect3DDeviceImpl *This,
538 D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, STATEBLOCK *lpStateBlock)
540 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
542 /* Some special cases first.. */
543 if (dwRenderStateType == D3DRENDERSTATE_SRCBLEND) {
544 if (dwRenderState == D3DBLEND_BOTHSRCALPHA) {
545 lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_SRCALPHA;
546 lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_SRCALPHA;
547 return;
548 } else if (dwRenderState == D3DBLEND_BOTHINVSRCALPHA) {
549 lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_INVSRCALPHA;
550 lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_INVSRCALPHA;
551 return;
553 } else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) {
554 lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSU - 1] = dwRenderState;
555 lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSV - 1] = dwRenderState;
556 } else if (dwRenderStateType == D3DRENDERSTATE_WRAPU) {
557 if (dwRenderState)
558 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_U;
559 else
560 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
561 } else if (dwRenderStateType == D3DRENDERSTATE_WRAPV) {
562 if (dwRenderState)
563 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_V;
564 else
565 lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
568 /* Default case */
569 lpStateBlock->render_state[dwRenderStateType - 1] = dwRenderState;
572 void get_render_state(IDirect3DDeviceImpl *This,
573 D3DRENDERSTATETYPE dwRenderStateType, LPDWORD lpdwRenderState, STATEBLOCK *lpStateBlock)
575 *lpdwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
576 if (TRACE_ON(ddraw))
577 TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
580 void apply_render_state(IDirect3DDeviceImpl *This, STATEBLOCK *lpStateBlock)
582 DWORD i;
583 TRACE("(%p,%p)\n", This, lpStateBlock);
584 for(i = 0; i < HIGHEST_RENDER_STATE; i++)
585 if (lpStateBlock->set_flags.render_state[i])
586 set_render_state(This, i + 1, lpStateBlock);
590 /* Texture management code.
592 - upload_surface_to_tex_memory_init initialize the code and computes the GL formats
593 according to the surface description.
595 - upload_surface_to_tex_memory does the real upload. If one buffer is split over
596 multiple textures, this can be called multiple times after the '_init' call. 'rect'
597 can be NULL if the whole buffer needs to be upload.
599 - upload_surface_to_tex_memory_release does the clean-up.
601 These functions are called in the following cases :
602 - texture management (ie to upload a D3D texture to GL when it changes).
603 - flush of the 'in-memory' frame buffer to the GL frame buffer using the texture
604 engine.
605 - use of the texture engine to simulate Blits to the 3D Device.
607 typedef enum {
608 NO_CONVERSION,
609 CONVERT_PALETTED,
610 CONVERT_CK_565,
611 CONVERT_CK_5551,
612 CONVERT_CK_4444,
613 CONVERT_CK_4444_ARGB,
614 CONVERT_CK_1555,
615 CONVERT_555,
616 CONVERT_CK_RGB24,
617 CONVERT_CK_8888,
618 CONVERT_CK_8888_ARGB,
619 CONVERT_RGB32_888
620 } CONVERT_TYPES;
622 /* Note : we suppose that all the code calling this is protected by the GL lock... Otherwise bad things
623 may happen :-) */
624 static GLenum current_format;
625 static GLenum current_pixel_format;
626 static CONVERT_TYPES convert_type;
627 static IDirectDrawSurfaceImpl *current_surface;
628 static GLuint current_level;
629 static DWORD current_tex_width;
630 static DWORD current_tex_height;
631 static GLuint current_alignement_constraints;
632 static int current_storage_width;
634 HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLuint level, GLenum *current_internal_format,
635 BOOLEAN need_to_alloc, BOOLEAN need_alpha_ck, DWORD tex_width, DWORD tex_height)
637 const DDPIXELFORMAT * const src_pf = &(surf_ptr->surface_desc.u4.ddpfPixelFormat);
638 BOOL error = FALSE;
639 BOOL colorkey_active = need_alpha_ck && (surf_ptr->surface_desc.dwFlags & DDSD_CKSRCBLT);
640 GLenum internal_format = GL_LUMINANCE; /* A bogus value to be sure to have a nice Mesa warning :-) */
641 BYTE bpp = GET_BPP(surf_ptr->surface_desc);
642 BOOL sub_texture = TRUE;
644 current_surface = surf_ptr;
645 current_level = level;
647 /* First, do some sanity checks ... */
648 if ((surf_ptr->surface_desc.u1.lPitch % bpp) != 0) {
649 FIXME("Warning : pitch is not a multiple of BPP - not supported yet !\n");
650 } else {
651 /* In that case, no need to have any alignement constraints... */
652 if (current_alignement_constraints != 1) {
653 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
654 current_alignement_constraints = 1;
658 /* Note: we only check width here as you cannot have width non-zero while height is set to zero */
659 if (tex_width == 0) {
660 sub_texture = FALSE;
662 tex_width = surf_ptr->surface_desc.dwWidth;
663 tex_height = surf_ptr->surface_desc.dwHeight;
666 current_tex_width = tex_width;
667 current_tex_height = tex_height;
669 if (src_pf->dwFlags & DDPF_PALETTEINDEXED8) {
670 /* ****************
671 Paletted Texture
672 **************** */
673 current_format = GL_RGBA;
674 internal_format = GL_RGBA;
675 current_pixel_format = GL_UNSIGNED_BYTE;
676 convert_type = CONVERT_PALETTED;
677 } else if (src_pf->dwFlags & DDPF_RGB) {
678 /* ************
679 RGB Textures
680 ************ */
681 if (src_pf->u1.dwRGBBitCount == 8) {
682 if ((src_pf->dwFlags & DDPF_ALPHAPIXELS) &&
683 (src_pf->u5.dwRGBAlphaBitMask != 0x00)) {
684 error = TRUE;
685 } else {
686 if ((src_pf->u2.dwRBitMask == 0xE0) &&
687 (src_pf->u3.dwGBitMask == 0x1C) &&
688 (src_pf->u4.dwBBitMask == 0x03)) {
689 /* **********************
690 GL_UNSIGNED_BYTE_3_3_2
691 ********************** */
692 if (colorkey_active) {
693 /* This texture format will never be used.. So do not care about color keying
694 up until the point in time it will be needed :-) */
695 FIXME(" ColorKeying not supported in the RGB 332 format !");
697 current_format = GL_RGB;
698 internal_format = GL_RGB;
699 current_pixel_format = GL_UNSIGNED_BYTE_3_3_2;
700 convert_type = NO_CONVERSION;
701 } else {
702 error = TRUE;
705 } else if (src_pf->u1.dwRGBBitCount == 16) {
706 if ((src_pf->dwFlags & DDPF_ALPHAPIXELS) &&
707 (src_pf->u5.dwRGBAlphaBitMask != 0x0000)) {
708 if ((src_pf->u2.dwRBitMask == 0xF800) &&
709 (src_pf->u3.dwGBitMask == 0x07C0) &&
710 (src_pf->u4.dwBBitMask == 0x003E) &&
711 (src_pf->u5.dwRGBAlphaBitMask == 0x0001)) {
712 current_format = GL_RGBA;
713 internal_format = GL_RGBA;
714 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
715 if (colorkey_active) {
716 convert_type = CONVERT_CK_5551;
717 } else {
718 convert_type = NO_CONVERSION;
720 } else if ((src_pf->u2.dwRBitMask == 0xF000) &&
721 (src_pf->u3.dwGBitMask == 0x0F00) &&
722 (src_pf->u4.dwBBitMask == 0x00F0) &&
723 (src_pf->u5.dwRGBAlphaBitMask == 0x000F)) {
724 current_format = GL_RGBA;
725 internal_format = GL_RGBA;
726 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
727 if (colorkey_active) {
728 convert_type = CONVERT_CK_4444;
729 } else {
730 convert_type = NO_CONVERSION;
732 } else if ((src_pf->u2.dwRBitMask == 0x0F00) &&
733 (src_pf->u3.dwGBitMask == 0x00F0) &&
734 (src_pf->u4.dwBBitMask == 0x000F) &&
735 (src_pf->u5.dwRGBAlphaBitMask == 0xF000)) {
736 if (colorkey_active) {
737 convert_type = CONVERT_CK_4444_ARGB;
738 current_format = GL_RGBA;
739 internal_format = GL_RGBA;
740 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4;
741 } else {
742 convert_type = NO_CONVERSION;
743 current_format = GL_BGRA;
744 internal_format = GL_RGBA;
745 current_pixel_format = GL_UNSIGNED_SHORT_4_4_4_4_REV;
747 } else if ((src_pf->u2.dwRBitMask == 0x7C00) &&
748 (src_pf->u3.dwGBitMask == 0x03E0) &&
749 (src_pf->u4.dwBBitMask == 0x001F) &&
750 (src_pf->u5.dwRGBAlphaBitMask == 0x8000)) {
751 if (colorkey_active) {
752 convert_type = CONVERT_CK_1555;
753 current_format = GL_RGBA;
754 internal_format = GL_RGBA;
755 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
756 } else {
757 convert_type = NO_CONVERSION;
758 current_format = GL_BGRA;
759 internal_format = GL_RGBA;
760 current_pixel_format = GL_UNSIGNED_SHORT_1_5_5_5_REV;
762 } else {
763 error = TRUE;
765 } else {
766 if ((src_pf->u2.dwRBitMask == 0xF800) &&
767 (src_pf->u3.dwGBitMask == 0x07E0) &&
768 (src_pf->u4.dwBBitMask == 0x001F)) {
769 if (colorkey_active) {
770 convert_type = CONVERT_CK_565;
771 current_format = GL_RGBA;
772 internal_format = GL_RGBA;
773 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
774 } else {
775 convert_type = NO_CONVERSION;
776 current_format = GL_RGB;
777 internal_format = GL_RGB;
778 current_pixel_format = GL_UNSIGNED_SHORT_5_6_5;
780 } else if ((src_pf->u2.dwRBitMask == 0x7C00) &&
781 (src_pf->u3.dwGBitMask == 0x03E0) &&
782 (src_pf->u4.dwBBitMask == 0x001F)) {
783 convert_type = CONVERT_555;
784 current_format = GL_RGBA;
785 internal_format = GL_RGBA;
786 current_pixel_format = GL_UNSIGNED_SHORT_5_5_5_1;
787 } else {
788 error = TRUE;
791 } else if (src_pf->u1.dwRGBBitCount == 24) {
792 if ((src_pf->dwFlags & DDPF_ALPHAPIXELS) &&
793 (src_pf->u5.dwRGBAlphaBitMask != 0x000000)) {
794 error = TRUE;
795 } else {
796 if ((src_pf->u2.dwRBitMask == 0xFF0000) &&
797 (src_pf->u3.dwGBitMask == 0x00FF00) &&
798 (src_pf->u4.dwBBitMask == 0x0000FF)) {
799 if (colorkey_active) {
800 convert_type = CONVERT_CK_RGB24;
801 current_format = GL_RGBA;
802 internal_format = GL_RGBA;
803 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
804 } else {
805 convert_type = NO_CONVERSION;
806 current_format = GL_BGR;
807 internal_format = GL_RGB;
808 current_pixel_format = GL_UNSIGNED_BYTE;
810 } else {
811 error = TRUE;
814 } else if (src_pf->u1.dwRGBBitCount == 32) {
815 if ((src_pf->dwFlags & DDPF_ALPHAPIXELS) &&
816 (src_pf->u5.dwRGBAlphaBitMask != 0x00000000)) {
817 if ((src_pf->u2.dwRBitMask == 0xFF000000) &&
818 (src_pf->u3.dwGBitMask == 0x00FF0000) &&
819 (src_pf->u4.dwBBitMask == 0x0000FF00) &&
820 (src_pf->u5.dwRGBAlphaBitMask == 0x000000FF)) {
821 if (colorkey_active) {
822 convert_type = CONVERT_CK_8888;
823 } else {
824 convert_type = NO_CONVERSION;
826 current_format = GL_RGBA;
827 internal_format = GL_RGBA;
828 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
829 } else if ((src_pf->u2.dwRBitMask == 0x00FF0000) &&
830 (src_pf->u3.dwGBitMask == 0x0000FF00) &&
831 (src_pf->u4.dwBBitMask == 0x000000FF) &&
832 (src_pf->u5.dwRGBAlphaBitMask == 0xFF000000)) {
833 if (colorkey_active) {
834 convert_type = CONVERT_CK_8888_ARGB;
835 current_format = GL_RGBA;
836 internal_format = GL_RGBA;
837 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
838 } else {
839 convert_type = NO_CONVERSION;
840 current_format = GL_BGRA;
841 internal_format = GL_RGBA;
842 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8_REV;
844 } else {
845 error = TRUE;
847 } else {
848 if ((src_pf->u2.dwRBitMask == 0x00FF0000) &&
849 (src_pf->u3.dwGBitMask == 0x0000FF00) &&
850 (src_pf->u4.dwBBitMask == 0x000000FF)) {
851 if (need_alpha_ck == TRUE) {
852 convert_type = CONVERT_RGB32_888;
853 current_format = GL_RGBA;
854 internal_format = GL_RGBA;
855 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8;
856 } else {
857 convert_type = NO_CONVERSION;
858 current_format = GL_BGRA;
859 internal_format = GL_RGBA;
860 current_pixel_format = GL_UNSIGNED_INT_8_8_8_8_REV;
862 } else {
863 error = TRUE;
866 } else {
867 error = TRUE;
869 } else {
870 error = TRUE;
873 if (error == TRUE) {
874 ERR("Unsupported pixel format for textures : \n");
875 if (ERR_ON(ddraw)) {
876 DDRAW_dump_pixelformat(src_pf);
878 return DDERR_INVALIDPIXELFORMAT;
879 } else {
880 if ((need_to_alloc) ||
881 (internal_format != *current_internal_format)) {
882 glTexImage2D(GL_TEXTURE_2D, level, internal_format,
883 tex_width, tex_height, 0,
884 current_format, current_pixel_format, NULL);
885 *current_internal_format = internal_format;
889 if ((sub_texture == TRUE) && (convert_type == NO_CONVERSION)) {
890 current_storage_width = surf_ptr->surface_desc.u1.lPitch / bpp;
891 } else {
892 if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
893 current_storage_width = 0;
894 } else {
895 current_storage_width = surf_ptr->surface_desc.u1.lPitch / bpp;
898 glPixelStorei(GL_UNPACK_ROW_LENGTH, current_storage_width);
900 return DD_OK;
903 HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, void **temp_buffer)
905 const DDSURFACEDESC * const src_d = (DDSURFACEDESC *)&(current_surface->surface_desc);
906 void *surf_buffer = NULL;
907 RECT lrect;
908 DWORD width, height;
909 BYTE bpp = GET_BPP(current_surface->surface_desc);
910 int line_increase;
912 if (rect == NULL) {
913 lrect.top = 0;
914 lrect.left = 0;
915 lrect.bottom = current_tex_height;
916 lrect.right = current_tex_width;
917 rect = &lrect;
920 width = rect->right - rect->left;
921 height = rect->bottom - rect->top;
923 /* Used when converting stuff */
924 line_increase = src_d->u1.lPitch - (width * bpp);
926 switch (convert_type) {
927 case CONVERT_PALETTED: {
928 IDirectDrawPaletteImpl* pal = current_surface->palette;
929 BYTE table[256][4];
930 int i;
931 int x, y;
932 BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
934 if (pal == NULL) {
935 /* Upload a black texture. The real one will be uploaded on palette change */
936 WARN("Palettized texture Loading with a NULL palette !\n");
937 memset(table, 0, 256 * 4);
938 } else {
939 /* Get the surface's palette */
940 for (i = 0; i < 256; i++) {
941 table[i][0] = pal->palents[i].peRed;
942 table[i][1] = pal->palents[i].peGreen;
943 table[i][2] = pal->palents[i].peBlue;
944 if ((src_d->dwFlags & DDSD_CKSRCBLT) &&
945 (i >= src_d->ddckCKSrcBlt.dwColorSpaceLowValue) &&
946 (i <= src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
947 /* We should maybe here put a more 'neutral' color than the standard bright purple
948 one often used by application to prevent the nice purple borders when bi-linear
949 filtering is on */
950 table[i][3] = 0x00;
951 else
952 table[i][3] = 0xFF;
956 if (*temp_buffer == NULL)
957 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
958 current_tex_width * current_tex_height * sizeof(DWORD));
959 dst = (BYTE *) *temp_buffer;
961 for (y = 0; y < height; y++) {
962 for (x = 0; x < width; x++) {
963 BYTE color = *src++;
964 *dst++ = table[color][0];
965 *dst++ = table[color][1];
966 *dst++ = table[color][2];
967 *dst++ = table[color][3];
969 src += line_increase;
971 } break;
973 case CONVERT_CK_565: {
974 /* Converting the 565 format in 5551 packed to emulate color-keying.
976 Note : in all these conversion, it would be best to average the averaging
977 pixels to get the color of the pixel that will be color-keyed to
978 prevent 'color bleeding'. This will be done later on if ever it is
979 too visible.
981 Note2: when using color-keying + alpha, are the alpha bits part of the
982 color-space or not ?
984 int x, y;
985 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
987 if (*temp_buffer == NULL)
988 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
989 current_tex_width * current_tex_height * sizeof(WORD));
990 dst = (WORD *) *temp_buffer;
992 for (y = 0; y < height; y++) {
993 for (x = 0; x < width; x++) {
994 WORD color = *src++;
995 *dst = ((color & 0xFFD0) | ((color & 0x1F) << 1));
996 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
997 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
998 *dst |= 0x0001;
999 dst++;
1001 src = (WORD *) (((BYTE *) src) + line_increase);
1003 } break;
1005 case CONVERT_CK_5551: {
1006 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
1007 int x, y;
1008 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1010 if (*temp_buffer == NULL)
1011 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1012 current_tex_width * current_tex_height * sizeof(WORD));
1013 dst = (WORD *) *temp_buffer;
1015 for (y = 0; y < height; y++) {
1016 for (x = 0; x < width; x++) {
1017 WORD color = *src++;
1018 *dst = color & 0xFFFE;
1019 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1020 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1021 *dst |= color & 0x0001;
1022 dst++;
1024 src = (WORD *) (((BYTE *) src) + line_increase);
1026 } break;
1028 case CONVERT_CK_4444: {
1029 /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
1030 int x, y;
1031 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1033 if (*temp_buffer == NULL)
1034 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1035 current_tex_width * current_tex_height * sizeof(WORD));
1036 dst = (WORD *) *temp_buffer;
1038 for (y = 0; y < height; y++) {
1039 for (x = 0; x < width; x++) {
1040 WORD color = *src++;
1041 *dst = color & 0xFFF0;
1042 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1043 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1044 *dst |= color & 0x000F;
1045 dst++;
1047 src = (WORD *) (((BYTE *) src) + line_increase);
1049 } break;
1051 case CONVERT_CK_4444_ARGB: {
1052 /* Move the four Alpha bits... */
1053 int x, y;
1054 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1056 if (*temp_buffer == NULL)
1057 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1058 current_tex_width * current_tex_height * sizeof(WORD));
1059 dst = (WORD *) *temp_buffer;
1061 for (y = 0; y < height; y++) {
1062 for (x = 0; x < width; x++) {
1063 WORD color = *src++;
1064 *dst = (color & 0x0FFF) << 4;
1065 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1066 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1067 *dst |= (color & 0xF000) >> 12;
1068 dst++;
1070 src = (WORD *) (((BYTE *) src) + line_increase);
1072 } break;
1074 case CONVERT_CK_1555: {
1075 int x, y;
1076 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1078 if (*temp_buffer == NULL)
1079 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1080 current_tex_width * current_tex_height * sizeof(WORD));
1081 dst = (WORD *) *temp_buffer;
1083 for (y = 0; y < height; y++) {
1084 for (x = 0; x < width; x++) {
1085 WORD color = *src++;
1086 *dst = (color & 0x7FFF) << 1;
1087 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1088 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1089 *dst |= (color & 0x8000) >> 15;
1090 dst++;
1092 src = (WORD *) (((BYTE *) src) + line_increase);
1094 } break;
1096 case CONVERT_555: {
1097 /* Converting the 0555 format in 5551 packed */
1098 int x, y;
1099 WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1101 if (*temp_buffer == NULL)
1102 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1103 current_tex_width * current_tex_height * sizeof(WORD));
1104 dst = (WORD *) *temp_buffer;
1106 if (src_d->dwFlags & DDSD_CKSRCBLT) {
1107 for (y = 0; y < height; y++) {
1108 for (x = 0; x < width; x++) {
1109 WORD color = *src++;
1110 *dst = (color & 0x7FFF) << 1;
1111 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1112 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1113 *dst |= 0x0001;
1114 dst++;
1116 src = (WORD *) (((BYTE *) src) + line_increase);
1118 } else {
1119 for (y = 0; y < height; y++) {
1120 for (x = 0; x < width; x++) {
1121 WORD color = *src++;
1122 *dst++ = ((color & 0x7FFF) << 1) | 0x0001;
1124 src = (WORD *) (((BYTE *) src) + line_increase);
1128 } break;
1130 case CONVERT_CK_RGB24: {
1131 /* This is a pain :-) */
1132 int x, y;
1133 BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
1134 DWORD *dst;
1136 if (*temp_buffer == NULL)
1137 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1138 current_tex_width * current_tex_height * sizeof(DWORD));
1139 dst = (DWORD *) *temp_buffer;
1141 for (y = 0; y < height; y++) {
1142 for (x = 0; x < width; x++) {
1143 DWORD color = *((DWORD *) src) & 0x00FFFFFF;
1144 src += 3;
1145 *dst = *src++ << 8;
1146 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1147 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1148 *dst |= 0xFF;
1149 dst++;
1151 src += line_increase;
1153 } break;
1155 case CONVERT_CK_8888: {
1156 /* Just use the alpha component to handle color-keying... */
1157 int x, y;
1158 DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1160 if (*temp_buffer == NULL)
1161 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1162 current_tex_width * current_tex_height * sizeof(DWORD));
1163 dst = (DWORD *) *temp_buffer;
1165 for (y = 0; y < height; y++) {
1166 for (x = 0; x < width; x++) {
1167 DWORD color = *src++;
1168 *dst = color & 0xFFFFFF00;
1169 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1170 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1171 *dst |= color & 0x000000FF;
1172 dst++;
1174 src = (DWORD *) (((BYTE *) src) + line_increase);
1176 } break;
1178 case CONVERT_CK_8888_ARGB: {
1179 int x, y;
1180 DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1182 if (*temp_buffer == NULL)
1183 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1184 current_tex_width * current_tex_height * sizeof(DWORD));
1185 dst = (DWORD *) *temp_buffer;
1187 for (y = 0; y < height; y++) {
1188 for (x = 0; x < width; x++) {
1189 DWORD color = *src++;
1190 *dst = (color & 0x00FFFFFF) << 8;
1191 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1192 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1193 *dst |= (color & 0xFF000000) >> 24;
1194 dst++;
1196 src = (DWORD *) (((BYTE *) src) + line_increase);
1198 } break;
1200 case CONVERT_RGB32_888: {
1201 /* Just add an alpha component and handle color-keying... */
1202 int x, y;
1203 DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
1205 if (*temp_buffer == NULL)
1206 *temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1207 current_tex_width * current_tex_height * sizeof(DWORD));
1208 dst = (DWORD *) *temp_buffer;
1210 if (src_d->dwFlags & DDSD_CKSRCBLT) {
1211 for (y = 0; y < height; y++) {
1212 for (x = 0; x < width; x++) {
1213 DWORD color = *src++;
1214 *dst = color << 8;
1215 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1216 (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1217 *dst |= 0xFF;
1218 dst++;
1220 src = (DWORD *) (((BYTE *) src) + line_increase);
1222 } else {
1223 for (y = 0; y < height; y++) {
1224 for (x = 0; x < width; x++) {
1225 *dst++ = (*src++ << 8) | 0xFF;
1227 src = (DWORD *) (((BYTE *) src) + line_increase);
1230 } break;
1232 case NO_CONVERSION:
1233 /* Nothing to do here as the name suggests... Just set-up the buffer correctly */
1234 surf_buffer = (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
1235 break;
1238 if (convert_type != NO_CONVERSION) {
1239 /* When doing conversion, the storage is always of width 'width' as there will never
1240 be any Pitch issue... For now :-)
1242 surf_buffer = *temp_buffer;
1243 if (width != current_storage_width) {
1244 glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1245 current_storage_width = width;
1249 glTexSubImage2D(GL_TEXTURE_2D,
1250 current_level,
1251 xoffset, yoffset,
1252 width, height,
1253 current_format,
1254 current_pixel_format,
1255 surf_buffer);
1257 return DD_OK;
1260 HRESULT upload_surface_to_tex_memory_release(void)
1262 current_surface = NULL;
1264 return DD_OK;