- some clean-ups (extension code to be added soon)
[wine] / dlls / ddraw / mesa.c
1 /* Direct3D Common functions
2  * Copyright (c) 1998 Lionel ULMER
3  *
4  * This file contains all MESA common code
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
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"
30
31 #include "mesa_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
34
35 GLenum convert_D3D_compare_to_GL(D3DCMPFUNC dwRenderState)
36 {
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);
47     }
48     return GL_ALWAYS;
49 }
50
51 GLenum convert_D3D_stencilop_to_GL(D3DSTENCILOP dwRenderState)
52 {
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);      
63     }
64     return GL_KEEP;
65 }
66
67 GLenum convert_D3D_blendop_to_GL(D3DBLEND dwRenderState)
68 {
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;
82     }
83 }
84
85 void set_render_state(IDirect3DDeviceImpl* This,
86                       D3DRENDERSTATETYPE dwRenderStateType, STATEBLOCK *lpStateBlock)
87 {
88     DWORD dwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
89     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
90     
91     if (TRACE_ON(ddraw))
92         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
93
94     /* First, all the stipple patterns */
95     if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
96         (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
97         ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
98     } else {
99         ENTER_GL();
100
101         /* All others state variables */
102         switch (dwRenderStateType) {
103             case D3DRENDERSTATE_TEXTUREHANDLE: {    /*  1 */
104                 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
105                 
106                 IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
107                                             0, 
108                                             ICOM_INTERFACE(tex, IDirectDrawSurface7));
109             } break;
110               
111             case D3DRENDERSTATE_TEXTUREADDRESSU:  /* 44 */
112             case D3DRENDERSTATE_TEXTUREADDRESSV:  /* 45 */
113             case D3DRENDERSTATE_TEXTUREADDRESS: { /*  3 */
114                 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType;
115
116                 if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) d3dTexStageStateType = D3DTSS_ADDRESS;
117                 else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) d3dTexStageStateType = D3DTSS_ADDRESSU;
118                 else d3dTexStageStateType = D3DTSS_ADDRESSV;
119
120                 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
121                                                       0, d3dTexStageStateType,
122                                                       dwRenderState);
123             } break;
124               
125             case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
126                 if (dwRenderState)
127                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
128                 else
129                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
130                 break;
131
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 */
142                 if (dwRenderState)
143                     ERR("Texture WRAP modes unsupported by OpenGL.. Expect graphical glitches !\n");
144                 break;
145
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.
149                    
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);
155                 else {
156                     glEnable(GL_DEPTH_TEST);
157                     WARN(" w-buffering not supported.\n");
158                 }
159                 break;
160
161             case D3DRENDERSTATE_FILLMODE:           /*  8 */
162                 switch ((D3DFILLMODE) dwRenderState) {
163                     case D3DFILL_POINT:
164                         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);        
165                         break;
166                     case D3DFILL_WIREFRAME:
167                         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
168                         break;
169                     case D3DFILL_SOLID:
170                         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
171                         break;
172                     default:
173                         ERR("Unhandled fill mode %ld !\n",dwRenderState);
174                  }
175                  break;
176
177             case D3DRENDERSTATE_SHADEMODE:          /*  9 */
178                 switch ((D3DSHADEMODE) dwRenderState) {
179                     case D3DSHADE_FLAT:
180                         glShadeModel(GL_FLAT);
181                         break;
182                     case D3DSHADE_GOURAUD:
183                         glShadeModel(GL_SMOOTH);
184                         break;
185                     default:
186                         ERR("Unhandled shade mode %ld !\n",dwRenderState);
187                 }
188                 break;
189
190             case D3DRENDERSTATE_ZWRITEENABLE:     /* 14 */
191                 if (dwRenderState)
192                     glDepthMask(GL_TRUE);
193                 else
194                     glDepthMask(GL_FALSE);
195                 break;
196               
197             case D3DRENDERSTATE_ALPHATESTENABLE:  /* 15 */
198                 if (dwRenderState)
199                     glEnable(GL_ALPHA_TEST);
200                 else
201                     glDisable(GL_ALPHA_TEST);
202                 break;
203
204             case D3DRENDERSTATE_TEXTUREMAG: {     /* 17 */
205                 DWORD tex_mag = 0xFFFFFFFF;
206
207                 switch ((D3DTEXTUREFILTER) dwRenderState) {
208                     case D3DFILTER_NEAREST:
209                         tex_mag = D3DTFG_POINT;
210                         break;
211                     case D3DFILTER_LINEAR:
212                         tex_mag = D3DTFG_LINEAR;
213                         break;
214                     default:
215                         ERR("Unhandled texture mag %ld !\n",dwRenderState);
216                 }
217
218                 if (tex_mag != 0xFFFFFFFF) {
219                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag);
220                 }
221             } break;
222
223             case D3DRENDERSTATE_TEXTUREMIN: {       /* 18 */
224                 DWORD tex_min = 0xFFFFFFFF;
225
226                 switch ((D3DTEXTUREFILTER) dwRenderState) {
227                     case D3DFILTER_NEAREST:
228                         tex_min = D3DTFN_POINT;
229                         break;
230                     case D3DFILTER_LINEAR:
231                         tex_min = D3DTFN_LINEAR;
232                         break;
233                     default:
234                         ERR("Unhandled texture min %ld !\n",dwRenderState);
235                 }
236
237                 if (tex_min != 0xFFFFFFFF) {
238                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min);
239                 }
240             } break;
241
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]));
246                 break;
247
248             case D3DRENDERSTATE_TEXTUREMAPBLEND:    /* 21 */
249                 switch ((D3DTEXTUREBLEND) dwRenderState) {
250                     case D3DTBLEND_DECAL:
251                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
252                         break;
253                     case D3DTBLEND_MODULATE:
254                     case D3DTBLEND_MODULATEALPHA:
255                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
256                         break;
257                     default:
258                         ERR("Unhandled texture environment %ld !\n",dwRenderState);
259                 }
260                 break;
261
262             case D3DRENDERSTATE_CULLMODE:           /* 22 */
263                 switch ((D3DCULL) dwRenderState) {
264                     case D3DCULL_NONE:
265                          glDisable(GL_CULL_FACE);
266                          break;
267                     case D3DCULL_CW:
268                          glEnable(GL_CULL_FACE);
269                          glFrontFace(GL_CCW);
270                          glCullFace(GL_BACK);
271                          break;
272                     case D3DCULL_CCW:
273                          glEnable(GL_CULL_FACE);
274                          glFrontFace(GL_CW);
275                          glCullFace(GL_BACK);
276                          break;
277                     default:
278                          ERR("Unhandled cull mode %ld !\n",dwRenderState);
279                 }
280                 break;
281
282             case D3DRENDERSTATE_ZFUNC:            /* 23 */
283                 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
284                 break;
285               
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);
290                 break;
291
292             case D3DRENDERSTATE_DITHERENABLE:     /* 26 */
293                 if (dwRenderState)
294                     glEnable(GL_DITHER);
295                 else
296                     glDisable(GL_DITHER);
297                 break;
298
299             case D3DRENDERSTATE_ALPHABLENDENABLE:   /* 27 */
300                 if (dwRenderState) {
301                     glEnable(GL_BLEND);
302                 } else {
303                     glDisable(GL_BLEND);
304                 }
305                 break;
306               
307             case D3DRENDERSTATE_FOGENABLE: /* 28 */
308                 /* Nothing to do here. Only the storage matters :-) */
309                 break;
310
311             case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
312                 if (dwRenderState)
313                     ERR(" Specular Lighting not supported yet.\n");
314                 break;
315               
316             case D3DRENDERSTATE_SUBPIXEL:  /* 31 */
317             case D3DRENDERSTATE_SUBPIXELX: /* 32 */
318                 /* We do not support this anyway, so why protest :-) */
319                 break; 
320
321             case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
322                 if (dwRenderState)
323                     ERR(" Stippled Alpha not supported yet.\n");
324                 break;
325
326             case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
327                 GLfloat color[4];
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 */
334             } break;
335
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 :-) */
341                 break;
342
343             case D3DRENDERSTATE_FOGDENSITY:    /* 38 */
344                 glFogi(GL_FOG_DENSITY,*(float*)&dwRenderState);
345                 break;
346
347             case D3DRENDERSTATE_COLORKEYENABLE:     /* 41 */
348                 /* This needs to be fixed. */
349                 if (dwRenderState)
350                     glEnable(GL_BLEND);
351                 else
352                     glDisable(GL_BLEND);
353                 break;
354
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);
361                 } else {
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);
366                 }
367                 break;
368               
369             case D3DRENDERSTATE_FLUSHBATCH:         /* 50 */
370                 break;
371
372             case D3DRENDERSTATE_STENCILENABLE:    /* 52 */
373                 if (dwRenderState)
374                     glEnable(GL_STENCIL_TEST);
375                 else
376                     glDisable(GL_STENCIL_TEST);
377                 break;
378             
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]));
385                 break;
386
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]);
393                 break;
394           
395             case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
396                 glStencilMask(dwRenderState);
397                 break;
398
399             case D3DRENDERSTATE_TEXTUREFACTOR:      /* 60 */
400                 /* Only the storage matters... */
401                 break;
402
403             case D3DRENDERSTATE_CLIPPING:          /* 136 */
404             case D3DRENDERSTATE_CLIPPLANEENABLE: { /* 152 */
405                     GLint i;
406                     DWORD mask, runner;
407                     
408                     if (dwRenderStateType == D3DRENDERSTATE_CLIPPING) {
409                         mask = ((dwRenderState) ?
410                                 (This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) : (0x00000000));
411                     } else {
412                         mask = dwRenderState;
413                     }
414                     for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner = (runner << 1)) {
415                         if (mask & runner) {
416                             GLint enabled;
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
421                                  * properly to GL.
422                                  */
423                                 glThis->transform_state = GL_TRANSFORM_NONE;
424                             }
425                         } else {
426                             glDisable(GL_CLIP_PLANE0 + i);
427                         }
428                     }
429                 }
430                 break;
431
432             case D3DRENDERSTATE_LIGHTING:    /* 137 */
433                 if (dwRenderState)
434                     glEnable(GL_LIGHTING);
435                 else
436                     glDisable(GL_LIGHTING);
437                 break;
438                 
439             case D3DRENDERSTATE_AMBIENT: {            /* 139 */
440                 float light[4];
441
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);
447             } break;
448
449             case D3DRENDERSTATE_COLORVERTEX:          /* 141 */
450                   /* Nothing to do here.. Only storage matters */
451                   break;
452                   
453             case D3DRENDERSTATE_LOCALVIEWER:          /* 142 */
454                 if (dwRenderState)
455                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
456                 else
457                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
458                 break;
459
460             case D3DRENDERSTATE_NORMALIZENORMALS:     /* 143 */
461                 if (dwRenderState) {
462                     glEnable(GL_NORMALIZE);
463                     glEnable(GL_RESCALE_NORMAL);
464                 } else {
465                     glDisable(GL_NORMALIZE);
466                     glDisable(GL_RESCALE_NORMAL);
467                 }
468                 break;
469
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 :-) */
475                 break;
476
477             default:
478                 ERR("Unhandled dwRenderStateType %s (%08x) value : %08lx !\n",
479                     _get_renderstate(dwRenderStateType), dwRenderStateType, dwRenderState);
480         }
481         LEAVE_GL();
482     }
483 }
484
485 void store_render_state(IDirect3DDeviceImpl *This,
486                         D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, STATEBLOCK *lpStateBlock)
487 {
488     TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
489     
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;
495             return;
496         } else if (dwRenderState == D3DBLEND_BOTHINVSRCALPHA) {
497             lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_INVSRCALPHA;
498             lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_INVSRCALPHA;
499             return;
500         }
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) {
505         if (dwRenderState) 
506             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_U;
507         else
508             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
509     } else if (dwRenderStateType == D3DRENDERSTATE_WRAPV) {
510         if (dwRenderState) 
511             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_V;
512         else
513             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
514     }
515     
516     /* Default case */
517     lpStateBlock->render_state[dwRenderStateType - 1] = dwRenderState;
518 }
519
520 void get_render_state(IDirect3DDeviceImpl *This,
521                       D3DRENDERSTATETYPE dwRenderStateType, LPDWORD lpdwRenderState, STATEBLOCK *lpStateBlock)
522 {
523     *lpdwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
524     if (TRACE_ON(ddraw))
525         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
526 }
527
528 void apply_render_state(IDirect3DDeviceImpl *This, STATEBLOCK *lpStateBlock)
529 {
530     DWORD i;
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);
535 }
536
537
538 /* Texture management code.
539
540     - upload_surface_to_tex_memory_init initialize the code and computes the GL formats 
541       according to the surface description.
542
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.
546
547     - upload_surface_to_tex_memory_release does the clean-up.
548
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
552       engine.
553     - use of the texture engine to simulate Blits to the 3D Device.
554 */
555 typedef enum {
556     NO_CONVERSION,
557     CONVERT_PALETTED,
558     CONVERT_CK_565,
559     CONVERT_CK_5551,
560     CONVERT_CK_4444,
561     CONVERT_CK_4444_ARGB,
562     CONVERT_CK_1555,
563     CONVERT_555,
564     CONVERT_CK_RGB24,
565     CONVERT_CK_8888,
566     CONVERT_CK_8888_ARGB,
567     CONVERT_RGB32_888
568 } CONVERT_TYPES;
569
570 /* Note : we suppose that all the code calling this is protected by the GL lock... Otherwise bad things
571    may happen :-) */
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;
577
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)
580 {
581     const DDPIXELFORMAT * const src_pf = &(surf_ptr->surface_desc.u4.ddpfPixelFormat);
582     BOOL error = FALSE;
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);
586
587     current_surface = surf_ptr;
588     current_level = level;
589
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");
593     }
594
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);
598     } else {
599         if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
600             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
601         } else {
602             glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
603         }
604         tex_width = surf_ptr->surface_desc.dwWidth;
605         tex_height = surf_ptr->surface_desc.dwHeight;
606     }
607
608     if (src_pf->dwFlags & DDPF_PALETTEINDEXED8) {
609         /* ****************
610            Paletted Texture
611            **************** */
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) {
617         /* ************
618            RGB Textures
619            ************ */
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 !");
631                 }
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;
636             } else {
637                 error = TRUE;
638             }
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;
649                 } else {
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;
654                 }
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;
664                 } else {
665                     convert_type = NO_CONVERSION;
666                 }
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;
676                 } else {
677                     convert_type = NO_CONVERSION;
678                 }
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;
688                 } else {
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;
693                 }
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;
703                 } else {
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;
708                 }
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;
717             } else {
718                 error = TRUE;
719             }
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;
730                 } else {
731                     convert_type = NO_CONVERSION;
732                     current_format = GL_BGR;
733                     internal_format = GL_RGB;
734                     current_pixel_format = GL_UNSIGNED_BYTE;
735                 }
736             } else {
737                 error = TRUE;
738             }
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;
746                 } else {
747                     convert_type = NO_CONVERSION;
748                 }
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;
761                 } else {
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;
766                 }
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)) {
771                 if (need_alpha_ck) {
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;
776                 } else {
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;
781                 }
782             } else {
783                 error = TRUE;
784             }
785         } else {
786             error = TRUE;
787         }
788     } else {
789         error = TRUE;
790     } 
791
792     if (error == TRUE) {
793         if (ERR_ON(ddraw)) {
794             ERR("  unsupported pixel format for textures : \n");
795             DDRAW_dump_pixelformat(src_pf);
796         }
797         return DDERR_INVALIDPIXELFORMAT;
798     } else {
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;
805         }
806     }
807
808     return DD_OK;
809 }
810
811 HRESULT upload_surface_to_tex_memory(RECT *rect, void **temp_buffer)
812 {
813     const DDSURFACEDESC * const src_d = (DDSURFACEDESC *)&(current_surface->surface_desc);
814     void *surf_buffer = NULL;
815
816     switch (convert_type) {
817         case CONVERT_PALETTED: {
818             IDirectDrawPaletteImpl* pal = current_surface->palette;
819             BYTE table[256][4];
820             int i;
821             BYTE *src = (BYTE *) src_d->lpSurface, *dst;
822                     
823             if (pal == NULL) {
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);
827             } else {
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
838                            filtering is on */
839                         table[i][3] = 0x00;
840                     else
841                         table[i][3] = 0xFF;
842                 }
843             }
844             
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;
849             
850             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
851                 BYTE color = *src++;
852                 *dst++ = table[color][0];
853                 *dst++ = table[color][1];
854                 *dst++ = table[color][2];
855                 *dst++ = table[color][3];
856             }
857         } break;
858
859         case CONVERT_CK_565: {
860             /* Converting the 565 format in 5551 packed to emulate color-keying.
861                
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
865                       too visible.
866                       
867                Note2: when using color-keying + alpha, are the alpha bits part of the
868                       color-space or not ?
869             */
870             DWORD i;
871             WORD *src = (WORD *) src_d->lpSurface, *dst;
872             
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;
877             
878             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
879                 WORD color = *src++;
880                 *dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
881                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
882                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
883                     *dst |= 0x0001;
884                 dst++;
885             }
886         } break;
887         
888         case CONVERT_CK_5551: {
889             /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
890             DWORD i;
891             WORD *src = (WORD *) src_d->lpSurface, *dst;
892             
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;
897             
898             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
899                 WORD color = *src++;
900                 *dst = color & 0xFFFE;
901                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
902                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
903                     *dst |= color & 0x0001;
904                 dst++;
905             }
906         } break;
907         
908         case CONVERT_CK_4444: {
909             /* Change the alpha value of the color-keyed pixels to emulate color-keying. */
910             DWORD i;
911             WORD *src = (WORD *) src_d->lpSurface, *dst;
912             
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;
917             
918             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
919                 WORD color = *src++;
920                 *dst = color & 0xFFF0;
921                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
922                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
923                     *dst |= color & 0x000F;
924                 dst++;
925             }
926         } break;
927         
928         case CONVERT_CK_4444_ARGB: {
929             /* Move the four Alpha bits... */
930             DWORD i;
931             WORD *src = (WORD *) src_d->lpSurface, *dst;
932             
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;
937             
938             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
939                 WORD color = *src++;
940                 *dst = (color & 0x0FFF) << 4;
941                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
942                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
943                     *dst |= (color & 0xF000) >> 12;
944                 dst++;
945             }
946         } break;
947         
948         case CONVERT_CK_1555: {
949             DWORD i;
950             WORD *src = (WORD *) src_d->lpSurface, *dst;
951             
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;
956             
957             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
958                 WORD color = *src++;
959                 *dst = (color & 0x7FFF) << 1;
960                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
961                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
962                     *dst |= (color & 0x8000) >> 15;
963                 dst++;
964             }
965         } break;
966         
967         case CONVERT_555: {
968             /* Converting the 0555 format in 5551 packed */
969             DWORD i;
970             WORD *src = (WORD *) src_d->lpSurface, *dst;
971             
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;
976             
977             if (src_d->dwFlags & DDSD_CKSRCBLT) {
978                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
979                     WORD color = *src++;
980                     *dst = (color & 0x7FFF) << 1;
981                     if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
982                         (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
983                         *dst |= 0x0001;
984                     dst++;
985                 }
986             } else {
987                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
988                     WORD color = *src++;
989                     *dst++ = ((color & 0x7FFF) << 1) | 0x0001;
990                 }
991             }
992             
993         } break;
994         
995         case CONVERT_CK_RGB24: {
996             /* This is a pain :-) */
997             DWORD i;
998             BYTE *src = (BYTE *) src_d->lpSurface;
999             DWORD *dst;
1000             
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;
1005
1006             for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1007                 DWORD color = *((DWORD *) src) & 0x00FFFFFF;
1008                 src += 3;
1009                 *dst = *src++ << 8;
1010                 if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1011                     (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1012                     *dst |= 0xFF;
1013                 dst++;
1014             }
1015         } break;
1016
1017         case CONVERT_CK_8888: {
1018             /* Just use the alpha component to handle color-keying... */
1019             DWORD i;
1020             DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1021             
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;
1026             
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;
1033                 dst++;
1034             }
1035         } break;
1036         
1037         case CONVERT_CK_8888_ARGB: {
1038             DWORD i;
1039             DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1040             
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;
1045             
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;
1052                 dst++;
1053             }
1054         } break;
1055         
1056         case CONVERT_RGB32_888: {
1057             /* Just add an alpha component and handle color-keying... */
1058             DWORD i;
1059             DWORD *src = (DWORD *) src_d->lpSurface, *dst;
1060             
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;
1065             
1066             if (src_d->dwFlags & DDSD_CKSRCBLT) {
1067                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1068                     DWORD color = *src++;
1069                     *dst = color << 8;
1070                     if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
1071                         (color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
1072                         *dst |= 0xFF;
1073                     dst++;
1074                 }
1075             } else {
1076                 for (i = 0; i < src_d->dwHeight * src_d->dwWidth; i++) {
1077                     *dst++ = (*src++ << 8) | 0xFF;
1078                 }
1079             }
1080         } break;
1081
1082         case NO_CONVERSION:
1083             /* Nothing to do here as the name suggests... This just prevents a compiler warning */
1084             surf_buffer = src_d->lpSurface;
1085             break;
1086     }
1087
1088     if (convert_type != NO_CONVERSION) {
1089         surf_buffer = *temp_buffer;
1090     }
1091     
1092     glTexSubImage2D(GL_TEXTURE_2D,
1093                     current_level,
1094                     0, 0,
1095                     src_d->dwWidth, src_d->dwHeight,
1096                     current_format,
1097                     current_pixel_format,
1098                     surf_buffer);
1099
1100     return DD_OK;
1101 }
1102
1103 HRESULT upload_surface_to_tex_memory_release(void)
1104 {
1105     current_surface = NULL;
1106
1107     return DD_OK;
1108 }