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