ok() does not support '%S'. Store the Ansi version, convert to Unicode
[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 "windef.h"
24 #include "objbase.h"
25 #include "ddraw.h"
26 #include "d3d.h"
27 #include "wine/debug.h"
28
29 #include "mesa_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
32
33 GLenum convert_D3D_compare_to_GL(D3DCMPFUNC dwRenderState)
34 {
35     switch (dwRenderState) {
36         case D3DCMP_NEVER: return GL_NEVER;
37         case D3DCMP_LESS: return GL_LESS;
38         case D3DCMP_EQUAL: return GL_EQUAL;
39         case D3DCMP_LESSEQUAL: return GL_LEQUAL;
40         case D3DCMP_GREATER: return GL_GREATER;
41         case D3DCMP_NOTEQUAL: return GL_NOTEQUAL;
42         case D3DCMP_GREATEREQUAL: return GL_GEQUAL;
43         case D3DCMP_ALWAYS: return GL_ALWAYS;
44         default: ERR("Unexpected compare type %d !\n", dwRenderState);
45     }
46     return GL_ALWAYS;
47 }
48
49 GLenum convert_D3D_stencilop_to_GL(D3DSTENCILOP dwRenderState)
50 {
51     switch (dwRenderState) {
52         case D3DSTENCILOP_KEEP: return GL_KEEP;
53         case D3DSTENCILOP_ZERO: return GL_ZERO;
54         case D3DSTENCILOP_REPLACE: return GL_REPLACE;
55         case D3DSTENCILOP_INCRSAT: return GL_INCR;
56         case D3DSTENCILOP_DECRSAT: return GL_DECR;
57         case D3DSTENCILOP_INVERT: return GL_INVERT;
58         case D3DSTENCILOP_INCR: WARN("D3DSTENCILOP_INCR not properly handled !\n"); return GL_INCR;
59         case D3DSTENCILOP_DECR: WARN("D3DSTENCILOP_DECR not properly handled !\n"); return GL_DECR;
60         default: ERR("Unexpected compare type %d !\n", dwRenderState);      
61     }
62     return GL_KEEP;
63 }
64
65 GLenum convert_D3D_blendop_to_GL(D3DBLEND dwRenderState)
66 {
67     switch ((D3DBLEND) dwRenderState) {
68         case D3DBLEND_ZERO: return GL_ZERO;
69         case D3DBLEND_ONE: return GL_ONE;
70         case D3DBLEND_SRCALPHA: return GL_SRC_ALPHA;
71         case D3DBLEND_INVSRCALPHA: return GL_ONE_MINUS_SRC_ALPHA;
72         case D3DBLEND_DESTALPHA: return GL_DST_ALPHA;
73         case D3DBLEND_INVDESTALPHA: return GL_ONE_MINUS_DST_ALPHA;
74         case D3DBLEND_DESTCOLOR: return GL_DST_COLOR;
75         case D3DBLEND_INVDESTCOLOR: return GL_ONE_MINUS_DST_COLOR;
76         case D3DBLEND_SRCALPHASAT: return GL_SRC_ALPHA_SATURATE;
77         case D3DBLEND_SRCCOLOR: return GL_SRC_COLOR;
78         case D3DBLEND_INVSRCCOLOR: return GL_ONE_MINUS_SRC_COLOR;
79         default: ERR("Unhandled blend mode %d !\n", dwRenderState); return GL_ZERO;
80     }
81 }
82
83 void set_render_state(IDirect3DDeviceImpl* This,
84                       D3DRENDERSTATETYPE dwRenderStateType, STATEBLOCK *lpStateBlock)
85 {
86     IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
87     DWORD dwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
88
89     if (TRACE_ON(ddraw))
90         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
91
92     /* First, all the stipple patterns */
93     if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
94         (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
95         ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
96     } else {
97         ENTER_GL();
98
99         /* All others state variables */
100         switch (dwRenderStateType) {
101             case D3DRENDERSTATE_TEXTUREHANDLE: {    /*  1 */
102                 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
103                 
104                 LEAVE_GL();
105                 IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
106                                             0, 
107                                             ICOM_INTERFACE(tex, IDirectDrawSurface7));
108                 ENTER_GL();
109             } break;
110               
111             case D3DRENDERSTATE_TEXTUREADDRESSU:  /* 44 */
112             case D3DRENDERSTATE_TEXTUREADDRESSV:  /* 45 */
113             case D3DRENDERSTATE_TEXTUREADDRESS: { /*  3 */
114                 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType;
115
116                 if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) d3dTexStageStateType = D3DTSS_ADDRESS;
117                 else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) d3dTexStageStateType = D3DTSS_ADDRESSU;
118                 else d3dTexStageStateType = D3DTSS_ADDRESSV;
119
120                 LEAVE_GL();
121                 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
122                                                       0, d3dTexStageStateType,
123                                                       dwRenderState);
124                 ENTER_GL();
125             } break;
126               
127             case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
128                 if (dwRenderState)
129                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
130                 else
131                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
132                 break;
133
134             case D3DRENDERSTATE_WRAPU: /* 5 */
135                 if (dwRenderState)
136                     ERR("WRAPU mode unsupported by OpenGL.. Expect graphical glitches !\n");
137                 break;
138               
139             case D3DRENDERSTATE_WRAPV: /* 6 */
140                 if (dwRenderState)
141                     ERR("WRAPV mode unsupported by OpenGL.. Expect graphical glitches !\n");
142                 break;
143
144             case D3DRENDERSTATE_ZENABLE:          /*  7 */
145                 /* To investigate : in OpenGL, if we disable the depth test, the Z buffer will NOT be
146                    updated either.. No idea about what happens in D3D.
147                    
148                    Maybe replacing the Z function by ALWAYS would be a better idea. */
149                 if (dwRenderState == D3DZB_TRUE)
150                     glEnable(GL_DEPTH_TEST);
151                 else if (dwRenderState == D3DZB_FALSE)
152                     glDisable(GL_DEPTH_TEST);
153                 else {
154                     glEnable(GL_DEPTH_TEST);
155                     WARN(" w-buffering not supported.\n");
156                 }
157                 break;
158
159             case D3DRENDERSTATE_FILLMODE:           /*  8 */
160                 switch ((D3DFILLMODE) dwRenderState) {
161                     case D3DFILL_POINT:
162                         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);        
163                         break;
164                     case D3DFILL_WIREFRAME:
165                         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
166                         break;
167                     case D3DFILL_SOLID:
168                         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
169                         break;
170                     default:
171                         ERR("Unhandled fill mode %ld !\n",dwRenderState);
172                  }
173                  break;
174
175             case D3DRENDERSTATE_SHADEMODE:          /*  9 */
176                 switch ((D3DSHADEMODE) dwRenderState) {
177                     case D3DSHADE_FLAT:
178                         glShadeModel(GL_FLAT);
179                         break;
180                     case D3DSHADE_GOURAUD:
181                         glShadeModel(GL_SMOOTH);
182                         break;
183                     default:
184                         ERR("Unhandled shade mode %ld !\n",dwRenderState);
185                 }
186                 break;
187
188             case D3DRENDERSTATE_ZWRITEENABLE:     /* 14 */
189                 if (dwRenderState)
190                     glDepthMask(GL_TRUE);
191                 else
192                     glDepthMask(GL_FALSE);
193                 break;
194               
195             case D3DRENDERSTATE_ALPHATESTENABLE:  /* 15 */
196                 if (dwRenderState)
197                     glEnable(GL_ALPHA_TEST);
198                 else
199                     glDisable(GL_ALPHA_TEST);
200                 break;
201
202             case D3DRENDERSTATE_TEXTUREMAG: {     /* 17 */
203                 DWORD tex_mag = 0xFFFFFFFF;
204
205                 switch ((D3DTEXTUREFILTER) dwRenderState) {
206                     case D3DFILTER_NEAREST:
207                         tex_mag = D3DTFG_POINT;
208                         break;
209                     case D3DFILTER_LINEAR:
210                         tex_mag = D3DTFG_LINEAR;
211                         break;
212                     default:
213                         ERR("Unhandled texture mag %ld !\n",dwRenderState);
214                 }
215
216                 if (tex_mag != 0xFFFFFFFF) {
217                     LEAVE_GL();
218                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag);
219                     ENTER_GL();
220                 }
221             } break;
222
223             case D3DRENDERSTATE_TEXTUREMIN: {       /* 18 */
224                 DWORD tex_min = 0xFFFFFFFF;
225
226                 switch ((D3DTEXTUREFILTER) dwRenderState) {
227                     case D3DFILTER_NEAREST:
228                         tex_min = D3DTFN_POINT;
229                         break;
230                     case D3DFILTER_LINEAR:
231                         tex_min = D3DTFN_LINEAR;
232                         break;
233                     default:
234                         ERR("Unhandled texture min %ld !\n",dwRenderState);
235                 }
236
237                 if (tex_min != 0xFFFFFFFF) {
238                     LEAVE_GL();
239                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min);
240                     ENTER_GL();
241                 }
242             } break;
243
244             case D3DRENDERSTATE_SRCBLEND:           /* 19 */
245             case D3DRENDERSTATE_DESTBLEND:          /* 20 */
246                 glBlendFunc(convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1]),
247                             convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1]));
248                 break;
249
250             case D3DRENDERSTATE_TEXTUREMAPBLEND:    /* 21 */
251                 switch ((D3DTEXTUREBLEND) dwRenderState) {
252                     case D3DTBLEND_MODULATE:
253                     case D3DTBLEND_MODULATEALPHA:
254                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
255                         break;
256                     default:
257                         ERR("Unhandled texture environment %ld !\n",dwRenderState);
258                 }
259                 break;
260
261             case D3DRENDERSTATE_CULLMODE:           /* 22 */
262                 switch ((D3DCULL) dwRenderState) {
263                     case D3DCULL_NONE:
264                          glDisable(GL_CULL_FACE);
265                          break;
266                     case D3DCULL_CW:
267                          glEnable(GL_CULL_FACE);
268                          glFrontFace(GL_CCW);
269                          glCullFace(GL_BACK);
270                          break;
271                     case D3DCULL_CCW:
272                          glEnable(GL_CULL_FACE);
273                          glFrontFace(GL_CW);
274                          glCullFace(GL_BACK);
275                          break;
276                     default:
277                          ERR("Unhandled cull mode %ld !\n",dwRenderState);
278                 }
279                 break;
280
281             case D3DRENDERSTATE_ZFUNC:            /* 23 */
282                 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
283                 break;
284               
285             case D3DRENDERSTATE_ALPHAREF:   /* 24 */
286             case D3DRENDERSTATE_ALPHAFUNC:  /* 25 */
287                 glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
288                             (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
289                 break;
290
291             case D3DRENDERSTATE_DITHERENABLE:     /* 26 */
292                 if (dwRenderState)
293                     glEnable(GL_DITHER);
294                 else
295                     glDisable(GL_DITHER);
296                 break;
297
298             case D3DRENDERSTATE_ALPHABLENDENABLE:   /* 27 */
299                 if (dwRenderState) {
300                     glEnable(GL_BLEND);
301                 } else {
302                     glDisable(GL_BLEND);
303                 }
304                 break;
305               
306             case D3DRENDERSTATE_FOGENABLE: /* 28 */
307                 if ((dwRenderState == TRUE) &&
308                     (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
309                     glEnable(GL_FOG);
310                 } else {
311                     glDisable(GL_FOG);
312                 }
313                 break;
314
315             case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
316                 if (dwRenderState)
317                     ERR(" Specular Lighting not supported yet.\n");
318                 break;
319               
320             case D3DRENDERSTATE_SUBPIXEL:  /* 31 */
321             case D3DRENDERSTATE_SUBPIXELX: /* 32 */
322                 /* We do not support this anyway, so why protest :-) */
323                 break;
324
325             case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
326                 if (dwRenderState)
327                     ERR(" Stippled Alpha not supported yet.\n");
328                 break;
329
330             case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
331                 GLint color[4];
332                 color[0] = (dwRenderState >> 16) & 0xFF;
333                 color[1] = (dwRenderState >>  8) & 0xFF;
334                 color[2] = (dwRenderState >>  0) & 0xFF;
335                 color[3] = (dwRenderState >> 24) & 0xFF;
336                 glFogiv(GL_FOG_COLOR, color);
337             } break;
338
339               
340             case D3DRENDERSTATE_COLORKEYENABLE:     /* 41 */
341                 /* This needs to be fixed. */
342                 if (dwRenderState)
343                     glEnable(GL_BLEND);
344                 else
345                     glDisable(GL_BLEND);
346                 break;
347
348             case D3DRENDERSTATE_ZBIAS: /* 47 */
349                 /* This is a tad bit hacky.. But well, no idea how to do it better in OpenGL :-/ */
350                 if (dwRenderState == 0) {
351                     glDisable(GL_POLYGON_OFFSET_FILL);
352                     glDisable(GL_POLYGON_OFFSET_LINE);
353                     glDisable(GL_POLYGON_OFFSET_POINT);
354                 } else {
355                     glEnable(GL_POLYGON_OFFSET_FILL);
356                     glEnable(GL_POLYGON_OFFSET_LINE);
357                     glEnable(GL_POLYGON_OFFSET_POINT);
358                     glPolygonOffset(1.0, dwRenderState * 1.0);
359                 }
360                 break;
361               
362             case D3DRENDERSTATE_FLUSHBATCH:         /* 50 */
363                 break;
364
365             case D3DRENDERSTATE_STENCILENABLE:    /* 52 */
366                 if (dwRenderState)
367                     glEnable(GL_STENCIL_TEST);
368                 else
369                     glDisable(GL_STENCIL_TEST);
370                 break;
371             
372             case D3DRENDERSTATE_STENCILFAIL:      /* 53 */
373             case D3DRENDERSTATE_STENCILZFAIL:     /* 54 */
374             case D3DRENDERSTATE_STENCILPASS:      /* 55 */
375                 glStencilOp(convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFAIL - 1]),
376                             convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILZFAIL - 1]),
377                             convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILPASS - 1]));
378                 break;
379
380             case D3DRENDERSTATE_STENCILFUNC:      /* 56 */
381             case D3DRENDERSTATE_STENCILREF:       /* 57 */
382             case D3DRENDERSTATE_STENCILMASK:      /* 58 */
383                 glStencilFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFUNC - 1]),
384                               lpStateBlock->render_state[D3DRENDERSTATE_STENCILREF - 1],
385                               lpStateBlock->render_state[D3DRENDERSTATE_STENCILMASK - 1]);
386                 break;
387           
388             case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
389                 glStencilMask(dwRenderState);
390                 break;
391
392             case D3DRENDERSTATE_CLIPPING:          /* 136 */
393             case D3DRENDERSTATE_CLIPPLANEENABLE: { /* 152 */
394                     GLint i;
395                     DWORD mask, runner;
396                     
397                     if (dwRenderStateType == D3DRENDERSTATE_CLIPPING) {
398                         mask = ((dwRenderState) ?
399                                 (This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) : (0x0000));
400                     } else {
401                         mask = dwRenderState;
402                     }
403                     for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner = (runner << 1)) {
404                         if (mask & runner) {
405                             glEnable(GL_CLIP_PLANE0 + i);
406                         } else {
407                             glDisable(GL_CLIP_PLANE0 + i);
408                         }
409                     }
410                 }
411                 break;
412
413             case D3DRENDERSTATE_LIGHTING:    /* 137 */
414                 if (dwRenderState)
415                     glEnable(GL_LIGHTING);
416                 else
417                     glDisable(GL_LIGHTING);
418                 break;
419                 
420             case D3DRENDERSTATE_AMBIENT: {            /* 139 */
421                 float light[4];
422
423                 light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0;
424                 light[1] = ((dwRenderState >>  8) & 0xFF) / 255.0;
425                 light[2] = ((dwRenderState >>  0) & 0xFF) / 255.0;
426                 light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0;
427                 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
428             } break;
429
430             case D3DRENDERSTATE_LOCALVIEWER:          /* 142 */
431                 if (dwRenderState)
432                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
433                 else
434                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
435                 break;
436
437             case D3DRENDERSTATE_NORMALIZENORMALS:     /* 143 */
438                 if (dwRenderState) {
439                     glEnable(GL_NORMALIZE);
440                     glEnable(GL_RESCALE_NORMAL);
441                 } else {
442                     glDisable(GL_NORMALIZE);
443                     glDisable(GL_RESCALE_NORMAL);
444                 }
445                 break;
446
447             case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE:    /* 145 */
448             case D3DRENDERSTATE_SPECULARMATERIALSOURCE:   /* 146 */
449             case D3DRENDERSTATE_AMBIENTMATERIALSOURCE:    /* 147 */
450             case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE:   /* 148 */
451                 /* Nothing to do here. Only the storage matters :-) */
452                 break;
453
454             default:
455                 ERR("Unhandled dwRenderStateType %s (%08x) !\n", _get_renderstate(dwRenderStateType), dwRenderStateType);
456         }
457         LEAVE_GL();
458     }
459 }
460
461 void store_render_state(IDirect3DDeviceImpl *This,
462                         D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, STATEBLOCK *lpStateBlock)
463 {
464     TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
465     
466     /* Some special cases first.. */
467     if (dwRenderStateType == D3DRENDERSTATE_SRCBLEND) {
468         if (dwRenderState == D3DBLEND_BOTHSRCALPHA) {
469             lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_SRCALPHA;
470             lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_SRCALPHA;
471             return;
472         } else if (dwRenderState == D3DBLEND_BOTHINVSRCALPHA) {
473             lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_INVSRCALPHA;
474             lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_INVSRCALPHA;
475             return;
476         }
477     } else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) {
478         lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSU - 1] = dwRenderState;
479         lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSV - 1] = dwRenderState;
480     }
481     
482     /* Default case */
483     lpStateBlock->render_state[dwRenderStateType - 1] = dwRenderState;
484 }
485
486 void get_render_state(IDirect3DDeviceImpl *This,
487                       D3DRENDERSTATETYPE dwRenderStateType, LPDWORD lpdwRenderState, STATEBLOCK *lpStateBlock)
488 {
489     *lpdwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
490     if (TRACE_ON(ddraw))
491         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
492 }
493
494 void apply_render_state(IDirect3DDeviceImpl *This, STATEBLOCK *lpStateBlock)
495 {
496     DWORD i;
497     TRACE("(%p,%p)\n", This, lpStateBlock);
498     for(i = 0; i < HIGHEST_RENDER_STATE; i++)
499         if (lpStateBlock->set_flags.render_state[i])
500             set_render_state(This, i + 1, lpStateBlock);
501 }