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