- implement the TFACTOR texture stage state
[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     DWORD dwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
87
88     if (TRACE_ON(ddraw))
89         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
90
91     /* First, all the stipple patterns */
92     if ((dwRenderStateType >= D3DRENDERSTATE_STIPPLEPATTERN00) &&
93         (dwRenderStateType <= D3DRENDERSTATE_STIPPLEPATTERN31)) {
94         ERR("Unhandled dwRenderStateType stipple %d!\n",dwRenderStateType);
95     } else {
96         ENTER_GL();
97
98         /* All others state variables */
99         switch (dwRenderStateType) {
100             case D3DRENDERSTATE_TEXTUREHANDLE: {    /*  1 */
101                 IDirectDrawSurfaceImpl *tex = (IDirectDrawSurfaceImpl*) dwRenderState;
102                 
103                 LEAVE_GL();
104                 IDirect3DDevice7_SetTexture(ICOM_INTERFACE(This, IDirect3DDevice7),
105                                             0, 
106                                             ICOM_INTERFACE(tex, IDirectDrawSurface7));
107                 ENTER_GL();
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                 LEAVE_GL();
120                 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
121                                                       0, d3dTexStageStateType,
122                                                       dwRenderState);
123                 ENTER_GL();
124             } break;
125               
126             case D3DRENDERSTATE_TEXTUREPERSPECTIVE: /* 4 */
127                 if (dwRenderState)
128                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
129                 else
130                     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
131                 break;
132
133             case D3DRENDERSTATE_WRAPU: /* 5 */
134             case D3DRENDERSTATE_WRAPV: /* 6 */
135             case D3DRENDERSTATE_WRAP0: /* 128 */
136             case D3DRENDERSTATE_WRAP1: /* 129 */
137             case D3DRENDERSTATE_WRAP2: /* 130 */
138             case D3DRENDERSTATE_WRAP3: /* 131 */
139             case D3DRENDERSTATE_WRAP4: /* 132 */
140             case D3DRENDERSTATE_WRAP5: /* 133 */
141             case D3DRENDERSTATE_WRAP6: /* 134 */
142             case D3DRENDERSTATE_WRAP7: /* 135 */
143                 if (dwRenderState)
144                     ERR("Texture WRAP modes unsupported by OpenGL.. Expect graphical glitches !\n");
145                 break;
146
147             case D3DRENDERSTATE_ZENABLE:          /*  7 */
148                 /* To investigate : in OpenGL, if we disable the depth test, the Z buffer will NOT be
149                    updated either.. No idea about what happens in D3D.
150                    
151                    Maybe replacing the Z function by ALWAYS would be a better idea. */
152                 if (dwRenderState == D3DZB_TRUE)
153                     glEnable(GL_DEPTH_TEST);
154                 else if (dwRenderState == D3DZB_FALSE)
155                     glDisable(GL_DEPTH_TEST);
156                 else {
157                     glEnable(GL_DEPTH_TEST);
158                     WARN(" w-buffering not supported.\n");
159                 }
160                 break;
161
162             case D3DRENDERSTATE_FILLMODE:           /*  8 */
163                 switch ((D3DFILLMODE) dwRenderState) {
164                     case D3DFILL_POINT:
165                         glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);        
166                         break;
167                     case D3DFILL_WIREFRAME:
168                         glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
169                         break;
170                     case D3DFILL_SOLID:
171                         glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
172                         break;
173                     default:
174                         ERR("Unhandled fill mode %ld !\n",dwRenderState);
175                  }
176                  break;
177
178             case D3DRENDERSTATE_SHADEMODE:          /*  9 */
179                 switch ((D3DSHADEMODE) dwRenderState) {
180                     case D3DSHADE_FLAT:
181                         glShadeModel(GL_FLAT);
182                         break;
183                     case D3DSHADE_GOURAUD:
184                         glShadeModel(GL_SMOOTH);
185                         break;
186                     default:
187                         ERR("Unhandled shade mode %ld !\n",dwRenderState);
188                 }
189                 break;
190
191             case D3DRENDERSTATE_ZWRITEENABLE:     /* 14 */
192                 if (dwRenderState)
193                     glDepthMask(GL_TRUE);
194                 else
195                     glDepthMask(GL_FALSE);
196                 break;
197               
198             case D3DRENDERSTATE_ALPHATESTENABLE:  /* 15 */
199                 if (dwRenderState)
200                     glEnable(GL_ALPHA_TEST);
201                 else
202                     glDisable(GL_ALPHA_TEST);
203                 break;
204
205             case D3DRENDERSTATE_TEXTUREMAG: {     /* 17 */
206                 DWORD tex_mag = 0xFFFFFFFF;
207
208                 switch ((D3DTEXTUREFILTER) dwRenderState) {
209                     case D3DFILTER_NEAREST:
210                         tex_mag = D3DTFG_POINT;
211                         break;
212                     case D3DFILTER_LINEAR:
213                         tex_mag = D3DTFG_LINEAR;
214                         break;
215                     default:
216                         ERR("Unhandled texture mag %ld !\n",dwRenderState);
217                 }
218
219                 if (tex_mag != 0xFFFFFFFF) {
220                     LEAVE_GL();
221                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MAGFILTER, tex_mag);
222                     ENTER_GL();
223                 }
224             } break;
225
226             case D3DRENDERSTATE_TEXTUREMIN: {       /* 18 */
227                 DWORD tex_min = 0xFFFFFFFF;
228
229                 switch ((D3DTEXTUREFILTER) dwRenderState) {
230                     case D3DFILTER_NEAREST:
231                         tex_min = D3DTFN_POINT;
232                         break;
233                     case D3DFILTER_LINEAR:
234                         tex_min = D3DTFN_LINEAR;
235                         break;
236                     default:
237                         ERR("Unhandled texture min %ld !\n",dwRenderState);
238                 }
239
240                 if (tex_min != 0xFFFFFFFF) {
241                     LEAVE_GL();
242                     IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7), 0, D3DTSS_MINFILTER, tex_min);
243                     ENTER_GL();
244                 }
245             } break;
246
247             case D3DRENDERSTATE_SRCBLEND:           /* 19 */
248             case D3DRENDERSTATE_DESTBLEND:          /* 20 */
249                 glBlendFunc(convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1]),
250                             convert_D3D_blendop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1]));
251                 break;
252
253             case D3DRENDERSTATE_TEXTUREMAPBLEND:    /* 21 */
254                 switch ((D3DTEXTUREBLEND) dwRenderState) {
255                     case D3DTBLEND_MODULATE:
256                     case D3DTBLEND_MODULATEALPHA:
257                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
258                         break;
259                     default:
260                         ERR("Unhandled texture environment %ld !\n",dwRenderState);
261                 }
262                 break;
263
264             case D3DRENDERSTATE_CULLMODE:           /* 22 */
265                 switch ((D3DCULL) dwRenderState) {
266                     case D3DCULL_NONE:
267                          glDisable(GL_CULL_FACE);
268                          break;
269                     case D3DCULL_CW:
270                          glEnable(GL_CULL_FACE);
271                          glFrontFace(GL_CCW);
272                          glCullFace(GL_BACK);
273                          break;
274                     case D3DCULL_CCW:
275                          glEnable(GL_CULL_FACE);
276                          glFrontFace(GL_CW);
277                          glCullFace(GL_BACK);
278                          break;
279                     default:
280                          ERR("Unhandled cull mode %ld !\n",dwRenderState);
281                 }
282                 break;
283
284             case D3DRENDERSTATE_ZFUNC:            /* 23 */
285                 glDepthFunc(convert_D3D_compare_to_GL(dwRenderState));
286                 break;
287               
288             case D3DRENDERSTATE_ALPHAREF:   /* 24 */
289             case D3DRENDERSTATE_ALPHAFUNC:  /* 25 */
290                 glAlphaFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
291                             (lpStateBlock->render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
292                 break;
293
294             case D3DRENDERSTATE_DITHERENABLE:     /* 26 */
295                 if (dwRenderState)
296                     glEnable(GL_DITHER);
297                 else
298                     glDisable(GL_DITHER);
299                 break;
300
301             case D3DRENDERSTATE_ALPHABLENDENABLE:   /* 27 */
302                 if (dwRenderState) {
303                     glEnable(GL_BLEND);
304                 } else {
305                     glDisable(GL_BLEND);
306                 }
307                 break;
308               
309             case D3DRENDERSTATE_FOGENABLE: /* 28 */
310                 /* Nothing to do here. Only the storage matters :-) */
311                 break;
312
313             case D3DRENDERSTATE_SPECULARENABLE: /* 29 */
314                 if (dwRenderState)
315                     ERR(" Specular Lighting not supported yet.\n");
316                 break;
317               
318             case D3DRENDERSTATE_SUBPIXEL:  /* 31 */
319             case D3DRENDERSTATE_SUBPIXELX: /* 32 */
320                 /* We do not support this anyway, so why protest :-) */
321                 break; 
322
323             case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */
324                 if (dwRenderState)
325                     ERR(" Stippled Alpha not supported yet.\n");
326                 break;
327
328             case D3DRENDERSTATE_FOGCOLOR: { /* 34 */
329                 GLfloat color[4];
330                 color[0] = ((dwRenderState >> 16) & 0xFF)/255.0f;
331                 color[1] = ((dwRenderState >>  8) & 0xFF)/255.0f;
332                 color[2] = ((dwRenderState >>  0) & 0xFF)/255.0f;
333                 color[3] = ((dwRenderState >> 24) & 0xFF)/255.0f;
334                 glFogfv(GL_FOG_COLOR,color);
335                 /* Note: glFogiv does not seem to work */
336             } break;
337
338             case D3DRENDERSTATE_FOGTABLEMODE:  /* 35 */
339             case D3DRENDERSTATE_FOGVERTEXMODE: /* 140 */
340             case D3DRENDERSTATE_FOGSTART:      /* 36 */
341             case D3DRENDERSTATE_FOGEND:        /* 37 */
342                 /* Nothing to do here. Only the storage matters :-) */
343                 break;
344
345             case D3DRENDERSTATE_FOGDENSITY:    /* 38 */
346                 glFogi(GL_FOG_DENSITY,*(float*)&dwRenderState);
347                 break;
348
349             case D3DRENDERSTATE_COLORKEYENABLE:     /* 41 */
350                 /* This needs to be fixed. */
351                 if (dwRenderState)
352                     glEnable(GL_BLEND);
353                 else
354                     glDisable(GL_BLEND);
355                 break;
356
357             case D3DRENDERSTATE_ZBIAS: /* 47 */
358                 /* This is a tad bit hacky.. But well, no idea how to do it better in OpenGL :-/ */
359                 if (dwRenderState == 0) {
360                     glDisable(GL_POLYGON_OFFSET_FILL);
361                     glDisable(GL_POLYGON_OFFSET_LINE);
362                     glDisable(GL_POLYGON_OFFSET_POINT);
363                 } else {
364                     glEnable(GL_POLYGON_OFFSET_FILL);
365                     glEnable(GL_POLYGON_OFFSET_LINE);
366                     glEnable(GL_POLYGON_OFFSET_POINT);
367                     glPolygonOffset(1.0, dwRenderState * 1.0);
368                 }
369                 break;
370               
371             case D3DRENDERSTATE_FLUSHBATCH:         /* 50 */
372                 break;
373
374             case D3DRENDERSTATE_STENCILENABLE:    /* 52 */
375                 if (dwRenderState)
376                     glEnable(GL_STENCIL_TEST);
377                 else
378                     glDisable(GL_STENCIL_TEST);
379                 break;
380             
381             case D3DRENDERSTATE_STENCILFAIL:      /* 53 */
382             case D3DRENDERSTATE_STENCILZFAIL:     /* 54 */
383             case D3DRENDERSTATE_STENCILPASS:      /* 55 */
384                 glStencilOp(convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFAIL - 1]),
385                             convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILZFAIL - 1]),
386                             convert_D3D_stencilop_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILPASS - 1]));
387                 break;
388
389             case D3DRENDERSTATE_STENCILFUNC:      /* 56 */
390             case D3DRENDERSTATE_STENCILREF:       /* 57 */
391             case D3DRENDERSTATE_STENCILMASK:      /* 58 */
392                 glStencilFunc(convert_D3D_compare_to_GL(lpStateBlock->render_state[D3DRENDERSTATE_STENCILFUNC - 1]),
393                               lpStateBlock->render_state[D3DRENDERSTATE_STENCILREF - 1],
394                               lpStateBlock->render_state[D3DRENDERSTATE_STENCILMASK - 1]);
395                 break;
396           
397             case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
398                 glStencilMask(dwRenderState);
399                 break;
400
401             case D3DRENDERSTATE_TEXTUREFACTOR:      /* 60 */
402                 /* Only the storage matters... */
403                 break;
404
405             case D3DRENDERSTATE_CLIPPING:          /* 136 */
406             case D3DRENDERSTATE_CLIPPLANEENABLE: { /* 152 */
407                     GLint i;
408                     DWORD mask, runner;
409                     
410                     if (dwRenderStateType == D3DRENDERSTATE_CLIPPING) {
411                         mask = ((dwRenderState) ?
412                                 (This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) : (0x0000));
413                     } else {
414                         mask = dwRenderState;
415                     }
416                     for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner = (runner << 1)) {
417                         if (mask & runner) {
418                             glEnable(GL_CLIP_PLANE0 + i);
419                         } else {
420                             glDisable(GL_CLIP_PLANE0 + i);
421                         }
422                     }
423                 }
424                 break;
425
426             case D3DRENDERSTATE_LIGHTING:    /* 137 */
427                 if (dwRenderState)
428                     glEnable(GL_LIGHTING);
429                 else
430                     glDisable(GL_LIGHTING);
431                 break;
432                 
433             case D3DRENDERSTATE_AMBIENT: {            /* 139 */
434                 float light[4];
435
436                 light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0;
437                 light[1] = ((dwRenderState >>  8) & 0xFF) / 255.0;
438                 light[2] = ((dwRenderState >>  0) & 0xFF) / 255.0;
439                 light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0;
440                 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
441             } break;
442
443             case D3DRENDERSTATE_COLORVERTEX:          /* 141 */
444                   /* Nothing to do here.. Only storage matters */
445                   break;
446                   
447             case D3DRENDERSTATE_LOCALVIEWER:          /* 142 */
448                 if (dwRenderState)
449                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
450                 else
451                     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
452                 break;
453
454             case D3DRENDERSTATE_NORMALIZENORMALS:     /* 143 */
455                 if (dwRenderState) {
456                     glEnable(GL_NORMALIZE);
457                     glEnable(GL_RESCALE_NORMAL);
458                 } else {
459                     glDisable(GL_NORMALIZE);
460                     glDisable(GL_RESCALE_NORMAL);
461                 }
462                 break;
463
464             case D3DRENDERSTATE_DIFFUSEMATERIALSOURCE:    /* 145 */
465             case D3DRENDERSTATE_SPECULARMATERIALSOURCE:   /* 146 */
466             case D3DRENDERSTATE_AMBIENTMATERIALSOURCE:    /* 147 */
467             case D3DRENDERSTATE_EMISSIVEMATERIALSOURCE:   /* 148 */
468                 /* Nothing to do here. Only the storage matters :-) */
469                 break;
470
471             default:
472                 ERR("Unhandled dwRenderStateType %s (%08x) value : %08lx !\n",
473                     _get_renderstate(dwRenderStateType), dwRenderStateType, dwRenderState);
474         }
475         LEAVE_GL();
476     }
477 }
478
479 void store_render_state(IDirect3DDeviceImpl *This,
480                         D3DRENDERSTATETYPE dwRenderStateType, DWORD dwRenderState, STATEBLOCK *lpStateBlock)
481 {
482     TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), dwRenderState);
483     
484     /* Some special cases first.. */
485     if (dwRenderStateType == D3DRENDERSTATE_SRCBLEND) {
486         if (dwRenderState == D3DBLEND_BOTHSRCALPHA) {
487             lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_SRCALPHA;
488             lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_SRCALPHA;
489             return;
490         } else if (dwRenderState == D3DBLEND_BOTHINVSRCALPHA) {
491             lpStateBlock->render_state[D3DRENDERSTATE_SRCBLEND - 1] = D3DBLEND_INVSRCALPHA;
492             lpStateBlock->render_state[D3DRENDERSTATE_DESTBLEND - 1] = D3DBLEND_INVSRCALPHA;
493             return;
494         }
495     } else if (dwRenderStateType == D3DRENDERSTATE_TEXTUREADDRESS) {
496         lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSU - 1] = dwRenderState;
497         lpStateBlock->render_state[D3DRENDERSTATE_TEXTUREADDRESSV - 1] = dwRenderState;
498     } else if (dwRenderStateType == D3DRENDERSTATE_WRAPU) {
499         if (dwRenderState) 
500             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_U;
501         else
502             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
503     } else if (dwRenderStateType == D3DRENDERSTATE_WRAPV) {
504         if (dwRenderState) 
505             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] |= D3DWRAP_V;
506         else
507             lpStateBlock->render_state[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
508     }
509     
510     /* Default case */
511     lpStateBlock->render_state[dwRenderStateType - 1] = dwRenderState;
512 }
513
514 void get_render_state(IDirect3DDeviceImpl *This,
515                       D3DRENDERSTATETYPE dwRenderStateType, LPDWORD lpdwRenderState, STATEBLOCK *lpStateBlock)
516 {
517     *lpdwRenderState = lpStateBlock->render_state[dwRenderStateType - 1];
518     if (TRACE_ON(ddraw))
519         TRACE("%s = %08lx\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
520 }
521
522 void apply_render_state(IDirect3DDeviceImpl *This, STATEBLOCK *lpStateBlock)
523 {
524     DWORD i;
525     TRACE("(%p,%p)\n", This, lpStateBlock);
526     for(i = 0; i < HIGHEST_RENDER_STATE; i++)
527         if (lpStateBlock->set_flags.render_state[i])
528             set_render_state(This, i + 1, lpStateBlock);
529 }