Delete all Trailing spaces in code.
[reactos.git] / reactos / dll / directx / wine / wined3d / state.c
1 /*
2 * Direct3D state management
3 *
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2007 Stefan Dösinger for CodeWeavers
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
38
39 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
40 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
41 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
42 */
43 if(STATE_IS_RENDER(state)) {
44 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
45 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
46 } else {
47 /* Shouldn't have an unknown type here */
48 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
49 }
50 }
51
52 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
53 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
54 * list without causing confusing terminal output. Deliberately no special debug name here
55 * because its undefined.
56 */
57 WARN("undefined state %d\n", state);
58 }
59
60 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
61 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
62
63 switch(Value) {
64 case WINED3DFILL_POINT:
65 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
66 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
67 break;
68 case WINED3DFILL_WIREFRAME:
69 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
70 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
71 break;
72 case WINED3DFILL_SOLID:
73 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
74 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
75 break;
76 default:
77 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
78 }
79 }
80
81 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
82 BOOL transformed;
83
84 /* Lighting is not enabled if transformed vertices are drawn
85 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
86 * This state reads the decoded vertex decl, so if it is dirty don't do anything. The
87 * vertex declaration appplying function calls this function for updating
88 */
89
90 if(isStateDirty(context, STATE_VDECL)) {
91 return;
92 }
93
94 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
95 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
96 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
97
98 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
99 glEnable(GL_LIGHTING);
100 checkGLcall("glEnable GL_LIGHTING");
101 } else {
102 glDisable(GL_LIGHTING);
103 checkGLcall("glDisable GL_LIGHTING");
104 }
105 }
106
107 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
108 /* No z test without depth stencil buffers */
109 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
110 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
111 checkGLcall("glDisable GL_DEPTH_TEST");
112 return;
113 }
114
115 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
116 case WINED3DZB_FALSE:
117 glDisable(GL_DEPTH_TEST);
118 checkGLcall("glDisable GL_DEPTH_TEST");
119 break;
120 case WINED3DZB_TRUE:
121 glEnable(GL_DEPTH_TEST);
122 checkGLcall("glEnable GL_DEPTH_TEST");
123 break;
124 case WINED3DZB_USEW:
125 glEnable(GL_DEPTH_TEST);
126 checkGLcall("glEnable GL_DEPTH_TEST");
127 FIXME("W buffer is not well handled\n");
128 break;
129 default:
130 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
131 }
132 }
133
134 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
135 /* TODO: Put this into the offscreen / onscreen rendering block due to device->render_offscreen */
136
137 /* If we are culling "back faces with clockwise vertices" then
138 set front faces to be counter clockwise and enable culling
139 of back faces */
140 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
141 case WINED3DCULL_NONE:
142 glDisable(GL_CULL_FACE);
143 checkGLcall("glDisable GL_CULL_FACE");
144 break;
145 case WINED3DCULL_CW:
146 glEnable(GL_CULL_FACE);
147 checkGLcall("glEnable GL_CULL_FACE");
148 if (stateblock->wineD3DDevice->render_offscreen) {
149 glFrontFace(GL_CW);
150 checkGLcall("glFrontFace GL_CW");
151 } else {
152 glFrontFace(GL_CCW);
153 checkGLcall("glFrontFace GL_CCW");
154 }
155 glCullFace(GL_BACK);
156 break;
157 case WINED3DCULL_CCW:
158 glEnable(GL_CULL_FACE);
159 checkGLcall("glEnable GL_CULL_FACE");
160 if (stateblock->wineD3DDevice->render_offscreen) {
161 glFrontFace(GL_CCW);
162 checkGLcall("glFrontFace GL_CCW");
163 } else {
164 glFrontFace(GL_CW);
165 checkGLcall("glFrontFace GL_CW");
166 }
167 glCullFace(GL_BACK);
168 break;
169 default:
170 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
171 }
172 }
173
174 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
175 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
176 case WINED3DSHADE_FLAT:
177 glShadeModel(GL_FLAT);
178 checkGLcall("glShadeModel(GL_FLAT)");
179 break;
180 case WINED3DSHADE_GOURAUD:
181 glShadeModel(GL_SMOOTH);
182 checkGLcall("glShadeModel(GL_SMOOTH)");
183 break;
184 case WINED3DSHADE_PHONG:
185 FIXME("WINED3DSHADE_PHONG isn't supported\n");
186 break;
187 default:
188 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
189 }
190 }
191
192 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
193 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
194 glEnable(GL_DITHER);
195 checkGLcall("glEnable GL_DITHER");
196 } else {
197 glDisable(GL_DITHER);
198 checkGLcall("glDisable GL_DITHER");
199 }
200 }
201
202 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
203 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
204 * this has to be merged with ZENABLE and ZFUNC
205 */
206 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
207 glDepthMask(1);
208 checkGLcall("glDepthMask(1)");
209 } else {
210 glDepthMask(0);
211 checkGLcall("glDepthMask(0)");
212 }
213 }
214
215 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
216 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
217
218 if(glParm) {
219 glDepthFunc(glParm);
220 checkGLcall("glDepthFunc");
221 }
222 }
223
224 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
225 float col[4];
226 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
227
228 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
229 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
230 checkGLcall("glLightModel for MODEL_AMBIENT");
231 }
232
233 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
234 int srcBlend = GL_ZERO;
235 int dstBlend = GL_ZERO;
236
237 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
238 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
239 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
240 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
241 glEnable(GL_BLEND);
242 checkGLcall("glEnable GL_BLEND");
243 } else {
244 glDisable(GL_BLEND);
245 checkGLcall("glDisable GL_BLEND");
246 /* Nothing more to do - get out */
247 return;
248 };
249
250 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
251 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
252 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
253 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
254 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
255 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
256 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
257 case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
258 case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
259 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
260 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
261 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
262
263 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
264 dstBlend = GL_SRC_ALPHA;
265 break;
266
267 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
268 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
269 break;
270
271 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
272 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
273 default:
274 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
275 }
276
277 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
278 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
279 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
280 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
281 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
282 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
283 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
284 case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
285 case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
286 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
287 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
288
289 case WINED3DBLEND_SRCALPHASAT :
290 dstBlend = GL_SRC_ALPHA_SATURATE;
291 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
292 break;
293
294 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
295 srcBlend = GL_SRC_ALPHA;
296 break;
297
298 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
299 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
300 break;
301
302 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
303 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
304 default:
305 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
306 }
307
308 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
309 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
310 glEnable(GL_LINE_SMOOTH);
311 checkGLcall("glEnable(GL_LINE_SMOOTH)");
312 if(srcBlend != GL_SRC_ALPHA) {
313 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
314 }
315 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
316 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
317 }
318 } else {
319 glDisable(GL_LINE_SMOOTH);
320 checkGLcall("glDisable(GL_LINE_SMOOTH)");
321 }
322
323 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
324 glBlendFunc(srcBlend, dstBlend);
325 checkGLcall("glBlendFunc");
326 }
327
328 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
329 float col[4];
330
331 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
332 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
333 GL_EXTCALL(glBlendColor (col[0],col[1],col[2],col[3]));
334 checkGLcall("glBlendColor");
335 }
336
337 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
338 int glParm = 0;
339 float ref;
340 BOOL enable_ckey = FALSE;
341
342 IWineD3DSurfaceImpl *surf;
343
344 /* Find out if the texture on the first stage has a ckey set
345 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
346 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
347 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
348 * in case it finds some texture+colorkeyenable combination which needs extra care.
349 */
350 if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
351 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
352
353 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
354 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
355 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
356 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
357 * surface has alpha bits
358 */
359 if(fmt->alphaMask == 0x00000000) {
360 enable_ckey = TRUE;
361 }
362 }
363 }
364
365 if(enable_ckey || context->last_was_ckey) {
366 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
367 }
368 context->last_was_ckey = enable_ckey;
369
370 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
371 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
372 glEnable(GL_ALPHA_TEST);
373 checkGLcall("glEnable GL_ALPHA_TEST");
374 } else {
375 glDisable(GL_ALPHA_TEST);
376 checkGLcall("glDisable GL_ALPHA_TEST");
377 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
378 * enable call
379 */
380 return;
381 }
382
383 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
384 glParm = GL_NOTEQUAL;
385 ref = 0.0;
386 } else {
387 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
388 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
389 }
390 if(glParm) {
391 glAlphaFunc(glParm, ref);
392 checkGLcall("glAlphaFunc");
393 }
394 }
395
396 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
397 DWORD enable = 0xFFFFFFFF;
398 DWORD disable = 0x00000000;
399
400 if (use_vs(stateblock->wineD3DDevice)) {
401 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
402 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
403 * contitions I got sick of tracking down. The shader state handler disables all clip planes because
404 * of that - don't do anything here and keep them disabled
405 */
406 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
407 static BOOL warned = FALSE;
408 if(!warned) {
409 FIXME("Clipping not supported with vertex shaders\n");
410 warned = TRUE;
411 }
412 }
413 return;
414 }
415
416 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
417 * of already set values
418 */
419
420 /* If enabling / disabling all
421 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
422 */
423 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
424 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
425 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
426 } else {
427 disable = 0xffffffff;
428 enable = 0x00;
429 }
430
431 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
432 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
433 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
434 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
435 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
436 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
437
438 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
439 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
440 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
441 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
442 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
443 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
444
445 /** update clipping status */
446 if (enable) {
447 stateblock->clip_status.ClipUnion = 0;
448 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
449 } else {
450 stateblock->clip_status.ClipUnion = 0;
451 stateblock->clip_status.ClipIntersection = 0;
452 }
453 }
454
455 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
456 int glParm = GL_FUNC_ADD;
457
458 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
459 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
460 return;
461 }
462
463 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
464 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
465 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
466 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
467 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
468 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
469 default:
470 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
471 }
472
473 TRACE("glBlendEquation(%x)\n", glParm);
474 GL_EXTCALL(glBlendEquation(glParm));
475 checkGLcall("glBlendEquation");
476 }
477
478 static void
479 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
480 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
481 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
482 * specular color. This is wrong:
483 * Separate specular color means the specular colour is maintained separately, whereas
484 * single color means it is merged in. However in both cases they are being used to
485 * some extent.
486 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
487 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
488 * running 1.4 yet!
489 *
490 *
491 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
492 * Instead, we need to setup the FinalCombiner properly.
493 *
494 * The default setup for the FinalCombiner is:
495 *
496 * <variable> <input> <mapping> <usage>
497 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
498 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
499 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
500 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
501 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
502 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
503 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
504 *
505 * That's pretty much fine as it is, except for variable B, which needs to take
506 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
507 * whether WINED3DRS_SPECULARENABLE is enabled or not.
508 */
509
510 TRACE("Setting specular enable state and materials\n");
511 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
512 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
513 checkGLcall("glMaterialfv");
514
515 if(stateblock->material.Power > 128.0) {
516 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
517 * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
518 * them, since 128 results in a hardly visible specular highlight, so it should be safe to
519 * to clamp to 128
520 */
521 WARN("Material power > 128\n");
522 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
523 } else {
524 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
525 }
526 checkGLcall("glMaterialf(GL_SHININESS");
527
528 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
529 glEnable(GL_COLOR_SUM_EXT);
530 } else {
531 TRACE("Specular colors cannot be enabled in this version of opengl\n");
532 }
533 checkGLcall("glEnable(GL_COLOR_SUM)");
534
535 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
536 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
537 checkGLcall("glFinalCombinerInputNV()");
538 }
539 } else {
540 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
541
542 /* for the case of enabled lighting: */
543 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
544 checkGLcall("glMaterialfv");
545
546 /* for the case of disabled lighting: */
547 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
548 glDisable(GL_COLOR_SUM_EXT);
549 } else {
550 TRACE("Specular colors cannot be disabled in this version of opengl\n");
551 }
552 checkGLcall("glDisable(GL_COLOR_SUM)");
553
554 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
555 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
556 checkGLcall("glFinalCombinerInputNV()");
557 }
558 }
559
560 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
561 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
562 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
563 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
564 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
565 stateblock->material.Specular.b, stateblock->material.Specular.a);
566 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
567 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
568
569 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
570 checkGLcall("glMaterialfv(GL_AMBIENT)");
571 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
572 checkGLcall("glMaterialfv(GL_DIFFUSE)");
573 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
574 checkGLcall("glMaterialfv(GL_EMISSION)");
575 }
576
577 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
578 unsigned int i;
579
580 /* Note the texture color applies to all textures whereas
581 * GL_TEXTURE_ENV_COLOR applies to active only
582 */
583 float col[4];
584 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
585
586 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
587 /* And now the default texture color as well */
588 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
589 /* Note the WINED3DRS value applies to all textures, but GL has one
590 * per texture, so apply it now ready to be used!
591 */
592 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
593 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
594 checkGLcall("glActiveTextureARB");
595 } else if (i>0) {
596 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
597 }
598
599 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
600 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
601 }
602 } else {
603 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
604 }
605 }
606
607 static void
608 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
609 #if 0 /* Don't use OpenGL 2.0 calls for now */
610 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
611 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
612 checkGLcall("glStencilFuncSeparate(...)");
613 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
614 checkGLcall("glStencilOpSeparate(...)");
615 }
616 else
617 #endif
618 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
619 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
620 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
621 GL_EXTCALL(glActiveStencilFaceEXT(face));
622 checkGLcall("glActiveStencilFaceEXT(...)");
623 glStencilFunc(func, ref, mask);
624 checkGLcall("glStencilFunc(...)");
625 glStencilOp(stencilFail, depthFail, stencilPass);
626 checkGLcall("glStencilOp(...)");
627 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
628 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
629 checkGLcall("glStencilFuncSeparateATI(...)");
630 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
631 checkGLcall("glStencilOpSeparateATI(...)");
632 } else {
633 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
634 }
635 }
636
637 static void
638 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
639 DWORD onesided_enable = FALSE;
640 DWORD twosided_enable = FALSE;
641 GLint func = GL_ALWAYS;
642 GLint func_ccw = GL_ALWAYS;
643 GLint ref = 0;
644 GLuint mask = 0;
645 GLint stencilFail = GL_KEEP;
646 GLint depthFail = GL_KEEP;
647 GLint stencilPass = GL_KEEP;
648 GLint stencilFail_ccw = GL_KEEP;
649 GLint depthFail_ccw = GL_KEEP;
650 GLint stencilPass_ccw = GL_KEEP;
651
652 /* No stencil test without a stencil buffer */
653 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
654 glDisable(GL_STENCIL_TEST);
655 checkGLcall("glDisable GL_STENCIL_TEST");
656 return;
657 }
658
659 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
660 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
661 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
662 func = GL_ALWAYS;
663 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
664 func = GL_ALWAYS;
665 ref = stateblock->renderState[WINED3DRS_STENCILREF];
666 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
667 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
668 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
669 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
670 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
671 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
672 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
673
674 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
675 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
676 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
677 onesided_enable, twosided_enable, ref, mask,
678 func, stencilFail, depthFail, stencilPass,
679 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
680
681 if (twosided_enable) {
682 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
683 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
684 } else {
685 if (onesided_enable) {
686 glEnable(GL_STENCIL_TEST);
687 checkGLcall("glEnable GL_STENCIL_TEST");
688 glStencilFunc(func, ref, mask);
689 checkGLcall("glStencilFunc(...)");
690 glStencilOp(stencilFail, depthFail, stencilPass);
691 checkGLcall("glStencilOp(...)");
692 } else {
693 glDisable(GL_STENCIL_TEST);
694 checkGLcall("glDisable GL_STENCIL_TEST");
695 }
696 }
697 }
698
699 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
700 if(stateblock->wineD3DDevice->stencilBufferTarget) {
701 glStencilMask(stateblock->renderState[WINED3DRS_STENCILWRITEMASK]);
702 } else {
703 glStencilMask(0);
704 }
705 checkGLcall("glStencilMask");
706 }
707
708 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
709 /* TODO: Put this into the vertex type block once that is in the state table */
710 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
711 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
712 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
713 float fogstart, fogend;
714
715 union {
716 DWORD d;
717 float f;
718 } tmpvalue;
719
720 if (!fogenable) {
721 /* No fog? Disable it, and we're done :-) */
722 glDisable(GL_FOG);
723 checkGLcall("glDisable GL_FOG");
724 if( use_ps(stateblock->wineD3DDevice)
725 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
726 /* disable fog in the pixel shader
727 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
728 * -1/(e-s) and e/(e-s) respectively.
729 */
730 glFogf(GL_FOG_START, 0.0f);
731 checkGLcall("glFogf(GL_FOG_START, fogstart");
732 glFogf(GL_FOG_END, 1.0f);
733 checkGLcall("glFogf(GL_FOG_END, fogend");
734 }
735 return;
736 }
737
738 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
739 fogstart = tmpvalue.f;
740 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
741 fogend = tmpvalue.f;
742
743 /* Fog Rules:
744 *
745 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
746 * It can use the Z value of the vertex, or the alpha component of the specular color.
747 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
748 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
749 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
750 *
751 * FOGTABLEMODE != NONE:
752 * The Z value is used, with the equation specified, no matter what vertex type.
753 *
754 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
755 * Per vertex fog is calculated using the specified fog equation and the parameters
756 *
757 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
758 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
759 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
760 *
761 *
762 * Rules for vertex fog with shaders:
763 *
764 * When mixing fixed function functionality with the programmable pipeline, D3D expects
765 * the fog computation to happen during transformation while openGL expects it to happen
766 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
767 * the pixel shader while openGL always expects the pixel shader to handle the blending.
768 * To solve this problem, WineD3D does:
769 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
770 * shader,
771 * and 2) disables the fog computation (in either the fixed function or programmable
772 * rasterizer) if using a vertex program.
773 *
774 *
775 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
776 * without shaders).
777 */
778
779 if( is_ps3 ) {
780 if( !use_vs(stateblock->wineD3DDevice)
781 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
782 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
783 }
784 }
785
786 if (use_vs(stateblock->wineD3DDevice)
787 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
788 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
789 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
790 /* Disable fog */
791 fogenable = FALSE;
792 } else {
793 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
794 glFogi(GL_FOG_MODE, GL_LINEAR);
795 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
796 fogstart = 1.0;
797 fogend = 0.0;
798 }
799 context->last_was_foggy_shader = TRUE;
800 }
801 else if( use_ps(stateblock->wineD3DDevice) ) {
802 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
803 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
804 */
805 WINED3DFOGMODE mode;
806 context->last_was_foggy_shader = FALSE;
807
808 /* If both fogmodes are set use the table fog mode */
809 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
810 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
811 else
812 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
813
814 switch (mode) {
815 case WINED3DFOG_EXP:
816 case WINED3DFOG_EXP2:
817 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
818 /* Disable fog */
819 fogenable = FALSE;
820 break;
821
822 case WINED3DFOG_LINEAR:
823 fogstart = -1.0f/(fogend-fogstart);
824 fogend *= -fogstart;
825 break;
826
827 case WINED3DFOG_NONE:
828 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
829 /* Disable fog */
830 fogenable = FALSE;
831 break;
832 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
833 }
834 }
835 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
836 * the system will apply only pixel(=table) fog effects."
837 */
838 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
839 glHint(GL_FOG_HINT, GL_FASTEST);
840 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
841 context->last_was_foggy_shader = FALSE;
842
843 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
844 /* If processed vertices are used, fall through to the NONE case */
845 case WINED3DFOG_EXP: {
846 if(!context->last_was_rhw) {
847 glFogi(GL_FOG_MODE, GL_EXP);
848 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
849 if(GL_SUPPORT(EXT_FOG_COORD)) {
850 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
851 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
852 }
853 break;
854 }
855 }
856 case WINED3DFOG_EXP2: {
857 if(!context->last_was_rhw) {
858 glFogi(GL_FOG_MODE, GL_EXP2);
859 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
860 if(GL_SUPPORT(EXT_FOG_COORD)) {
861 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
862 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
863 }
864 break;
865 }
866 }
867 case WINED3DFOG_LINEAR: {
868 if(!context->last_was_rhw) {
869 glFogi(GL_FOG_MODE, GL_LINEAR);
870 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
871 if(GL_SUPPORT(EXT_FOG_COORD)) {
872 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
873 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
874 }
875 break;
876 }
877 }
878 case WINED3DFOG_NONE: {
879 /* Both are none? According to msdn the alpha channel of the specular
880 * color contains a fog factor. Set it in drawStridedSlow.
881 * Same happens with Vertexfog on transformed vertices
882 */
883 if(GL_SUPPORT(EXT_FOG_COORD)) {
884 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
885 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
886 glFogi(GL_FOG_MODE, GL_LINEAR);
887 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
888 fogstart = 0xff;
889 fogend = 0x0;
890 } else {
891 /* Disable GL fog, handle this in software in drawStridedSlow */
892 fogenable = FALSE;
893 }
894 break;
895 }
896 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
897 }
898 } else {
899 glHint(GL_FOG_HINT, GL_NICEST);
900 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
901 context->last_was_foggy_shader = FALSE;
902
903 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
904 case WINED3DFOG_EXP:
905 glFogi(GL_FOG_MODE, GL_EXP);
906 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
907 if(GL_SUPPORT(EXT_FOG_COORD)) {
908 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
909 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
910 }
911 break;
912
913 case WINED3DFOG_EXP2:
914 glFogi(GL_FOG_MODE, GL_EXP2);
915 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
916 if(GL_SUPPORT(EXT_FOG_COORD)) {
917 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
918 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
919 }
920 break;
921
922 case WINED3DFOG_LINEAR:
923 glFogi(GL_FOG_MODE, GL_LINEAR);
924 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
925 if(GL_SUPPORT(EXT_FOG_COORD)) {
926 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
927 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
928 }
929 break;
930
931 case WINED3DFOG_NONE: /* Won't happen */
932 default:
933 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
934 }
935 }
936
937 if(fogenable) {
938 glEnable(GL_FOG);
939 checkGLcall("glEnable GL_FOG");
940
941 glFogfv(GL_FOG_START, &fogstart);
942 checkGLcall("glFogf(GL_FOG_START, fogstart");
943 TRACE("Fog Start == %f\n", fogstart);
944
945 glFogfv(GL_FOG_END, &fogend);
946 checkGLcall("glFogf(GL_FOG_END, fogend");
947 TRACE("Fog End == %f\n", fogend);
948 } else {
949 glDisable(GL_FOG);
950 checkGLcall("glDisable GL_FOG");
951 if( use_ps(stateblock->wineD3DDevice) ) {
952 /* disable fog in the pixel shader
953 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
954 * -1/(e-s) and e/(e-s) respectively.
955 */
956 glFogf(GL_FOG_START, 0.0f);
957 checkGLcall("glFogf(GL_FOG_START, fogstart");
958 glFogf(GL_FOG_END, 1.0f);
959 checkGLcall("glFogf(GL_FOG_END, fogend");
960 }
961 }
962
963 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
964 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
965 }
966 }
967
968 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
969 float col[4];
970 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
971 glFogfv(GL_FOG_COLOR, &col[0]);
972 checkGLcall("glFog GL_FOG_COLOR");
973 }
974
975 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
976 union {
977 DWORD d;
978 float f;
979 } tmpvalue;
980 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
981 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
982 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
983 }
984
985 /* TODO: Merge with primitive type + init_materials()!! */
986 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
987 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice;
988 GLenum Parm = 0;
989 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
990 BOOL isDiffuseSupplied;
991
992 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
993 * The vertex declaration will call this function if the fixed function pipeline is used.
994 */
995
996 if(isStateDirty(context, STATE_VDECL)) {
997 return;
998 }
999
1000 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1001
1002 context->num_untracked_materials = 0;
1003 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1004 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1005 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1006 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1007 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1008 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1009
1010 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1011 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1012 Parm = GL_AMBIENT_AND_DIFFUSE;
1013 } else {
1014 Parm = GL_DIFFUSE;
1015 }
1016 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1017 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1018 context->num_untracked_materials++;
1019 }
1020 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1021 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1022 context->num_untracked_materials++;
1023 }
1024 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1025 Parm = GL_AMBIENT;
1026 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1027 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1028 context->num_untracked_materials++;
1029 }
1030 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1031 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1032 context->num_untracked_materials++;
1033 }
1034 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1035 Parm = GL_EMISSION;
1036 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1037 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1038 context->num_untracked_materials++;
1039 }
1040 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1041 Parm = GL_SPECULAR;
1042 }
1043 }
1044
1045 /* Nothing changed, return. */
1046 if (Parm == context->tracking_parm) return;
1047
1048 if(!Parm) {
1049 glDisable(GL_COLOR_MATERIAL);
1050 checkGLcall("glDisable GL_COLOR_MATERIAL");
1051 } else {
1052 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1053 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1054 glEnable(GL_COLOR_MATERIAL);
1055 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1056 }
1057
1058 /* Apparently calls to glMaterialfv are ignored for properties we're
1059 * tracking with glColorMaterial, so apply those here. */
1060 switch (context->tracking_parm) {
1061 case GL_AMBIENT_AND_DIFFUSE:
1062 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1063 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1064 checkGLcall("glMaterialfv");
1065 break;
1066
1067 case GL_DIFFUSE:
1068 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1069 checkGLcall("glMaterialfv");
1070 break;
1071
1072 case GL_AMBIENT:
1073 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1074 checkGLcall("glMaterialfv");
1075 break;
1076
1077 case GL_EMISSION:
1078 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1079 checkGLcall("glMaterialfv");
1080 break;
1081
1082 case GL_SPECULAR:
1083 /* Only change material color if specular is enabled, otherwise it is set to black */
1084 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1085 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1086 checkGLcall("glMaterialfv");
1087 } else {
1088 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1089 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1090 checkGLcall("glMaterialfv");
1091 }
1092 break;
1093 }
1094
1095 context->tracking_parm = Parm;
1096 }
1097
1098 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1099 union {
1100 DWORD d;
1101 WINED3DLINEPATTERN lp;
1102 } tmppattern;
1103 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1104
1105 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1106
1107 if (tmppattern.lp.wRepeatFactor) {
1108 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1109 checkGLcall("glLineStipple(repeat, linepattern)");
1110 glEnable(GL_LINE_STIPPLE);
1111 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1112 } else {
1113 glDisable(GL_LINE_STIPPLE);
1114 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1115 }
1116 }
1117
1118 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1119 union {
1120 DWORD d;
1121 float f;
1122 } tmpvalue;
1123
1124 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1125 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1126 TRACE("ZBias value %f\n", tmpvalue.f);
1127 glPolygonOffset(0, -tmpvalue.f);
1128 checkGLcall("glPolygonOffset(0, -Value)");
1129 glEnable(GL_POLYGON_OFFSET_FILL);
1130 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1131 glEnable(GL_POLYGON_OFFSET_LINE);
1132 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1133 glEnable(GL_POLYGON_OFFSET_POINT);
1134 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1135 } else {
1136 glDisable(GL_POLYGON_OFFSET_FILL);
1137 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1138 glDisable(GL_POLYGON_OFFSET_LINE);
1139 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1140 glDisable(GL_POLYGON_OFFSET_POINT);
1141 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1142 }
1143 }
1144
1145
1146 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1147 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]) {
1148 glEnable(GL_NORMALIZE);
1149 checkGLcall("glEnable(GL_NORMALIZE);");
1150 } else {
1151 glDisable(GL_NORMALIZE);
1152 checkGLcall("glDisable(GL_NORMALIZE);");
1153 }
1154 }
1155
1156 static void state_psize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1157 union {
1158 DWORD d;
1159 float f;
1160 } tmpvalue;
1161
1162 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
1163 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1164 TRACE("Set point size to %f\n", tmpvalue.f);
1165 glPointSize(tmpvalue.f);
1166 checkGLcall("glPointSize(...);");
1167 }
1168
1169 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1170 union {
1171 DWORD d;
1172 float f;
1173 } tmpvalue;
1174
1175 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1176 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1177 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1178 checkGLcall("glPointParameterfARB(...");
1179 }
1180 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1181 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1182 checkGLcall("glPointParameterfEXT(...);");
1183 } else if(tmpvalue.f != 1.0) {
1184 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1185 }
1186 }
1187
1188 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1189 union {
1190 DWORD d;
1191 float f;
1192 } tmpvalue;
1193
1194 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1195 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1196 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1197 checkGLcall("glPointParameterfARB(...");
1198 }
1199 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1200 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1201 checkGLcall("glPointParameterfEXT(...);");
1202 } else if(tmpvalue.f != 64.0) {
1203 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1204 }
1205 }
1206
1207 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1208 /* TODO: Group this with the viewport */
1209 /*
1210 * POINTSCALEENABLE controls how point size value is treated. If set to
1211 * true, the point size is scaled with respect to height of viewport.
1212 * When set to false point size is in pixels.
1213 *
1214 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
1215 */
1216
1217 /* Default values */
1218 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1219
1220 /*
1221 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
1222 * This means that OpenGL will clamp really small point sizes to 1.0f.
1223 * To correct for this we need to multiply by the scale factor when sizes
1224 * are less than 1.0f. scale_factor = 1.0f / point_size.
1225 */
1226 GLfloat pointSize = *((float*)&stateblock->renderState[WINED3DRS_POINTSIZE]);
1227 if(pointSize > 0.0f) {
1228 GLfloat scaleFactor;
1229
1230 if(pointSize < 1.0f) {
1231 scaleFactor = pointSize * pointSize;
1232 } else {
1233 scaleFactor = 1.0f;
1234 }
1235
1236 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1237 att[0] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_A]) /
1238 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1239 att[1] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_B]) /
1240 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1241 att[2] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_C]) /
1242 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1243 }
1244 }
1245
1246 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1247 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1248 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
1249 }
1250 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1251 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1252 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
1253 } else {
1254 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
1255 }
1256 }
1257
1258 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1259 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1260
1261 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1262 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1263 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1264 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1265 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1266 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1267 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1268 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1269 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1270 checkGLcall("glColorMask(...)");
1271
1272 /* depends on WINED3DRS_COLORWRITEENABLE. */
1273 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1274 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1275 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1276 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1277 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1278 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1279 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1280 }
1281 }
1282
1283 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1284 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1285 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1286 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1287 } else {
1288 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1289 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1290 }
1291 }
1292
1293 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1294 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1295 TRACE("Last Pixel Drawing Enabled\n");
1296 } else {
1297 static BOOL first = TRUE;
1298 if(first) {
1299 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1300 first = FALSE;
1301 } else {
1302 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1303 }
1304 }
1305 }
1306
1307 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1308 /* TODO: NV_POINT_SPRITE */
1309 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1310 TRACE("Point sprites not supported\n");
1311 return;
1312 }
1313
1314 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1315 glEnable(GL_POINT_SPRITE_ARB);
1316 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n");
1317 } else {
1318 glDisable(GL_POINT_SPRITE_ARB);
1319 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n");
1320 }
1321 }
1322
1323 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1324 /**
1325 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1326 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
1327 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1328 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
1329 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1330
1331 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1332 */
1333 TRACE("Stub\n");
1334 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1335 stateblock->renderState[WINED3DRS_WRAP1] ||
1336 stateblock->renderState[WINED3DRS_WRAP2] ||
1337 stateblock->renderState[WINED3DRS_WRAP3] ||
1338 stateblock->renderState[WINED3DRS_WRAP4] ||
1339 stateblock->renderState[WINED3DRS_WRAP5] ||
1340 stateblock->renderState[WINED3DRS_WRAP6] ||
1341 stateblock->renderState[WINED3DRS_WRAP7] ||
1342 stateblock->renderState[WINED3DRS_WRAP8] ||
1343 stateblock->renderState[WINED3DRS_WRAP9] ||
1344 stateblock->renderState[WINED3DRS_WRAP10] ||
1345 stateblock->renderState[WINED3DRS_WRAP11] ||
1346 stateblock->renderState[WINED3DRS_WRAP12] ||
1347 stateblock->renderState[WINED3DRS_WRAP13] ||
1348 stateblock->renderState[WINED3DRS_WRAP14] ||
1349 stateblock->renderState[WINED3DRS_WRAP15] ) {
1350 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1351 }
1352 }
1353
1354 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1355 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1356 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1357 glEnable(GL_MULTISAMPLE_ARB);
1358 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1359 } else {
1360 glDisable(GL_MULTISAMPLE_ARB);
1361 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1362 }
1363 } else {
1364 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1365 WARN("Multisample antialiasing not supported by gl\n");
1366 }
1367 }
1368 }
1369
1370 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1371 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1372 glEnable(GL_SCISSOR_TEST);
1373 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1374 } else {
1375 glDisable(GL_SCISSOR_TEST);
1376 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1377 }
1378 }
1379
1380 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1381 union {
1382 DWORD d;
1383 float f;
1384 } tmpvalue;
1385
1386 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1387 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1388 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1389 glEnable(GL_POLYGON_OFFSET_FILL);
1390 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1391 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1392 checkGLcall("glPolygonOffset(...)");
1393 } else {
1394 glDisable(GL_POLYGON_OFFSET_FILL);
1395 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1396 }
1397 }
1398
1399 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1400 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1401 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1402 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1403 } else {
1404 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1405 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1406 }
1407 }
1408
1409 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1410 TRACE("Stub\n");
1411 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1412 FIXME(" Stippled Alpha not supported yet.\n");
1413 }
1414
1415 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1416 TRACE("Stub\n");
1417 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1418 FIXME(" Antialias not supported yet.\n");
1419 }
1420
1421 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1422 TRACE("Stub\n");
1423 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1424 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1425 }
1426
1427 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1428 TRACE("Stub\n");
1429 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1430 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1431 }
1432
1433 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1434 union {
1435 DWORD d;
1436 float f;
1437 } tmpvalue;
1438 tmpvalue.f = 1.0f;
1439
1440 TRACE("Stub\n");
1441 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1442 {
1443 static BOOL displayed = FALSE;
1444
1445 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1446 if(!displayed)
1447 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1448
1449 displayed = TRUE;
1450 }
1451 }
1452
1453 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1454 TRACE("Stub\n");
1455 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1456 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1457 }
1458
1459 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1460 TRACE("Stub\n");
1461 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1462 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1463 }
1464
1465 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1466 TRACE("Stub\n");
1467 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1468 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1469 }
1470
1471
1472 static void state_srgbwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1473 if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE])
1474 FIXME("Render state WINED3DRS_SRGBWRITEENABLE not yet implemented\n");
1475 }
1476
1477 static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1478 TRACE("Stub\n");
1479 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
1480 FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
1481 }
1482
1483 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1484 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1485 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1486 }
1487 }
1488
1489 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1490 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1491 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1492 }
1493 }
1494
1495 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1496 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1497 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1498 }
1499 }
1500
1501 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1502 if(stateblock->renderState[WINED3DRS_ROP2]) {
1503 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1504 }
1505 }
1506
1507 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1508 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1509 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1510 }
1511 }
1512
1513 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1514 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1515 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1516 }
1517 }
1518
1519 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1520 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1521 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1522 }
1523 }
1524
1525 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1526 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1527 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1528 }
1529 }
1530
1531 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1532 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1533 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1534 }
1535 }
1536
1537 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1538 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1539 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1540 }
1541 }
1542
1543 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1544 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1545 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1546 }
1547 }
1548
1549 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1550 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1551 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1552 }
1553 }
1554
1555 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1556 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1557 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1558 }
1559 }
1560
1561 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1562 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1563 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1564 }
1565 }
1566
1567 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1568 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1569 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1570 }
1571 }
1572
1573 /* Activates the texture dimension according to the bound D3D texture.
1574 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1575 * Requires the caller to activate the correct unit before
1576 */
1577 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1578 BOOL bumpmap = FALSE;
1579
1580 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1581 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1582 bumpmap = TRUE;
1583 context->texShaderBumpMap |= (1 << stage);
1584 } else {
1585 context->texShaderBumpMap &= ~(1 << stage);
1586 }
1587
1588 if(stateblock->textures[stage]) {
1589 switch(stateblock->textureDimensions[stage]) {
1590 case GL_TEXTURE_2D:
1591 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1592 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1593 } else {
1594 glDisable(GL_TEXTURE_3D);
1595 checkGLcall("glDisable(GL_TEXTURE_3D)");
1596 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1597 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1598 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1599 }
1600 glEnable(GL_TEXTURE_2D);
1601 checkGLcall("glEnable(GL_TEXTURE_2D)");
1602 }
1603 break;
1604 case GL_TEXTURE_3D:
1605 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1606 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1607 } else {
1608 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1609 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1610 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1611 }
1612 glDisable(GL_TEXTURE_2D);
1613 checkGLcall("glDisable(GL_TEXTURE_2D)");
1614 glEnable(GL_TEXTURE_3D);
1615 checkGLcall("glEnable(GL_TEXTURE_3D)");
1616 }
1617 break;
1618 case GL_TEXTURE_CUBE_MAP_ARB:
1619 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1620 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1621 } else {
1622 glDisable(GL_TEXTURE_2D);
1623 checkGLcall("glDisable(GL_TEXTURE_2D)");
1624 glDisable(GL_TEXTURE_3D);
1625 checkGLcall("glDisable(GL_TEXTURE_3D)");
1626 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1627 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1628 }
1629 break;
1630 }
1631 } else {
1632 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1633 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1634 } else {
1635 glEnable(GL_TEXTURE_2D);
1636 checkGLcall("glEnable(GL_TEXTURE_2D)");
1637 glDisable(GL_TEXTURE_3D);
1638 checkGLcall("glDisable(GL_TEXTURE_3D)");
1639 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1640 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1641 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1642 }
1643 /* Binding textures is done by samplers. A dummy texture will be bound */
1644 }
1645 }
1646 }
1647
1648 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1649 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1650 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1651 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1652
1653 TRACE("Setting color op for stage %d\n", stage);
1654
1655 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1656 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1657 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1658 return;
1659 }
1660
1661 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1662
1663 if (mapped_stage != -1) {
1664 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1665 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1666 FIXME("Attempt to enable unsupported stage!\n");
1667 return;
1668 }
1669 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1670 checkGLcall("glActiveTextureARB");
1671 } else if (stage > 0) {
1672 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1673 return;
1674 }
1675 }
1676
1677 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1678 if(stateblock->lowest_disabled_stage > 0) {
1679 glEnable(GL_REGISTER_COMBINERS_NV);
1680 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1681 } else {
1682 glDisable(GL_REGISTER_COMBINERS_NV);
1683 }
1684 }
1685 if(stage >= stateblock->lowest_disabled_stage) {
1686 TRACE("Stage disabled\n");
1687 if (mapped_stage != -1) {
1688 /* Disable everything here */
1689 glDisable(GL_TEXTURE_2D);
1690 checkGLcall("glDisable(GL_TEXTURE_2D)");
1691 glDisable(GL_TEXTURE_3D);
1692 checkGLcall("glDisable(GL_TEXTURE_3D)");
1693 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1694 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1695 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1696 }
1697 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1698 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1699 }
1700 }
1701 /* All done */
1702 return;
1703 }
1704
1705 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1706 * if the sampler for this stage is dirty
1707 */
1708 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1709 if (tex_used) activate_dimensions(stage, stateblock, context);
1710 }
1711
1712 /* Set the texture combiners */
1713 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1714 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1715 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1716 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1717 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1718 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1719 mapped_stage);
1720
1721 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1722 * thus the texture shader may have to be updated
1723 */
1724 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1725 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1726 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1727 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1728 if(usesBump != usedBump) {
1729 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1730 checkGLcall("glActiveTextureARB");
1731 activate_dimensions(stage + 1, stateblock, context);
1732 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1733 checkGLcall("glActiveTextureARB");
1734 }
1735 }
1736 } else {
1737 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1738 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1739 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1740 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1741 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1742 }
1743 }
1744
1745 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1746 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1747 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1748 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1749 DWORD op, arg1, arg2, arg0;
1750
1751 TRACE("Setting alpha op for stage %d\n", stage);
1752 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1753 if (mapped_stage != -1) {
1754 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1755 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1756 FIXME("Attempt to enable unsupported stage!\n");
1757 return;
1758 }
1759 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1760 checkGLcall("glActiveTextureARB");
1761 } else if (stage > 0) {
1762 /* We can't do anything here */
1763 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1764 return;
1765 }
1766 }
1767
1768 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1769 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1770 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1771 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1772
1773 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1774 stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
1775 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1776
1777 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1778 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1779
1780 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1781 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1782 * cannot remove the texture's alpha channel entirely.
1783 *
1784 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1785 * on color keyed surfaces.
1786 *
1787 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1788 */
1789 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1790 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1791 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1792 }
1793 }
1794
1795 TRACE("Setting alpha op for stage %d\n", stage);
1796 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1797 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1798 op, arg1, arg2, arg0,
1799 mapped_stage);
1800 } else {
1801 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1802 op, arg1, arg2, arg0);
1803 }
1804 }
1805
1806 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1807 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1808 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1809
1810 if (mapped_stage < 0) return;
1811
1812 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1813 if(mapped_stage >= GL_LIMITS(textures)) {
1814 return;
1815 }
1816 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1817 checkGLcall("glActiveTextureARB");
1818 } else if (mapped_stage > 0) {
1819 /* We can't do anything here */
1820 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1821 return;
1822 }
1823
1824 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1825 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1826 (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU);
1827
1828 }
1829
1830 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1831 int texture_idx;
1832
1833 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1834 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1835 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1836 }
1837 }
1838
1839 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
1840 UINT *offset = stateblock->streamOffset;
1841 unsigned int mapped_stage = 0;
1842 unsigned int textureNo = 0;
1843
1844 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1845 /* Abort if we don't support the extension. */
1846 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1847 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1848 return;
1849 }
1850
1851 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1852 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1853
1854 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
1855 if (mapped_stage == -1) continue;
1856
1857 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
1858 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1859 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1860
1861 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1862 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1863 checkGLcall("glBindBufferARB");
1864 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
1865 }
1866
1867 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1868 checkGLcall("glClientActiveTextureARB");
1869
1870 /* The coords to supply depend completely on the fvf / vertex shader */
1871 glTexCoordPointer(
1872 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1873 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1874 sd->u.s.texCoords[coordIdx].dwStride,
1875 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
1876 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1877 } else {
1878 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
1879 }
1880 }
1881 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1882 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
1883 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
1884 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1885 }
1886 }
1887 }
1888
1889 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1890 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1891 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1892
1893 if (mapped_stage == -1) {
1894 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
1895 return;
1896 }
1897
1898 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1899 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
1900 return;
1901 }
1902 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1903 checkGLcall("glActiveTextureARB");
1904 } else if (stage > 0) {
1905 /* We can't do anything here */
1906 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1907 return;
1908 }
1909
1910 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
1911 *
1912 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
1913 * one flag, you can still specify an index value, which the system uses to
1914 * determine the texture wrapping mode.
1915 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
1916 * means use the vertex position (camera-space) as the input texture coordinates
1917 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
1918 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
1919 * to the TEXCOORDINDEX value
1920 */
1921
1922 /*
1923 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
1924 */
1925 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
1926 case WINED3DTSS_TCI_PASSTHRU:
1927 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
1928 glDisable(GL_TEXTURE_GEN_S);
1929 glDisable(GL_TEXTURE_GEN_T);
1930 glDisable(GL_TEXTURE_GEN_R);
1931 glDisable(GL_TEXTURE_GEN_Q);
1932 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
1933 break;
1934
1935 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
1936 /* CameraSpacePosition means use the vertex position, transformed to camera space,
1937 * as the input texture coordinates for this stage's texture transformation. This
1938 * equates roughly to EYE_LINEAR
1939 */
1940 {
1941 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1942 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1943 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1944 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1945 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
1946
1947 glMatrixMode(GL_MODELVIEW);
1948 glPushMatrix();
1949 glLoadIdentity();
1950 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
1951 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
1952 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
1953 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
1954 glPopMatrix();
1955
1956 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
1957 glEnable(GL_TEXTURE_GEN_S);
1958 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
1959 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1960 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1961 glEnable(GL_TEXTURE_GEN_T);
1962 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
1963 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1964 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1965 glEnable(GL_TEXTURE_GEN_R);
1966 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
1967 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
1968 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
1969 }
1970 break;
1971
1972 case WINED3DTSS_TCI_CAMERASPACENORMAL:
1973 {
1974 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
1975 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
1976 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
1977 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
1978 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
1979 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
1980
1981 glMatrixMode(GL_MODELVIEW);
1982 glPushMatrix();
1983 glLoadIdentity();
1984 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
1985 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
1986 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
1987 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
1988 glPopMatrix();
1989
1990 glEnable(GL_TEXTURE_GEN_S);
1991 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
1992 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
1993 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
1994 glEnable(GL_TEXTURE_GEN_T);
1995 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
1996 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
1997 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
1998 glEnable(GL_TEXTURE_GEN_R);
1999 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2000 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2001 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2002 }
2003 }
2004 break;
2005
2006 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2007 {
2008 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2009 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2010 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2011 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2012 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2013 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2014
2015 glMatrixMode(GL_MODELVIEW);
2016 glPushMatrix();
2017 glLoadIdentity();
2018 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2019 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2020 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2021 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2022 glPopMatrix();
2023
2024 glEnable(GL_TEXTURE_GEN_S);
2025 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2026 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2027 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2028 glEnable(GL_TEXTURE_GEN_T);
2029 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2030 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2031 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2032 glEnable(GL_TEXTURE_GEN_R);
2033 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2034 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2035 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2036 }
2037 }
2038 break;
2039
2040 /* Unhandled types: */
2041 default:
2042 /* Todo: */
2043 /* ? disable GL_TEXTURE_GEN_n ? */
2044 glDisable(GL_TEXTURE_GEN_S);
2045 glDisable(GL_TEXTURE_GEN_T);
2046 glDisable(GL_TEXTURE_GEN_R);
2047 glDisable(GL_TEXTURE_GEN_Q);
2048 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2049 break;
2050 }
2051
2052 /* Update the texture matrix */
2053 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2054 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2055 }
2056
2057 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2058 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2059 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2060 * and do all the things linked to it
2061 * TODO: Tidy that up to reload only the arrays of the changed unit
2062 */
2063 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2064
2065 unloadTexCoords(stateblock);
2066 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2067 }
2068 }
2069
2070 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2071 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2072 union {
2073 DWORD d;
2074 float f;
2075 } tmpvalue;
2076
2077 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2078 if(tmpvalue.f != 0.0) {
2079 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2080 }
2081 }
2082
2083 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2084 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2085 union {
2086 DWORD d;
2087 float f;
2088 } tmpvalue;
2089
2090 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2091 if(tmpvalue.f != 0.0) {
2092 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2093 }
2094 }
2095
2096 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2097 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2098
2099 if(stage >= GL_LIMITS(texture_stages)) {
2100 return;
2101 }
2102
2103 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2104 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2105 }
2106 }
2107
2108 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2109 DWORD sampler = state - STATE_SAMPLER(0);
2110 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2111 union {
2112 float f;
2113 DWORD d;
2114 } tmpvalue;
2115
2116 TRACE("Sampler: %d\n", sampler);
2117 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2118 * only has to bind textures and set the per texture states
2119 */
2120
2121 if (mapped_stage == -1) {
2122 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2123 return;
2124 }
2125
2126 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2127 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2128 return;
2129 }
2130 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2131 checkGLcall("glActiveTextureARB");
2132 } else if (sampler > 0) {
2133 /* We can't do anything here */
2134 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2135 return;
2136 }
2137
2138 if(stateblock->textures[sampler]) {
2139 BOOL texIsPow2 = FALSE;
2140
2141 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2142 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2143 * scaling is reapplied or removed, the texture matrix has to be reapplied
2144 */
2145 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2146 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
2147 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
2148 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {
2149 texIsPow2 = TRUE;
2150 }
2151 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2152 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->pow2scalingFactor != 1.0) {
2153 texIsPow2 = TRUE;
2154 }
2155 }
2156
2157 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2158 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2159 context->lastWasPow2Texture[sampler] = texIsPow2;
2160 }
2161 }
2162
2163 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2164 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2165
2166 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2167 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2168 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2169 GL_TEXTURE_LOD_BIAS_EXT,
2170 tmpvalue.f);
2171 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2172 }
2173
2174 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2175 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2176 /* Using a pixel shader? Verify the sampler types */
2177
2178 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2179 * dimensions because the shader knows from which texture type to sample from. For the sake of
2180 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2181 * dimensions. This should make wrong sampling sources visible :-)
2182 */
2183 glEnable(stateblock->textureDimensions[sampler]);
2184 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2185 } else if(sampler < stateblock->lowest_disabled_stage) {
2186 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2187 activate_dimensions(sampler, stateblock, context);
2188 }
2189
2190 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2191 /* If color keying is enabled update the alpha test, it depends on the existence
2192 * of a color key in stage 0
2193 */
2194 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2195 }
2196 }
2197 } else if(sampler < GL_LIMITS(texture_stages)) {
2198 if(sampler < stateblock->lowest_disabled_stage) {
2199 /* TODO: What should I do with pixel shaders here ??? */
2200 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2201 activate_dimensions(sampler, stateblock, context);
2202 }
2203 } /* Otherwise tex_colorop disables the stage */
2204 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2205 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2206 }
2207 }
2208
2209 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2210 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2211
2212 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2213 * has an update pending
2214 */
2215 if(isStateDirty(context, STATE_VDECL) ||
2216 isStateDirty(context, STATE_PIXELSHADER)) {
2217 return;
2218 }
2219
2220 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2221 }
2222
2223 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2224 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2225 BOOL use_pshader = use_ps(device);
2226 BOOL use_vshader = use_vs(device);
2227 BOOL update_fog = FALSE;
2228 int i;
2229
2230 if (use_pshader) {
2231 if(!context->last_was_pshader) {
2232 /* Former draw without a pixel shader, some samplers
2233 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2234 * make sure to enable them
2235 */
2236 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2237 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2238 sampler(STATE_SAMPLER(i), stateblock, context);
2239 }
2240 }
2241 update_fog = TRUE;
2242 } else {
2243 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2244 * if a different texture was bound. I don't have to do anything.
2245 */
2246 }
2247
2248 /* Compile and bind the shader */
2249 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2250 } else {
2251 /* Disabled the pixel shader - color ops weren't applied
2252 * while it was enabled, so re-apply them.
2253 */
2254 for(i=0; i < MAX_TEXTURES; i++) {
2255 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2256 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2257 }
2258 }
2259 if(context->last_was_pshader)
2260 update_fog = TRUE;
2261 }
2262
2263 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2264 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2265
2266 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2267 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2268 }
2269 }
2270
2271 if(update_fog)
2272 state_fog(state, stateblock, context);
2273
2274 context->last_was_pshader = use_pshader;
2275 }
2276
2277 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2278 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2279
2280 if(stateblock->pixelShader && stage != 0 &&
2281 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2282 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2283 * anyway
2284 */
2285 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2286 !isStateDirty(context, STATE_PIXELSHADER)) {
2287 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2288 }
2289 }
2290
2291 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2292 if(stage >= GL_LIMITS(texture_stages)) {
2293 WARN("Bump env matrix of unsupported stage set\n");
2294 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2295 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2296 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2297 }
2298 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2299 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2300 checkGLcall("glTexBumpParameterfvATI");
2301 }
2302 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2303 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2304 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2305 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2306 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2307 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2308 */
2309 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2310
2311 if(mapped_stage < GL_LIMITS(textures)) {
2312 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2313 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2314
2315 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2316 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2317 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2318 }
2319 }
2320 }
2321
2322 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2323 /* This function is called by transform_view below if the view matrix was changed too
2324 *
2325 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2326 * does not always update the world matrix, only on a switch between transformed
2327 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2328 * draw, but that should be rather rare and cheaper in total.
2329 */
2330 glMatrixMode(GL_MODELVIEW);
2331 checkGLcall("glMatrixMode");
2332
2333 if(context->last_was_rhw) {
2334 glLoadIdentity();
2335 checkGLcall("glLoadIdentity()");
2336 } else {
2337 /* In the general case, the view matrix is the identity matrix */
2338 if (stateblock->wineD3DDevice->view_ident) {
2339 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2340 checkGLcall("glLoadMatrixf");
2341 } else {
2342 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2343 checkGLcall("glLoadMatrixf");
2344 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2345 checkGLcall("glMultMatrixf");
2346 }
2347 }
2348 }
2349
2350 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2351 UINT index = state - STATE_CLIPPLANE(0);
2352
2353 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2354 return;
2355 }
2356
2357 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2358 glMatrixMode(GL_MODELVIEW);
2359 glPushMatrix();
2360 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2361
2362 TRACE("Clipplane [%f,%f,%f,%f]\n",
2363 stateblock->clipplane[index][0],
2364 stateblock->clipplane[index][1],
2365 stateblock->clipplane[index][2],
2366 stateblock->clipplane[index][3]);
2367 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2368 checkGLcall("glClipPlane");
2369
2370 glPopMatrix();
2371 }
2372
2373 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2374 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2375 GLenum glMat;
2376 TRACE("Setting world matrix %d\n", matrix);
2377
2378 if(matrix >= GL_LIMITS(blends)) {
2379 WARN("Unsupported blend matrix set\n");
2380 return;
2381 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2382 return;
2383 }
2384
2385 /* GL_MODELVIEW0_ARB: 0x1700
2386 * GL_MODELVIEW1_ARB: 0x0x850a
2387 * GL_MODELVIEW2_ARB: 0x8722
2388 * GL_MODELVIEW3_ARB: 0x8723
2389 * etc
2390 * GL_MODELVIEW31_ARB: 0x873F
2391 */
2392 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2393 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2394
2395 glMatrixMode(glMat);
2396 checkGLcall("glMatrixMode(glMat)");
2397
2398 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2399 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2400 */
2401 if(stateblock->wineD3DDevice->view_ident) {
2402 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2403 checkGLcall("glLoadMatrixf")
2404 } else {
2405 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2406 checkGLcall("glLoadMatrixf")
2407 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2408 checkGLcall("glMultMatrixf")
2409 }
2410 }
2411
2412 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2413 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2414
2415 switch(val) {
2416 case WINED3DVBF_1WEIGHTS:
2417 case WINED3DVBF_2WEIGHTS:
2418 case WINED3DVBF_3WEIGHTS:
2419 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2420 glEnable(GL_VERTEX_BLEND_ARB);
2421 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2422
2423 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2424 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2425 */
2426 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2427
2428 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2429 int i;
2430 for(i = 1; i < GL_LIMITS(blends); i++) {
2431 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2432 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2433 }
2434 }
2435 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2436 }
2437 } else {
2438 /* TODO: Implement vertex blending in drawStridedSlow */
2439 FIXME("Vertex blending enabled, but not supported by hardware\n");
2440 }
2441 break;
2442
2443 case WINED3DVBF_DISABLE:
2444 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2445 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2446 glDisable(GL_VERTEX_BLEND_ARB);
2447 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2448 } else {
2449 TRACE("Vertex blending disabled\n");
2450 }
2451 break;
2452
2453 case WINED3DVBF_TWEENING:
2454 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2455 * vertex weights in the vertices?
2456 * For now we don't report that as supported, so a warn should suffice
2457 */
2458 WARN("Tweening not supported yet\n");
2459 break;
2460 }
2461 }
2462
2463 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2464 unsigned int k;
2465
2466 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2467 * NOTE: We have to reset the positions even if the light/plane is not currently
2468 * enabled, since the call to enable it will not reset the position.
2469 * NOTE2: Apparently texture transforms do NOT need reapplying
2470 */
2471
2472 PLIGHTINFOEL *light = NULL;
2473
2474 glMatrixMode(GL_MODELVIEW);
2475 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2476 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2477 checkGLcall("glLoadMatrixf(...)");
2478
2479 /* Reset lights. TODO: Call light apply func */
2480 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2481 light = stateblock->activeLights[k];
2482 if(!light) continue;
2483 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2484 checkGLcall("glLightfv posn");
2485 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2486 checkGLcall("glLightfv dirn");
2487 }
2488
2489 /* Reset Clipping Planes */
2490 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2491 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2492 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2493 }
2494 }
2495
2496 if(context->last_was_rhw) {
2497 glLoadIdentity();
2498 checkGLcall("glLoadIdentity()");
2499 /* No need to update the world matrix, the identity is fine */
2500 return;
2501 }
2502
2503 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2504 * No need to do it here if the state is scheduled for update.
2505 */
2506 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2507 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2508 }
2509
2510 /* Avoid looping over a number of matrices if the app never used the functionality */
2511 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2512 for(k = 1; k < GL_LIMITS(blends); k++) {
2513 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2514 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2515 }
2516 }
2517 }
2518 }
2519
2520 static const GLfloat invymat[16] = {
2521 1.0f, 0.0f, 0.0f, 0.0f,
2522 0.0f, -1.0f, 0.0f, 0.0f,
2523 0.0f, 0.0f, 1.0f, 0.0f,
2524 0.0f, 0.0f, 0.0f, 1.0f};
2525
2526 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2527 glMatrixMode(GL_PROJECTION);
2528 checkGLcall("glMatrixMode(GL_PROJECTION)");
2529 glLoadIdentity();
2530 checkGLcall("glLoadIdentity");
2531
2532 if(context->last_was_rhw) {
2533 double X, Y, height, width, minZ, maxZ;
2534
2535 X = stateblock->viewport.X;
2536 Y = stateblock->viewport.Y;
2537 height = stateblock->viewport.Height;
2538 width = stateblock->viewport.Width;
2539 minZ = stateblock->viewport.MinZ;
2540 maxZ = stateblock->viewport.MaxZ;
2541
2542 if(!stateblock->wineD3DDevice->untransformed) {
2543 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2544 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2545 * suppress depth clipping. This can be done because it is an orthogonal projection and
2546 * the Z coordinate does not affect the size of the primitives
2547 */
2548 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2549 if(stateblock->wineD3DDevice->render_offscreen) {
2550 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2551 } else {
2552 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2553 }
2554 } else {
2555 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2556 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2557 * unmodified to opengl.
2558 *
2559 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2560 * replacement shader.
2561 */
2562 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2563 if(stateblock->wineD3DDevice->render_offscreen) {
2564 glOrtho(X, X + width, -Y, -Y - height, 1.0, -1.0);
2565 } else {
2566 glOrtho(X, X + width, Y + height, Y, 1.0, -1.0);
2567 }
2568 }
2569 checkGLcall("glOrtho");
2570
2571 /* Window Coord 0 is the middle of the first pixel, so translate by 3/8 pixels */
2572 glTranslatef(0.375, 0.375, 0);
2573 checkGLcall("glTranslatef(0.375, 0.375, 0)");
2574 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2575 * render everything upside down when rendering offscreen. */
2576 if (stateblock->wineD3DDevice->render_offscreen) {
2577 glMultMatrixf(invymat);
2578 checkGLcall("glMultMatrixf(invymat)");
2579 }
2580 } else {
2581 /* The rule is that the window coordinate 0 does not correspond to the
2582 beginning of the first pixel, but the center of the first pixel.
2583 As a consequence if you want to correctly draw one line exactly from
2584 the left to the right end of the viewport (with all matrices set to
2585 be identity), the x coords of both ends of the line would be not
2586 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2587 instead. */
2588 glTranslatef(0.9 / stateblock->viewport.Width, -0.9 / stateblock->viewport.Height, 0);
2589 checkGLcall("glTranslatef (0.9 / width, -0.9 / height, 0)");
2590
2591 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2592 * render everything upside down when rendering offscreen. */
2593 if (stateblock->wineD3DDevice->render_offscreen) {
2594 glMultMatrixf(invymat);
2595 checkGLcall("glMultMatrixf(invymat)");
2596 }
2597 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2598 checkGLcall("glLoadMatrixf");
2599 }
2600 }
2601
2602 /* This should match any arrays loaded in loadVertexData.
2603 * stateblock impl is required for GL_SUPPORT
2604 * TODO: Only load / unload arrays if we have to.
2605 */
2606 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2607 glDisableClientState(GL_VERTEX_ARRAY);
2608 glDisableClientState(GL_NORMAL_ARRAY);
2609 glDisableClientState(GL_COLOR_ARRAY);
2610 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2611 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2612 }
2613 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2614 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2615 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2616 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2617 }
2618 unloadTexCoords(stateblock);
2619 }
2620
2621 /* This should match any arrays loaded in loadNumberedArrays
2622 * TODO: Only load / unload arrays if we have to.
2623 */
2624 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2625 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2626 GLint maxAttribs;
2627 int i;
2628
2629 /* Leave all the attribs disabled */
2630 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2631 /* MESA does not support it right not */
2632 if (glGetError() != GL_NO_ERROR)
2633 maxAttribs = 16;
2634 for (i = 0; i < maxAttribs; ++i) {
2635 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2636 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2637 }
2638 }
2639
2640 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2641 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2642 int i;
2643 UINT *offset = stateblock->streamOffset;
2644
2645 /* Default to no instancing */
2646 stateblock->wineD3DDevice->instancedDraw = FALSE;
2647
2648 for (i = 0; i < MAX_ATTRIBS; i++) {
2649
2650 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2651 continue;
2652
2653 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2654 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2655 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2656 stateblock->wineD3DDevice->instancedDraw = TRUE;
2657 continue;
2658 }
2659
2660 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2661
2662 if(strided->u.input[i].dwStride) {
2663 if(curVBO != strided->u.input[i].VBO) {
2664 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2665 checkGLcall("glBindBufferARB");
2666 curVBO = strided->u.input[i].VBO;
2667 }
2668 GL_EXTCALL(glVertexAttribPointerARB(i,
2669 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2670 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2671 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2672 strided->u.input[i].dwStride,
2673 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2674 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2675 } else {
2676 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2677 * set up the attribute statically. But we have to figure out the system memory address.
2678 */
2679 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2680 if(strided->u.input[i].VBO) {
2681 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2682 ptr += (long) vb->resource.allocatedMemory;
2683 }
2684 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2685
2686 switch(strided->u.input[i].dwType) {
2687 case WINED3DDECLTYPE_FLOAT1:
2688 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2689 break;
2690 case WINED3DDECLTYPE_FLOAT2:
2691 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2692 break;
2693 case WINED3DDECLTYPE_FLOAT3:
2694 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2695 break;
2696 case WINED3DDECLTYPE_FLOAT4:
2697 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2698 break;
2699
2700 case WINED3DDECLTYPE_UBYTE4:
2701 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2702 break;
2703 case WINED3DDECLTYPE_UBYTE4N:
2704 case WINED3DDECLTYPE_D3DCOLOR:
2705 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2706 break;
2707
2708 case WINED3DDECLTYPE_SHORT2:
2709 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2710 break;
2711 case WINED3DDECLTYPE_SHORT4:
2712 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2713 break;
2714
2715 case WINED3DDECLTYPE_SHORT2N:
2716 {
2717 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2718 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2719 break;
2720 }
2721 case WINED3DDECLTYPE_USHORT2N:
2722 {
2723 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2724 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2725 break;
2726 }
2727 case WINED3DDECLTYPE_SHORT4N:
2728 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2729 break;
2730 case WINED3DDECLTYPE_USHORT4N:
2731 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2732 break;
2733
2734 case WINED3DDECLTYPE_UDEC3:
2735 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2736 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2737 break;
2738 case WINED3DDECLTYPE_DEC3N:
2739 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2740 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2741 break;
2742
2743 case WINED3DDECLTYPE_FLOAT16_2:
2744 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2745 * byte float according to the IEEE standard
2746 */
2747 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2748 break;
2749 case WINED3DDECLTYPE_FLOAT16_4:
2750 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2751 break;
2752
2753 case WINED3DDECLTYPE_UNUSED:
2754 default:
2755 ERR("Unexpected declaration in stride 0 attributes\n");
2756 break;
2757
2758 }
2759 }
2760 }
2761 }
2762
2763 /* Used from 2 different functions, and too big to justify making it inlined */
2764 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2765 UINT *offset = stateblock->streamOffset;
2766 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2767
2768 TRACE("Using fast vertex array code\n");
2769
2770 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2771 stateblock->wineD3DDevice->instancedDraw = FALSE;
2772
2773 /* Blend Data ---------------------------------------------- */
2774 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2775 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2776
2777 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2778 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2779 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2780
2781 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
2782 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
2783
2784 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
2785
2786 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
2787 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
2788 sd->u.s.blendWeights.dwStride,
2789 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
2790
2791 if(curVBO != sd->u.s.blendWeights.VBO) {
2792 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
2793 checkGLcall("glBindBufferARB");
2794 curVBO = sd->u.s.blendWeights.VBO;
2795 }
2796
2797 GL_EXTCALL(glWeightPointerARB)(
2798 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2799 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2800 sd->u.s.blendWeights.dwStride,
2801 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2802
2803 checkGLcall("glWeightPointerARB");
2804
2805 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
2806 static BOOL showfixme = TRUE;
2807 if(showfixme){
2808 FIXME("blendMatrixIndices support\n");
2809 showfixme = FALSE;
2810 }
2811 }
2812 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2813 /* FIXME("TODO\n");*/
2814 #if 0
2815
2816 GL_EXTCALL(glVertexWeightPointerEXT)(
2817 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2818 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2819 sd->u.s.blendWeights.dwStride,
2820 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
2821 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
2822 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2823 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
2824 #endif
2825
2826 } else {
2827 /* TODO: support blends in drawStridedSlow
2828 * No need to write a FIXME here, this is done after the general vertex decl decoding
2829 */
2830 WARN("unsupported blending in openGl\n");
2831 }
2832 } else {
2833 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2834 static const GLbyte one = 1;
2835 GL_EXTCALL(glWeightbvARB(1, &one));
2836 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
2837 }
2838 }
2839
2840 #if 0 /* FOG ----------------------------------------------*/
2841 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
2842 /* TODO: fog*/
2843 if (GL_SUPPORT(EXT_FOG_COORD) {
2844 glEnableClientState(GL_FOG_COORDINATE_EXT);
2845 (GL_EXTCALL)(FogCoordPointerEXT)(
2846 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
2847 sd->u.s.fog.dwStride,
2848 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
2849 } else {
2850 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
2851 /* FIXME: fixme once */
2852 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
2853 }
2854 } else {
2855 if (GL_SUPPRT(EXT_FOR_COORD) {
2856 /* make sure fog is disabled */
2857 glDisableClientState(GL_FOG_COORDINATE_EXT);
2858 }
2859 }
2860 #endif
2861
2862 #if 0 /* tangents ----------------------------------------------*/
2863 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
2864 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2865 /* TODO: tangents*/
2866 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2867 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
2868 glEnable(GL_TANGENT_ARRAY_EXT);
2869 (GL_EXTCALL)(TangentPointerEXT)(
2870 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
2871 sd->u.s.tangent.dwStride,
2872 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
2873 } else {
2874 glDisable(GL_TANGENT_ARRAY_EXT);
2875 }
2876 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
2877 glEnable(GL_BINORMAL_ARRAY_EXT);
2878 (GL_EXTCALL)(BinormalPointerEXT)(
2879 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
2880 sd->u.s.binormal.dwStride,
2881 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
2882 } else{
2883 glDisable(GL_BINORMAL_ARRAY_EXT);
2884 }
2885
2886 } else {
2887 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
2888 /* FIXME: fixme once */
2889 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
2890 }
2891 } else {
2892 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
2893 /* make sure fog is disabled */
2894 glDisable(GL_TANGENT_ARRAY_EXT);
2895 glDisable(GL_BINORMAL_ARRAY_EXT);
2896 }
2897 }
2898 #endif
2899
2900 /* Point Size ----------------------------------------------*/
2901 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
2902
2903 /* no such functionality in the fixed function GL pipeline */
2904 TRACE("Cannot change ptSize here in openGl\n");
2905 /* TODO: Implement this function in using shaders if they are available */
2906
2907 }
2908
2909 /* Vertex Pointers -----------------------------------------*/
2910 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
2911 /* Note dwType == float3 or float4 == 2 or 3 */
2912 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
2913 sd->u.s.position.dwStride,
2914 sd->u.s.position.dwType + 1,
2915 sd->u.s.position.lpData));
2916
2917 if(curVBO != sd->u.s.position.VBO) {
2918 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
2919 checkGLcall("glBindBufferARB");
2920 curVBO = sd->u.s.position.VBO;
2921 }
2922
2923 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
2924 handling for rhw mode should not impact screen position whereas in GL it does.
2925 This may result in very slightly distored textures in rhw mode, but
2926 a very minimal different. There's always the other option of
2927 fixing the view matrix to prevent w from having any effect
2928
2929 This only applies to user pointer sources, in VBOs the vertices are fixed up
2930 */
2931 if(sd->u.s.position.VBO == 0) {
2932 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
2933 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2934 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2935 } else {
2936 glVertexPointer(
2937 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
2938 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
2939 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
2940 }
2941 checkGLcall("glVertexPointer(...)");
2942 glEnableClientState(GL_VERTEX_ARRAY);
2943 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
2944 }
2945
2946 /* Normals -------------------------------------------------*/
2947 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
2948 /* Note dwType == float3 or float4 == 2 or 3 */
2949 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
2950 sd->u.s.normal.dwStride,
2951 sd->u.s.normal.lpData));
2952 if(curVBO != sd->u.s.normal.VBO) {
2953 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
2954 checkGLcall("glBindBufferARB");
2955 curVBO = sd->u.s.normal.VBO;
2956 }
2957 glNormalPointer(
2958 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
2959 sd->u.s.normal.dwStride,
2960 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
2961 checkGLcall("glNormalPointer(...)");
2962 glEnableClientState(GL_NORMAL_ARRAY);
2963 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
2964
2965 } else {
2966 glNormal3f(0, 0, 1);
2967 checkGLcall("glNormal3f(0, 0, 1)");
2968 }
2969
2970 /* Diffuse Colour --------------------------------------------*/
2971 /* WARNING: Data here MUST be in RGBA format, so cannot */
2972 /* go directly into fast mode from app pgm, because */
2973 /* directx requires data in BGRA format. */
2974 /* currently fixupVertices swizels the format, but this isn't */
2975 /* very practical when using VBOS */
2976 /* NOTE: Unless we write a vertex shader to swizel the colour */
2977 /* , or the user doesn't care and wants the speed advantage */
2978
2979 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
2980 /* Note dwType == float3 or float4 == 2 or 3 */
2981 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
2982 sd->u.s.diffuse.dwStride,
2983 sd->u.s.diffuse.lpData));
2984
2985 if(curVBO != sd->u.s.diffuse.VBO) {
2986 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
2987 checkGLcall("glBindBufferARB");
2988 curVBO = sd->u.s.diffuse.VBO;
2989 }
2990 glColorPointer(4, GL_UNSIGNED_BYTE,
2991 sd->u.s.diffuse.dwStride,
2992 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
2993 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
2994 glEnableClientState(GL_COLOR_ARRAY);
2995 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
2996
2997 } else {
2998 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
2999 checkGLcall("glColor4f(1, 1, 1, 1)");
3000 }
3001
3002 /* Specular Colour ------------------------------------------*/
3003 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3004 TRACE("setting specular colour\n");
3005 /* Note dwType == float3 or float4 == 2 or 3 */
3006 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3007 sd->u.s.specular.dwStride,
3008 sd->u.s.specular.lpData));
3009 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3010 if(curVBO != sd->u.s.specular.VBO) {
3011 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3012 checkGLcall("glBindBufferARB");
3013 curVBO = sd->u.s.specular.VBO;
3014 }
3015 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3016 sd->u.s.specular.dwStride,
3017 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3018 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3019 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3020 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3021 } else {
3022
3023 /* Missing specular color is not critical, no warnings */
3024 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3025 }
3026
3027 } else {
3028 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3029 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3030 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3031 } else {
3032
3033 /* Missing specular color is not critical, no warnings */
3034 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3035 }
3036 }
3037
3038 /* Texture coords -------------------------------------------*/
3039 loadTexCoords(stateblock, sd, &curVBO);
3040 }
3041
3042 static inline void drawPrimitiveTraceDataLocations(
3043 WineDirect3DVertexStridedData *dataLocations) {
3044
3045 /* Dump out what parts we have supplied */
3046 TRACE("Strided Data:\n");
3047 TRACE_STRIDED((dataLocations), position);
3048 TRACE_STRIDED((dataLocations), blendWeights);
3049 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3050 TRACE_STRIDED((dataLocations), normal);
3051 TRACE_STRIDED((dataLocations), pSize);
3052 TRACE_STRIDED((dataLocations), diffuse);
3053 TRACE_STRIDED((dataLocations), specular);
3054 TRACE_STRIDED((dataLocations), texCoords[0]);
3055 TRACE_STRIDED((dataLocations), texCoords[1]);
3056 TRACE_STRIDED((dataLocations), texCoords[2]);
3057 TRACE_STRIDED((dataLocations), texCoords[3]);
3058 TRACE_STRIDED((dataLocations), texCoords[4]);
3059 TRACE_STRIDED((dataLocations), texCoords[5]);
3060 TRACE_STRIDED((dataLocations), texCoords[6]);
3061 TRACE_STRIDED((dataLocations), texCoords[7]);
3062 TRACE_STRIDED((dataLocations), position2);
3063 TRACE_STRIDED((dataLocations), normal2);
3064 TRACE_STRIDED((dataLocations), tangent);
3065 TRACE_STRIDED((dataLocations), binormal);
3066 TRACE_STRIDED((dataLocations), tessFactor);
3067 TRACE_STRIDED((dataLocations), fog);
3068 TRACE_STRIDED((dataLocations), depth);
3069 TRACE_STRIDED((dataLocations), sample);
3070
3071 return;
3072 }
3073
3074 /* Helper for vertexdeclaration() */
3075 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3076 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3077 BOOL fixup = FALSE;
3078 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3079
3080 if(device->up_strided) {
3081 /* Note: this is a ddraw fixed-function code path */
3082 TRACE("================ Strided Input ===================\n");
3083 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3084
3085 if(TRACE_ON(d3d)) {
3086 drawPrimitiveTraceDataLocations(dataLocations);
3087 }
3088 } else {
3089 /* Note: This is a fixed function or shader codepath.
3090 * This means it must handle both types of strided data.
3091 * Shaders must go through here to zero the strided data, even if they
3092 * don't set any declaration at all
3093 */
3094 TRACE("================ Vertex Declaration ===================\n");
3095 memset(dataLocations, 0, sizeof(*dataLocations));
3096 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3097 useVertexShaderFunction, dataLocations, &fixup);
3098 }
3099
3100 if (dataLocations->u.s.position_transformed) {
3101 useVertexShaderFunction = FALSE;
3102 }
3103
3104 /* Unload the old arrays before loading the new ones to get old junk out */
3105 if(context->numberedArraysLoaded) {
3106 unloadNumberedArrays(stateblock);
3107 context->numberedArraysLoaded = FALSE;
3108 }
3109 if(context->namedArraysLoaded) {
3110 unloadVertexData(stateblock);
3111 context->namedArraysLoaded = FALSE;
3112 }
3113
3114 if(useVertexShaderFunction) {
3115 TRACE("Loading numbered arrays\n");
3116 loadNumberedArrays(stateblock, dataLocations);
3117 device->useDrawStridedSlow = FALSE;
3118 context->numberedArraysLoaded = TRUE;
3119 } else if (fixup ||
3120 (dataLocations->u.s.pSize.lpData == NULL &&
3121 dataLocations->u.s.diffuse.lpData == NULL &&
3122 dataLocations->u.s.specular.lpData == NULL)) {
3123 /* Load the vertex data using named arrays */
3124 TRACE("Loading vertex data\n");
3125 loadVertexData(stateblock, dataLocations);
3126 device->useDrawStridedSlow = FALSE;
3127 context->namedArraysLoaded = TRUE;
3128 } else {
3129 TRACE("Not loading vertex data\n");
3130 device->useDrawStridedSlow = TRUE;
3131 }
3132
3133 /* Generate some fixme's if unsupported functionality is being used */
3134 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3135 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3136 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3137 FIXME("Tweening is only valid with vertex shaders\n");
3138 }
3139 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3140 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3141 }
3142 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3143 FIXME("Extended attributes are only valid with vertex shaders\n");
3144 }
3145 #undef BUFFER_OR_DATA
3146 }
3147
3148 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3149 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3150 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3151 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3152 BOOL transformed;
3153 /* Some stuff is in the device until we have per context tracking */
3154 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3155 BOOL wasrhw = context->last_was_rhw;
3156
3157 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3158 * here simply check whether a shader was set, or the user disabled shaders
3159 */
3160 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3161 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3162 useVertexShaderFunction = TRUE;
3163
3164 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3165 updateFog = TRUE;
3166 }
3167 } else if(context->last_was_foggy_shader) {
3168 updateFog = TRUE;
3169 }
3170
3171 handleStreams(stateblock, useVertexShaderFunction, context);
3172
3173 transformed = device->strided_streams.u.s.position_transformed;
3174 if (transformed) useVertexShaderFunction = FALSE;
3175
3176 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3177 updateFog = TRUE;
3178 }
3179
3180 /* Reapply lighting if it is not scheduled for reapplication already */
3181 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3182 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3183 }
3184
3185 if (transformed) {
3186 context->last_was_rhw = TRUE;
3187 } else {
3188
3189 /* Untransformed, so relies on the view and projection matrices */
3190 context->last_was_rhw = FALSE;
3191 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3192 device->untransformed = TRUE;
3193
3194 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3195 * Not needed as long as only hw shaders are supported
3196 */
3197
3198 /* This sets the shader output position correction constants.
3199 * TODO: Move to the viewport state
3200 */
3201 if (useVertexShaderFunction) {
3202 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3203 }
3204 }
3205
3206 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3207 * off this function will be called again anyway to make sure they're properly set
3208 */
3209 if(!useVertexShaderFunction) {
3210 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3211 * or transformed / untransformed was switched
3212 */
3213 if(wasrhw != context->last_was_rhw &&
3214 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3215 !isStateDirty(context, STATE_VIEWPORT)) {
3216 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3217 }
3218 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3219 * mode.
3220 *
3221 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3222 * this check will fail and the matrix not applied again. This is OK because a simple
3223 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3224 * needs of the vertex declaration.
3225 *
3226 * World and view matrix go into the same gl matrix, so only apply them when neither is
3227 * dirty
3228 */
3229 if(transformed != wasrhw &&
3230 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3231 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3232 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3233 }
3234
3235 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3236 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3237 }
3238
3239 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3240 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3241 }
3242 } else {
3243 /* We compile the shader here because we need the vertex declaration
3244 * in order to determine if we need to do any swizzling for D3DCOLOR
3245 * registers. If the shader is already compiled this call will do nothing. */
3246 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3247
3248 if(!context->last_was_vshader) {
3249 int i;
3250 static BOOL warned = FALSE;
3251 /* Disable all clip planes to get defined results on all drivers. See comment in the
3252 * state_clipping state handler
3253 */
3254 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3255 glDisable(GL_CLIP_PLANE0 + i);
3256 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3257 }
3258
3259 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3260 FIXME("Clipping not supported with vertex shaders\n");
3261 warned = TRUE;
3262 }
3263 }
3264 }
3265
3266 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3267 * application
3268 */
3269 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3270 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3271
3272 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3273 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3274 }
3275 }
3276
3277 context->last_was_vshader = useVertexShaderFunction;
3278
3279 if(updateFog) {
3280 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3281 }
3282 }
3283
3284 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3285 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3286 checkGLcall("glDepthRange");
3287 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3288 */
3289 if(stateblock->wineD3DDevice->render_offscreen) {
3290 glViewport(stateblock->viewport.X,
3291 stateblock->viewport.Y,
3292 stateblock->viewport.Width, stateblock->viewport.Height);
3293 } else {
3294 glViewport(stateblock->viewport.X,
3295 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3296 stateblock->viewport.Width, stateblock->viewport.Height);
3297 }
3298
3299 checkGLcall("glViewport");
3300
3301 stateblock->wineD3DDevice->posFixup[2] = 0.9 / stateblock->viewport.Width;
3302 stateblock->wineD3DDevice->posFixup[3] = -0.9 / stateblock->viewport.Height;
3303 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3304 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3305 }
3306
3307 }
3308
3309 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3310 UINT Index = state - STATE_ACTIVELIGHT(0);
3311 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3312
3313 if(!lightInfo) {
3314 glDisable(GL_LIGHT0 + Index);
3315 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3316 } else {
3317 float quad_att;
3318 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3319
3320 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3321 glMatrixMode(GL_MODELVIEW);
3322 glPushMatrix();
3323 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3324
3325 /* Diffuse: */
3326 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3327 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3328 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3329 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3330 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3331 checkGLcall("glLightfv");
3332
3333 /* Specular */
3334 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3335 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3336 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3337 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3338 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3339 checkGLcall("glLightfv");
3340
3341 /* Ambient */
3342 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3343 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3344 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3345 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3346 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3347 checkGLcall("glLightfv");
3348
3349 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3350 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3351 } else {
3352 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3353 }
3354
3355 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3356 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3357 * Attenuation0 to NaN and crashes in the gl lib
3358 */
3359
3360 switch (lightInfo->OriginalParms.Type) {
3361 case WINED3DLIGHT_POINT:
3362 /* Position */
3363 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3364 checkGLcall("glLightfv");
3365 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3366 checkGLcall("glLightf");
3367 /* Attenuation - Are these right? guessing... */
3368 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3369 checkGLcall("glLightf");
3370 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3371 checkGLcall("glLightf");
3372 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3373 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3374 checkGLcall("glLightf");
3375 /* FIXME: Range */
3376 break;
3377
3378 case WINED3DLIGHT_SPOT:
3379 /* Position */
3380 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3381 checkGLcall("glLightfv");
3382 /* Direction */
3383 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3384 checkGLcall("glLightfv");
3385 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3386 checkGLcall("glLightf");
3387 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3388 checkGLcall("glLightf");
3389 /* Attenuation - Are these right? guessing... */
3390 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3391 checkGLcall("glLightf");
3392 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3393 checkGLcall("glLightf");
3394 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3395 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3396 checkGLcall("glLightf");
3397 /* FIXME: Range */
3398 break;
3399
3400 case WINED3DLIGHT_DIRECTIONAL:
3401 /* Direction */
3402 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3403 checkGLcall("glLightfv");
3404 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3405 checkGLcall("glLightf");
3406 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3407 checkGLcall("glLightf");
3408 break;
3409
3410 default:
3411 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3412 }
3413
3414 /* Restore the modelview matrix */
3415 glPopMatrix();
3416
3417 glEnable(GL_LIGHT0 + Index);
3418 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3419 }
3420
3421 return;
3422 }
3423
3424 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3425 IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) stateblock->wineD3DDevice->swapchains[0];
3426 RECT *pRect = &stateblock->scissorRect;
3427 RECT windowRect;
3428 UINT winHeight;
3429
3430 GetClientRect(swapchain->win_handle, &windowRect);
3431 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3432 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3433 */
3434 winHeight = windowRect.bottom - windowRect.top;
3435 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3436 pRect->right - pRect->left, pRect->bottom - pRect->top);
3437
3438 if (stateblock->wineD3DDevice->render_offscreen) {
3439 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3440 } else {
3441 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3442 }
3443 checkGLcall("glScissor");
3444 }
3445
3446 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3447 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3448 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3449 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3450 } else {
3451 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3452 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3453 }
3454 }
3455 }
3456
3457 const struct StateEntry StateTable[] =
3458 {
3459 /* State name representative, apply function */
3460 { /* 0, Undefined */ 0, state_undefined },
3461 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3462 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3463 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3464 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3465 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3466 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3467 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3468 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3469 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3470 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3471 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3472 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3473 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3474 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3475 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3476 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3477 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3478 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3479 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3480 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3481 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3482 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3483 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3484 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3485 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3486 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3487 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3488 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3489 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3490 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3491 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3492 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3493 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3494 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3495 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3496 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3497 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3498 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3499 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3500 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3501 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3502 { /* 42, undefined */ 0, state_undefined },
3503 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3504 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3505 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3506 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3507 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3508 { /* 48, WINED3DRS_RANGEFOGENABLE */ 0, state_nogl },
3509 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3510 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3511 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3512 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3513 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3514 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3515 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3516 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3517 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3518 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3519 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3520 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3521 { /* 61, Undefined */ 0, state_undefined },
3522 { /* 62, Undefined */ 0, state_undefined },
3523 { /* 63, Undefined */ 0, state_undefined },
3524 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3525 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3526 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3527 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3528 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3529 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3530 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3531 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3532 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3533 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3534 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3535 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3536 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3537 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3538 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3539 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3540 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3541 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3542 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3543 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3544 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3545 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3546 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3547 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3548 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3549 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3550 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3551 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3552 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3553 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3554 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3555 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3556 { /* 96, Undefined */ 0, state_undefined },
3557 { /* 97, Undefined */ 0, state_undefined },
3558 { /* 98, Undefined */ 0, state_undefined },
3559 { /* 99, Undefined */ 0, state_undefined },
3560 { /*100, Undefined */ 0, state_undefined },
3561 { /*101, Undefined */ 0, state_undefined },
3562 { /*102, Undefined */ 0, state_undefined },
3563 { /*103, Undefined */ 0, state_undefined },
3564 { /*104, Undefined */ 0, state_undefined },
3565 { /*105, Undefined */ 0, state_undefined },
3566 { /*106, Undefined */ 0, state_undefined },
3567 { /*107, Undefined */ 0, state_undefined },
3568 { /*108, Undefined */ 0, state_undefined },
3569 { /*109, Undefined */ 0, state_undefined },
3570 { /*110, Undefined */ 0, state_undefined },
3571 { /*111, Undefined */ 0, state_undefined },
3572 { /*112, Undefined */ 0, state_undefined },
3573 { /*113, Undefined */ 0, state_undefined },
3574 { /*114, Undefined */ 0, state_undefined },
3575 { /*115, Undefined */ 0, state_undefined },
3576 { /*116, Undefined */ 0, state_undefined },
3577 { /*117, Undefined */ 0, state_undefined },
3578 { /*118, Undefined */ 0, state_undefined },
3579 { /*119, Undefined */ 0, state_undefined },
3580 { /*120, Undefined */ 0, state_undefined },
3581 { /*121, Undefined */ 0, state_undefined },
3582 { /*122, Undefined */ 0, state_undefined },
3583 { /*123, Undefined */ 0, state_undefined },
3584 { /*124, Undefined */ 0, state_undefined },
3585 { /*125, Undefined */ 0, state_undefined },
3586 { /*126, Undefined */ 0, state_undefined },
3587 { /*127, Undefined */ 0, state_undefined },
3588 /* Big hole ends */
3589 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3590 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3591 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3592 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3593 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3594 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3595 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3596 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3597 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3598 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3599 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3600 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3601 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3602 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3603 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3604 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3605 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3606 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3607 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3608 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3609 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3610 { /*149, Undefined */ 0, state_undefined },
3611 { /*150, Undefined */ 0, state_undefined },
3612 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3613 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3614 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3615 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
3616 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3617 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3618 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3619 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3620 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3621 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3622 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3623 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3624 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3625 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3626 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3627 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3628 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3629 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3630 { /*169, Undefined */ 0, state_undefined },
3631 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3632 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3633 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3634 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3635 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3636 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3637 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3638 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3639 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3640 { /*177, undefined */ 0, state_undefined },
3641 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3642 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3643 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3644 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3645 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3646 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3647 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3648 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3649 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3650 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3651 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3652 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3653 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3654 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3655 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3656 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3657 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite },
3658 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3659 { /*196, undefined */ 0, state_undefined },
3660 { /*197, undefined */ 0, state_undefined },
3661 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3662 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3663 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3664 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3665 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3666 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3667 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3668 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3669 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3670 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3671 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3672 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3673 /* Texture stage states */
3674 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3675 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3676 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3677 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3678 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3679 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3680 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3681 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3682 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3683 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3684 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3685 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3686 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3687 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3688 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3689 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3690 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3691 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3692 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3693 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3694 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3695 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3696 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3697 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3698 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3699 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3700 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3701 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3702 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3703 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3704 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3705 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3706
3707 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3708 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3709 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3710 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3711 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3712 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3713 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3714 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3715 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3716 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3717 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3718 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3719 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3720 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3721 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3722 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3723 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3724 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3725 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3726 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3727 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3728 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3729 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3730 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3731 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3732 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3733 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3734 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3735 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3736 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3737 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3738 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3739
3740 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3741 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3742 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3743 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3744 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3745 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3746 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3747 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3748 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3749 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3750 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3751 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3752 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3753 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3754 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3755 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3756 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3757 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3758 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3759 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3760 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3761 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3762 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3763 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3764 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3765 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3766 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3767 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
3768 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3769 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3770 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3771 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3772
3773 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3774 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3775 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3776 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3777 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3778 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3779 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3780 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3781 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3782 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3783 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3784 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3785 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3786 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3787 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3788 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3789 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3790 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3791 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3792 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3793 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3794 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3795 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3796 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3797 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3798 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3799 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3800 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
3801 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3802 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3803 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3804 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3805
3806 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3807 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3808 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3809 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3810 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3811 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3812 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3813 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3814 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3815 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3816 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3817 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3818 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3819 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3820 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3821 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3822 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3823 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3824 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3825 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3826 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3827 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3828 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3829 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3830 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3831 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3832 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3833 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
3834 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3835 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3836 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3837 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3838
3839 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3840 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3841 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3842 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3843 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3844 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3845 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3846 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3847 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3848 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3849 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3850 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3851 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3852 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3853 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3854 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3855 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3856 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3857 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3858 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3859 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3860 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3861 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3862 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3863 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3864 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3865 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3866 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
3867 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3868 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3869 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3870 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3871
3872 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3873 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3874 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3875 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3876 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3877 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3878 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3879 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3880 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3881 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3882 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3883 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3884 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3885 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3886 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3887 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3888 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3889 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3890 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3891 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3892 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3893 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3894 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3895 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3896 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3897 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
3898 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
3899 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
3900 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3901 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3902 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3903 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3904
3905 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3906 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3907 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3908 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3909 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3910 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3911 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3912 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3913 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3914 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3915 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3916 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3917 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3918 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3919 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3920 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3921 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3922 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3923 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3924 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3925 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3926 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3927 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3928 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3929 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3930 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
3931 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
3932 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
3933 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3934 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3935 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3936 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3937 /* Sampler states */
3938 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
3939 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
3940 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
3941 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
3942 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
3943 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
3944 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
3945 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
3946 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
3947 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
3948 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
3949 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
3950 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
3951 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
3952 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
3953 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
3954 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
3955 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
3956 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
3957 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
3958 /* Pixel shader */
3959 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
3960 /* Transform states follow */
3961 { /* 1, undefined */ 0, state_undefined },
3962 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
3963 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
3964 { /* 4, undefined */ 0, state_undefined },
3965 { /* 5, undefined */ 0, state_undefined },
3966 { /* 6, undefined */ 0, state_undefined },
3967 { /* 7, undefined */ 0, state_undefined },
3968 { /* 8, undefined */ 0, state_undefined },
3969 { /* 9, undefined */ 0, state_undefined },
3970 { /* 10, undefined */ 0, state_undefined },
3971 { /* 11, undefined */ 0, state_undefined },
3972 { /* 12, undefined */ 0, state_undefined },
3973 { /* 13, undefined */ 0, state_undefined },
3974 { /* 14, undefined */ 0, state_undefined },
3975 { /* 15, undefined */ 0, state_undefined },
3976 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3977 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3978 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3979 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3980 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3981 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
3982 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
3983 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
3984 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
3985 { /* 24, undefined */ 0, state_undefined },
3986 { /* 25, undefined */ 0, state_undefined },
3987 { /* 26, undefined */ 0, state_undefined },
3988 { /* 27, undefined */ 0, state_undefined },
3989 { /* 28, undefined */ 0, state_undefined },
3990 { /* 29, undefined */ 0, state_undefined },
3991 { /* 30, undefined */ 0, state_undefined },
3992 { /* 31, undefined */ 0, state_undefined },
3993 { /* 32, undefined */ 0, state_undefined },
3994 { /* 33, undefined */ 0, state_undefined },
3995 { /* 34, undefined */ 0, state_undefined },
3996 { /* 35, undefined */ 0, state_undefined },
3997 { /* 36, undefined */ 0, state_undefined },
3998 { /* 37, undefined */ 0, state_undefined },
3999 { /* 38, undefined */ 0, state_undefined },
4000 { /* 39, undefined */ 0, state_undefined },
4001 { /* 40, undefined */ 0, state_undefined },
4002 { /* 41, undefined */ 0, state_undefined },
4003 { /* 42, undefined */ 0, state_undefined },
4004 { /* 43, undefined */ 0, state_undefined },
4005 { /* 44, undefined */ 0, state_undefined },
4006 { /* 45, undefined */ 0, state_undefined },
4007 { /* 46, undefined */ 0, state_undefined },
4008 { /* 47, undefined */ 0, state_undefined },
4009 { /* 48, undefined */ 0, state_undefined },
4010 { /* 49, undefined */ 0, state_undefined },
4011 { /* 50, undefined */ 0, state_undefined },
4012 { /* 51, undefined */ 0, state_undefined },
4013 { /* 52, undefined */ 0, state_undefined },
4014 { /* 53, undefined */ 0, state_undefined },
4015 { /* 54, undefined */ 0, state_undefined },
4016 { /* 55, undefined */ 0, state_undefined },
4017 { /* 56, undefined */ 0, state_undefined },
4018 { /* 57, undefined */ 0, state_undefined },
4019 { /* 58, undefined */ 0, state_undefined },
4020 { /* 59, undefined */ 0, state_undefined },
4021 { /* 60, undefined */ 0, state_undefined },
4022 { /* 61, undefined */ 0, state_undefined },
4023 { /* 62, undefined */ 0, state_undefined },
4024 { /* 63, undefined */ 0, state_undefined },
4025 { /* 64, undefined */ 0, state_undefined },
4026 { /* 65, undefined */ 0, state_undefined },
4027 { /* 66, undefined */ 0, state_undefined },
4028 { /* 67, undefined */ 0, state_undefined },
4029 { /* 68, undefined */ 0, state_undefined },
4030 { /* 69, undefined */ 0, state_undefined },
4031 { /* 70, undefined */ 0, state_undefined },
4032 { /* 71, undefined */ 0, state_undefined },
4033 { /* 72, undefined */ 0, state_undefined },
4034 { /* 73, undefined */ 0, state_undefined },
4035 { /* 74, undefined */ 0, state_undefined },
4036 { /* 75, undefined */ 0, state_undefined },
4037 { /* 76, undefined */ 0, state_undefined },
4038 { /* 77, undefined */ 0, state_undefined },
4039 { /* 78, undefined */ 0, state_undefined },
4040 { /* 79, undefined */ 0, state_undefined },
4041 { /* 80, undefined */ 0, state_undefined },
4042 { /* 81, undefined */ 0, state_undefined },
4043 { /* 82, undefined */ 0, state_undefined },
4044 { /* 83, undefined */ 0, state_undefined },
4045 { /* 84, undefined */ 0, state_undefined },
4046 { /* 85, undefined */ 0, state_undefined },
4047 { /* 86, undefined */ 0, state_undefined },
4048 { /* 87, undefined */ 0, state_undefined },
4049 { /* 88, undefined */ 0, state_undefined },
4050 { /* 89, undefined */ 0, state_undefined },
4051 { /* 90, undefined */ 0, state_undefined },
4052 { /* 91, undefined */ 0, state_undefined },
4053 { /* 92, undefined */ 0, state_undefined },
4054 { /* 93, undefined */ 0, state_undefined },
4055 { /* 94, undefined */ 0, state_undefined },
4056 { /* 95, undefined */ 0, state_undefined },
4057 { /* 96, undefined */ 0, state_undefined },
4058 { /* 97, undefined */ 0, state_undefined },
4059 { /* 98, undefined */ 0, state_undefined },
4060 { /* 99, undefined */ 0, state_undefined },
4061 { /*100, undefined */ 0, state_undefined },
4062 { /*101, undefined */ 0, state_undefined },
4063 { /*102, undefined */ 0, state_undefined },
4064 { /*103, undefined */ 0, state_undefined },
4065 { /*104, undefined */ 0, state_undefined },
4066 { /*105, undefined */ 0, state_undefined },
4067 { /*106, undefined */ 0, state_undefined },
4068 { /*107, undefined */ 0, state_undefined },
4069 { /*108, undefined */ 0, state_undefined },
4070 { /*109, undefined */ 0, state_undefined },
4071 { /*110, undefined */ 0, state_undefined },
4072 { /*111, undefined */ 0, state_undefined },
4073 { /*112, undefined */ 0, state_undefined },
4074 { /*113, undefined */ 0, state_undefined },
4075 { /*114, undefined */ 0, state_undefined },
4076 { /*115, undefined */ 0, state_undefined },
4077 { /*116, undefined */ 0, state_undefined },
4078 { /*117, undefined */ 0, state_undefined },
4079 { /*118, undefined */ 0, state_undefined },
4080 { /*119, undefined */ 0, state_undefined },
4081 { /*120, undefined */ 0, state_undefined },
4082 { /*121, undefined */ 0, state_undefined },
4083 { /*122, undefined */ 0, state_undefined },
4084 { /*123, undefined */ 0, state_undefined },
4085 { /*124, undefined */ 0, state_undefined },
4086 { /*125, undefined */ 0, state_undefined },
4087 { /*126, undefined */ 0, state_undefined },
4088 { /*127, undefined */ 0, state_undefined },
4089 { /*128, undefined */ 0, state_undefined },
4090 { /*129, undefined */ 0, state_undefined },
4091 { /*130, undefined */ 0, state_undefined },
4092 { /*131, undefined */ 0, state_undefined },
4093 { /*132, undefined */ 0, state_undefined },
4094 { /*133, undefined */ 0, state_undefined },
4095 { /*134, undefined */ 0, state_undefined },
4096 { /*135, undefined */ 0, state_undefined },
4097 { /*136, undefined */ 0, state_undefined },
4098 { /*137, undefined */ 0, state_undefined },
4099 { /*138, undefined */ 0, state_undefined },
4100 { /*139, undefined */ 0, state_undefined },
4101 { /*140, undefined */ 0, state_undefined },
4102 { /*141, undefined */ 0, state_undefined },
4103 { /*142, undefined */ 0, state_undefined },
4104 { /*143, undefined */ 0, state_undefined },
4105 { /*144, undefined */ 0, state_undefined },
4106 { /*145, undefined */ 0, state_undefined },
4107 { /*146, undefined */ 0, state_undefined },
4108 { /*147, undefined */ 0, state_undefined },
4109 { /*148, undefined */ 0, state_undefined },
4110 { /*149, undefined */ 0, state_undefined },
4111 { /*150, undefined */ 0, state_undefined },
4112 { /*151, undefined */ 0, state_undefined },
4113 { /*152, undefined */ 0, state_undefined },
4114 { /*153, undefined */ 0, state_undefined },
4115 { /*154, undefined */ 0, state_undefined },
4116 { /*155, undefined */ 0, state_undefined },
4117 { /*156, undefined */ 0, state_undefined },
4118 { /*157, undefined */ 0, state_undefined },
4119 { /*158, undefined */ 0, state_undefined },
4120 { /*159, undefined */ 0, state_undefined },
4121 { /*160, undefined */ 0, state_undefined },
4122 { /*161, undefined */ 0, state_undefined },
4123 { /*162, undefined */ 0, state_undefined },
4124 { /*163, undefined */ 0, state_undefined },
4125 { /*164, undefined */ 0, state_undefined },
4126 { /*165, undefined */ 0, state_undefined },
4127 { /*166, undefined */ 0, state_undefined },
4128 { /*167, undefined */ 0, state_undefined },
4129 { /*168, undefined */ 0, state_undefined },
4130 { /*169, undefined */ 0, state_undefined },
4131 { /*170, undefined */ 0, state_undefined },
4132 { /*171, undefined */ 0, state_undefined },
4133 { /*172, undefined */ 0, state_undefined },
4134 { /*173, undefined */ 0, state_undefined },
4135 { /*174, undefined */ 0, state_undefined },
4136 { /*175, undefined */ 0, state_undefined },
4137 { /*176, undefined */ 0, state_undefined },
4138 { /*177, undefined */ 0, state_undefined },
4139 { /*178, undefined */ 0, state_undefined },
4140 { /*179, undefined */ 0, state_undefined },
4141 { /*180, undefined */ 0, state_undefined },
4142 { /*181, undefined */ 0, state_undefined },
4143 { /*182, undefined */ 0, state_undefined },
4144 { /*183, undefined */ 0, state_undefined },
4145 { /*184, undefined */ 0, state_undefined },
4146 { /*185, undefined */ 0, state_undefined },
4147 { /*186, undefined */ 0, state_undefined },
4148 { /*187, undefined */ 0, state_undefined },
4149 { /*188, undefined */ 0, state_undefined },
4150 { /*189, undefined */ 0, state_undefined },
4151 { /*190, undefined */ 0, state_undefined },
4152 { /*191, undefined */ 0, state_undefined },
4153 { /*192, undefined */ 0, state_undefined },
4154 { /*193, undefined */ 0, state_undefined },
4155 { /*194, undefined */ 0, state_undefined },
4156 { /*195, undefined */ 0, state_undefined },
4157 { /*196, undefined */ 0, state_undefined },
4158 { /*197, undefined */ 0, state_undefined },
4159 { /*198, undefined */ 0, state_undefined },
4160 { /*199, undefined */ 0, state_undefined },
4161 { /*200, undefined */ 0, state_undefined },
4162 { /*201, undefined */ 0, state_undefined },
4163 { /*202, undefined */ 0, state_undefined },
4164 { /*203, undefined */ 0, state_undefined },
4165 { /*204, undefined */ 0, state_undefined },
4166 { /*205, undefined */ 0, state_undefined },
4167 { /*206, undefined */ 0, state_undefined },
4168 { /*207, undefined */ 0, state_undefined },
4169 { /*208, undefined */ 0, state_undefined },
4170 { /*209, undefined */ 0, state_undefined },
4171 { /*210, undefined */ 0, state_undefined },
4172 { /*211, undefined */ 0, state_undefined },
4173 { /*212, undefined */ 0, state_undefined },
4174 { /*213, undefined */ 0, state_undefined },
4175 { /*214, undefined */ 0, state_undefined },
4176 { /*215, undefined */ 0, state_undefined },
4177 { /*216, undefined */ 0, state_undefined },
4178 { /*217, undefined */ 0, state_undefined },
4179 { /*218, undefined */ 0, state_undefined },
4180 { /*219, undefined */ 0, state_undefined },
4181 { /*220, undefined */ 0, state_undefined },
4182 { /*221, undefined */ 0, state_undefined },
4183 { /*222, undefined */ 0, state_undefined },
4184 { /*223, undefined */ 0, state_undefined },
4185 { /*224, undefined */ 0, state_undefined },
4186 { /*225, undefined */ 0, state_undefined },
4187 { /*226, undefined */ 0, state_undefined },
4188 { /*227, undefined */ 0, state_undefined },
4189 { /*228, undefined */ 0, state_undefined },
4190 { /*229, undefined */ 0, state_undefined },
4191 { /*230, undefined */ 0, state_undefined },
4192 { /*231, undefined */ 0, state_undefined },
4193 { /*232, undefined */ 0, state_undefined },
4194 { /*233, undefined */ 0, state_undefined },
4195 { /*234, undefined */ 0, state_undefined },
4196 { /*235, undefined */ 0, state_undefined },
4197 { /*236, undefined */ 0, state_undefined },
4198 { /*237, undefined */ 0, state_undefined },
4199 { /*238, undefined */ 0, state_undefined },
4200 { /*239, undefined */ 0, state_undefined },
4201 { /*240, undefined */ 0, state_undefined },
4202 { /*241, undefined */ 0, state_undefined },
4203 { /*242, undefined */ 0, state_undefined },
4204 { /*243, undefined */ 0, state_undefined },
4205 { /*244, undefined */ 0, state_undefined },
4206 { /*245, undefined */ 0, state_undefined },
4207 { /*246, undefined */ 0, state_undefined },
4208 { /*247, undefined */ 0, state_undefined },
4209 { /*248, undefined */ 0, state_undefined },
4210 { /*249, undefined */ 0, state_undefined },
4211 { /*250, undefined */ 0, state_undefined },
4212 { /*251, undefined */ 0, state_undefined },
4213 { /*252, undefined */ 0, state_undefined },
4214 { /*253, undefined */ 0, state_undefined },
4215 { /*254, undefined */ 0, state_undefined },
4216 { /*255, undefined */ 0, state_undefined },
4217 /* End huge gap */
4218 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4219 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4220 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4221 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4222 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4223 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4224 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4225 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4226 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4227 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4228 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4229 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4230 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4231 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4232 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4233 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4234 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4235 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4236 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4237 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4238 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4239 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4240 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4241 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4242 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4243 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4244 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4245 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4246 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4247 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4248 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4249 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4250 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4251 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4252 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4253 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4254 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4255 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4256 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4257 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4258 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4259 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4260 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4261 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4262 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4263 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4264 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4265 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4266 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4267 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4268 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4269 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4270 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4271 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4272 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4273 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4274 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4275 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4276 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4277 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4278 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4279 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4280 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4281 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4282 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4283 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4284 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4285 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4286 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4287 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4288 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4289 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4290 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4291 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4292 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4293 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4294 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4295 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4296 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4297 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4298 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4299 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4300 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4301 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4302 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4303 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4304 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4305 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4306 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4307 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4308 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4309 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4310 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4311 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4312 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4313 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4314 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4315 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4316 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4317 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4318 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4319 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4320 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4321 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4322 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4323 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4324 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4325 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4326 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4327 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4328 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4329 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4330 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4331 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4332 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4333 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4334 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4335 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4336 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4337 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4338 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4339 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4340 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4341 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4342 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4343 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4344 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4345 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4346 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4347 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4348 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4349 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4350 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4351 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4352 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4353 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4354 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4355 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4356 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4357 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4358 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4359 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4360 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4361 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4362 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4363 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4364 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4365 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4366 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4367 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4368 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4369 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4370 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4371 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4372 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4373 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4374 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4375 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4376 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4377 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4378 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4379 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4380 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4381 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4382 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4383 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4384 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4385 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4386 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4387 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4388 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4389 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4390 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4391 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4392 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4393 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4394 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4395 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4396 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4397 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4398 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4399 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4400 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4401 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4402 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4403 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4404 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4405 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4406 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4407 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4408 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4409 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4410 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4411 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4412 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4413 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4414 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4415 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4416 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4417 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4418 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4419 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4420 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4421 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4422 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4423 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4424 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4425 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4426 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4427 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4428 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4429 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4430 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4431 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4432 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4433 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4434 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4435 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4436 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4437 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4438 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4439 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4440 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4441 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4442 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4443 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4444 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4445 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4446 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4447 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4448 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4449 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4450 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4451 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4452 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4453 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4454 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4455 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4456 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4457 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4458 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4459 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4460 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4461 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4462 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4463 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4464 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4465 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4466 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4467 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4468 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4469 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4470 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4471 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4472 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4473 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4474 /* Various Vertex states follow */
4475 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4476 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4477 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4478 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4479 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4480 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4481 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4482 /* Lights */
4483 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4484 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4485 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4486 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4487 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4488 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4489 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4490 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4491
4492 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4493 /* Clip planes */
4494 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4495 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4496 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4497 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4498 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4499 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4500 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4501 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4502 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4503 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4504 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4505 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4506 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4507 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4508 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4509 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4510 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4511 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4512 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4513 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4514 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4515 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4516 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4517 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4518 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4519 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4520 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4521 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4522 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4523 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4524 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4525 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4526
4527 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
4528 };