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