Handle more blend states.
[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
50 void set_render_state(D3DRENDERSTATETYPE dwRenderStateType,
51                       DWORD dwRenderState, RenderState *rs)
52 {
53     if (TRACE_ON(ddraw))
54         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
55
56     /* First, all the stipple patterns */
57     if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
58         (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
59         ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
60     } else {
61         ENTER_GL();
62
63         /* All others state variables */
64         switch (dwRenderStateType) {
65             case D3DRENDERSTATE_TEXTUREHANDLE: {    /*  1 */
66                 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
67                 
68                 if (tex == NULL) {
69                     glBindTexture(GL_TEXTURE_2D, 0);
70                     glDisable(GL_TEXTURE_2D);
71                     TRACE("disabling texturing\n");
72                 } else {
73                     IDirect3DTextureGLImpl *gl_tex = (IDirect3DTextureGLImpl *) tex->tex_private;
74                     
75                     glEnable(GL_TEXTURE_2D);
76                     /* Default parameters */
77                     glBindTexture(GL_TEXTURE_2D, gl_tex->tex_name);
78                     /* To prevent state change, we could test here what are the parameters
79                        stored in the texture */
80                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, rs->mag);
81                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, rs->min);
82                     TRACE("setting OpenGL texture handle : %d\n", gl_tex->tex_name);
83                 }
84             } break;
85
86               
87             case D3DRENDERSTATE_TEXTUREADDRESSU:  /* 44 */
88             case D3DRENDERSTATE_TEXTUREADDRESSV:  /* 45 */
89             case D3DRENDERSTATE_TEXTUREADDRESS: { /*  3 */
90                 GLenum arg = GL_REPEAT; /* Default value */
91                 switch ((D3DTEXTUREADDRESS) dwRenderState) {
92                     case D3DTADDRESS_WRAP:   arg = GL_REPEAT; break;
93                     case D3DTADDRESS_CLAMP:  arg = GL_CLAMP; break;
94                     case D3DTADDRESS_BORDER: arg = GL_CLAMP_TO_EDGE; break;
95                     default: ERR("Unhandled TEXTUREADDRESS mode %ld !\n", dwRenderState);
96                 }
97                 if ((dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSU) ||
98                     (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS))
99                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
100                 if ((dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESSV) ||
101                     (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS))
102                     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
103             } break;
104               
105             case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
106                 if (dwRenderState)
107                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
108                 else
109                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
110                 break;
111
112             case D3DRENDERSTATE_WRAPU: /* 5 */
113                 if (dwRenderState)
114                     ERR("WRAPU mode unsupported by OpenGL.. Expect graphical glitches !\n");
115                 break;
116               
117             case D3DRENDERSTATE_WRAPV: /* 6 */
118                 if (dwRenderState)
119                     ERR("WRAPV mode unsupported by OpenGL.. Expect graphical glitches !\n");
120                 break;
121
122             case D3DRENDERSTATE_ZENABLE:          /*  7 */
123                 if (dwRenderState)
124                     glEnable(GL_DEPTH_TEST);
125                 else
126                     glDisable(GL_DEPTH_TEST);
127                 break;
128
129             case D3DRENDERSTATE_FILLMODE:           /*  8 */
130                 switch ((D3DFILLMODE) dwRenderState) {
131                     case D3DFILL_POINT:
132                         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);        
133                         break;
134                     case D3DFILL_WIREFRAME:
135                         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
136                         break;
137                     case D3DFILL_SOLID:
138                         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
139                         break;
140                     default:
141                         ERR("Unhandled fill mode %ld !\n",dwRenderState);
142                  }
143                  break;
144
145             case D3DRENDERSTATE_SHADEMODE:          /*  9 */
146                 switch ((D3DSHADEMODE) dwRenderState) {
147                     case D3DSHADE_FLAT:
148                         glShadeModel(GL_FLAT);
149                         break;
150                     case D3DSHADE_GOURAUD:
151                         glShadeModel(GL_SMOOTH);
152                         break;
153                     default:
154                         ERR("Unhandled shade mode %ld !\n",dwRenderState);
155                 }
156                 break;
157
158             case D3DRENDERSTATE_ZWRITEENABLE:     /* 14 */
159                 if (dwRenderState)
160                     glDepthMask(GL_TRUE);
161                 else
162                     glDepthMask(GL_FALSE);
163                 break;
164               
165             case D3DRENDERSTATE_ALPHATESTENABLE:  /* 15 */
166                 if (dwRenderState)
167                     glEnable(GL_ALPHA_TEST);
168                 else
169                     glDisable(GL_ALPHA_TEST);
170                 break;
171
172             case D3DRENDERSTATE_TEXTUREMAG:       /* 17 */
173                 switch ((D3DTEXTUREFILTER) dwRenderState) {
174                     case D3DFILTER_NEAREST:
175                         rs->mag = GL_NEAREST;
176                         break;
177                     case D3DFILTER_LINEAR:
178                         rs->mag = GL_LINEAR;
179                         break;
180                     default:
181                         ERR("Unhandled texture mag %ld !\n",dwRenderState);
182                 }
183                 break;
184
185             case D3DRENDERSTATE_TEXTUREMIN:         /* 18 */
186                 switch ((D3DTEXTUREFILTER) dwRenderState) {
187                     case D3DFILTER_NEAREST:
188                         rs->min = GL_NEAREST;
189                         break;
190                     case D3DFILTER_LINEAR:
191                         rs->mag = GL_LINEAR;
192                         break;
193                     default:
194                         ERR("Unhandled texture min %ld !\n",dwRenderState);
195                 }
196                 break;
197
198             case D3DRENDERSTATE_SRCBLEND:           /* 19 */
199                 switch ((D3DBLEND) dwRenderState) {
200                     case D3DBLEND_ZERO:
201                           rs->src = GL_ZERO;
202                           break;
203                     case D3DBLEND_ONE:
204                           rs->src = GL_ONE;
205                           break;
206                     case D3DBLEND_SRCALPHA:
207                           rs->src = GL_SRC_ALPHA;
208                           break;
209                     case D3DBLEND_INVSRCALPHA:
210                           rs->src = GL_ONE_MINUS_SRC_ALPHA;
211                           break;
212                     case D3DBLEND_DESTALPHA:
213                           rs->src = GL_DST_ALPHA;
214                           break;
215                     case D3DBLEND_INVDESTALPHA:
216                           rs->src = GL_ONE_MINUS_DST_ALPHA;
217                           break;
218                     case D3DBLEND_DESTCOLOR:
219                           rs->src = GL_DST_COLOR;
220                           break;
221                     case D3DBLEND_INVDESTCOLOR:
222                           rs->src = GL_ONE_MINUS_DST_COLOR;
223                           break;
224                     case D3DBLEND_SRCCOLOR:
225                     case D3DBLEND_INVSRCCOLOR:
226                           /* Cannot be supported with OpenGL */
227                           break;
228                     default:
229                           ERR("Unhandled src blend mode %ld !\n",dwRenderState);
230                 }
231                 glBlendFunc(rs->src, rs->dst);
232                 break;
233
234             case D3DRENDERSTATE_DESTBLEND:          /* 20 */
235                 switch ((D3DBLEND) dwRenderState) {
236                     case D3DBLEND_ZERO:
237                         rs->dst = GL_ZERO;
238                         break;
239                     case D3DBLEND_ONE:
240                         rs->dst = GL_ONE;
241                         break;
242                     case D3DBLEND_SRCCOLOR:
243                         rs->dst = GL_SRC_COLOR;
244                         break;
245                     case D3DBLEND_INVSRCCOLOR:
246                         rs->dst = GL_ONE_MINUS_SRC_COLOR;
247                         break;
248                     case D3DBLEND_SRCALPHA:
249                         rs->dst = GL_SRC_ALPHA;
250                         break;
251                     case D3DBLEND_INVSRCALPHA:
252                         rs->dst = GL_ONE_MINUS_SRC_ALPHA;
253                         break;
254                     case D3DBLEND_DESTALPHA:
255                         rs->dst = GL_DST_ALPHA;
256                         break;
257                     case D3DBLEND_INVDESTALPHA:
258                         rs->dst = GL_ONE_MINUS_DST_ALPHA;
259                         break;
260                     case D3DBLEND_DESTCOLOR:
261                     case D3DBLEND_INVDESTCOLOR:
262                         /* Cannot be supported with OpenGL */
263                         break;
264                     default:
265                         ERR("Unhandled dest blend mode %ld !\n",dwRenderState);
266                 }
267                 glBlendFunc(rs->src, rs->dst);
268                 break;
269
270             case D3DRENDERSTATE_TEXTUREMAPBLEND:    /* 21 */
271                 switch ((D3DTEXTUREBLEND) dwRenderState) {
272                     case D3DTBLEND_MODULATE:
273                     case D3DTBLEND_MODULATEALPHA:
274                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
275                         break;
276                     default:
277                           ERR("Unhandled texture environment %ld !\n",dwRenderState);
278                 }
279                 break;
280
281             case D3DRENDERSTATE_CULLMODE:           /* 22 */
282                 switch ((D3DCULL) dwRenderState) {
283                     case D3DCULL_NONE:
284                          glDisable(GL_CULL_FACE);
285                          break;
286                          /* Not sure about these... The DirectX doc is, well, pretty unclear :-) */
287                     case D3DCULL_CW:
288                          glEnable(GL_CULL_FACE);
289                          glFrontFace(GL_CW);
290                          glCullFace(GL_BACK);
291                          break;
292                     case D3DCULL_CCW:
293                          glEnable(GL_CULL_FACE);
294                          glFrontFace(GL_CCW);
295                          glCullFace(GL_BACK);
296                          break;
297                     default:
298                          ERR("Unhandled cull mode %ld !\n",dwRenderState);
299                 }
300                 break;
301
302             case D3DRENDERSTATE_ZFUNC:            /* 23 */
303                 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
304                 break;
305               
306             case D3DRENDERSTATE_ALPHAREF:   /* 24 */
307                 rs->alpha_ref = dwRenderState / 255.0;
308                 glAlphaFunc(rs->alpha_func, rs->alpha_ref);
309                 break;
310               
311             case D3DRENDERSTATE_ALPHAFUNC: /* 25 */
312                 rs->alpha_func = convert_D3D_compare_to_GL(dwRenderState);
313                 glAlphaFunc(rs->alpha_func, rs->alpha_ref);
314                 break;
315
316             case D3DRENDERSTATE_DITHERENABLE:     /* 26 */
317                 if (dwRenderState)
318                     glEnable(GL_DITHER);
319                 else
320                     glDisable(GL_DITHER);
321                 break;
322
323             case D3DRENDERSTATE_ALPHABLENDENABLE:   /* 27 */
324                 if (dwRenderState) {
325                     glEnable(GL_BLEND);
326                     rs->alpha_blend_enable = TRUE;
327                 } else {
328                     glDisable(GL_BLEND);
329                     rs->alpha_blend_enable = FALSE;
330                 }
331                 break;
332               
333             case D3DRENDERSTATE_FOGENABLE: /* 28 */
334                 if (dwRenderState) {
335                     glEnable(GL_FOG);
336                     rs->fog_on = TRUE;
337                 } else {
338                     glDisable(GL_FOG);
339                     rs->fog_on = FALSE;
340                 }
341                 break;
342
343             case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
344                 if (dwRenderState)
345                     ERR(" Specular Lighting not supported yet.\n");
346                 break;
347               
348             case D3DRENDERSTATE_SUBPIXEL:  /* 31 */
349             case D3DRENDERSTATE_SUBPIXELX: /* 32 */
350                 /* We do not support this anyway, so why protest :-) */
351                 break;
352
353             case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
354                 if (dwRenderState)
355                     ERR(" Stippled Alpha not supported yet.\n");
356                 break;
357
358             case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
359                 GLint color[4];
360                 color[0] = (dwRenderState >> 16) & 0xFF;
361                 color[1] = (dwRenderState >>  8) & 0xFF;
362                 color[2] = (dwRenderState >>  0) & 0xFF;
363                 color[3] = (dwRenderState >> 24) & 0xFF;
364                 glFogiv(GL_FOG_COLOR, color);
365             } break;
366
367               
368             case D3DRENDERSTATE_COLORKEYENABLE:     /* 41 */
369                 if (dwRenderState)
370                     glEnable(GL_BLEND);
371                 else
372                     glDisable(GL_BLEND);
373                 break;
374
375             case D3DRENDERSTATE_ZBIAS: /* 47 */
376                 /* This is a tad bit hacky.. But well, no idea how to do it better in OpenGL :-/ */
377                 if (dwRenderState == 0) {
378                     glDisable(GL_POLYGON_OFFSET_FILL);
379                     glDisable(GL_POLYGON_OFFSET_LINE);
380                     glDisable(GL_POLYGON_OFFSET_POINT);
381                 } else {
382                     glEnable(GL_POLYGON_OFFSET_FILL);
383                     glEnable(GL_POLYGON_OFFSET_LINE);
384                     glEnable(GL_POLYGON_OFFSET_POINT);
385                     glPolygonOffset(1.0, dwRenderState * 1.0);
386                 }
387                 break;
388               
389             case D3DRENDERSTATE_FLUSHBATCH:         /* 50 */
390                 break;
391
392             case D3DRENDERSTATE_LIGHTING:    /* 137 */
393                 /* There will be more to do here once we really support D3D7 Lighting.
394                    Should be enough for now to prevent warnings :-) */
395                 if (dwRenderState)
396                     glEnable(GL_LIGHTING);
397                 else
398                     glDisable(GL_LIGHTING);
399                 break;
400
401             default:
402                 ERR("Unhandled dwRenderStateType %s (%08x) !\n", _get_renderstate(dwRenderStateType), dwRenderStateType);
403         }
404         LEAVE_GL();
405     }
406 }