2 * Direct3D state management
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
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.
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.
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
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
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
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]);
47 /* Shouldn't have an unknown type here */
48 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
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.
57 WARN("undefined state %d\n", state);
60 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
61 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
64 case WINED3DFILL_POINT:
65 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
66 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
68 case WINED3DFILL_WIREFRAME:
69 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
70 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
72 case WINED3DFILL_SOLID:
73 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
74 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
77 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
81 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
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
90 if(isStateDirty(context, STATE_VDECL)) {
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;
98 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
99 glEnable(GL_LIGHTING);
100 checkGLcall("glEnable GL_LIGHTING");
102 glDisable(GL_LIGHTING);
103 checkGLcall("glDisable GL_LIGHTING");
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");
115 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
116 case WINED3DZB_FALSE:
117 glDisable(GL_DEPTH_TEST);
118 checkGLcall("glDisable GL_DEPTH_TEST");
121 glEnable(GL_DEPTH_TEST);
122 checkGLcall("glEnable GL_DEPTH_TEST");
125 glEnable(GL_DEPTH_TEST);
126 checkGLcall("glEnable GL_DEPTH_TEST");
127 FIXME("W buffer is not well handled\n");
130 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
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 */
137 /* If we are culling "back faces with clockwise vertices" then
138 set front faces to be counter clockwise and enable culling
140 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
141 case WINED3DCULL_NONE:
142 glDisable(GL_CULL_FACE);
143 checkGLcall("glDisable GL_CULL_FACE");
146 glEnable(GL_CULL_FACE);
147 checkGLcall("glEnable GL_CULL_FACE");
148 if (stateblock->wineD3DDevice->render_offscreen) {
150 checkGLcall("glFrontFace GL_CW");
153 checkGLcall("glFrontFace GL_CCW");
157 case WINED3DCULL_CCW:
158 glEnable(GL_CULL_FACE);
159 checkGLcall("glEnable GL_CULL_FACE");
160 if (stateblock->wineD3DDevice->render_offscreen) {
162 checkGLcall("glFrontFace GL_CCW");
165 checkGLcall("glFrontFace GL_CW");
170 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
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)");
180 case WINED3DSHADE_GOURAUD:
181 glShadeModel(GL_SMOOTH);
182 checkGLcall("glShadeModel(GL_SMOOTH)");
184 case WINED3DSHADE_PHONG:
185 FIXME("WINED3DSHADE_PHONG isn't supported\n");
188 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
192 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
193 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
195 checkGLcall("glEnable GL_DITHER");
197 glDisable(GL_DITHER);
198 checkGLcall("glDisable GL_DITHER");
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
206 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
208 checkGLcall("glDepthMask(1)");
211 checkGLcall("glDepthMask(0)");
215 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
216 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
219 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
220 /* There are a few issues with this: First, our inability to
221 * select a proper Z depth, most of the time we're stuck with
222 * D24S8, even if the app selects D32 or D16. There seem to be
223 * some other precision problems which have to be debugged to
224 * make NOTEQUAL and EQUAL work properly
226 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
230 checkGLcall("glDepthFunc");
234 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
236 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
238 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
239 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
240 checkGLcall("glLightModel for MODEL_AMBIENT");
243 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
244 int srcBlend = GL_ZERO;
245 int dstBlend = GL_ZERO;
247 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
248 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
249 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
250 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
252 checkGLcall("glEnable GL_BLEND");
255 checkGLcall("glDisable GL_BLEND");
256 /* Nothing more to do - get out */
260 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
261 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
262 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
263 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
264 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
265 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
266 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
267 case WINED3DBLEND_DESTALPHA : dstBlend = GL_DST_ALPHA; break;
268 case WINED3DBLEND_INVDESTALPHA : dstBlend = GL_ONE_MINUS_DST_ALPHA; break;
269 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
270 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
272 case WINED3DBLEND_SRCALPHASAT :
273 dstBlend = GL_SRC_ALPHA_SATURATE;
274 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
277 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
278 * values which are still valid up to d3d9. They should not occur as dest blend values
280 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
281 srcBlend = GL_SRC_ALPHA;
282 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
285 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
286 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
287 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
290 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
291 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
293 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
296 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
297 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
298 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
299 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
300 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
301 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
302 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
303 case WINED3DBLEND_DESTALPHA : srcBlend = GL_DST_ALPHA; break;
304 case WINED3DBLEND_INVDESTALPHA : srcBlend = GL_ONE_MINUS_DST_ALPHA; break;
305 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
306 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
307 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
309 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
310 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
313 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
314 dstBlend = GL_SRC_ALPHA;
317 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
318 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
320 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
324 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
325 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
326 glEnable(GL_LINE_SMOOTH);
327 checkGLcall("glEnable(GL_LINE_SMOOTH)");
328 if(srcBlend != GL_SRC_ALPHA) {
329 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
331 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
332 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
335 glDisable(GL_LINE_SMOOTH);
336 checkGLcall("glDisable(GL_LINE_SMOOTH)");
339 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
340 glBlendFunc(srcBlend, dstBlend);
341 checkGLcall("glBlendFunc");
344 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
347 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
348 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
349 GL_EXTCALL(glBlendColor (col[0],col[1],col[2],col[3]));
350 checkGLcall("glBlendColor");
353 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
356 BOOL enable_ckey = FALSE;
358 IWineD3DSurfaceImpl *surf;
360 /* Find out if the texture on the first stage has a ckey set
361 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
362 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
363 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
364 * in case it finds some texture+colorkeyenable combination which needs extra care.
366 if(stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
367 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
369 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
370 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
371 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
372 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
373 * surface has alpha bits
375 if(fmt->alphaMask == 0x00000000) {
381 if(enable_ckey || context->last_was_ckey) {
382 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
384 context->last_was_ckey = enable_ckey;
386 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
387 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
388 glEnable(GL_ALPHA_TEST);
389 checkGLcall("glEnable GL_ALPHA_TEST");
391 glDisable(GL_ALPHA_TEST);
392 checkGLcall("glDisable GL_ALPHA_TEST");
393 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
399 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
400 glParm = GL_NOTEQUAL;
403 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
404 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
407 glAlphaFunc(glParm, ref);
408 checkGLcall("glAlphaFunc");
412 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
413 DWORD enable = 0xFFFFFFFF;
414 DWORD disable = 0x00000000;
416 if (use_vs(stateblock->wineD3DDevice)) {
417 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
418 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
419 * contitions I got sick of tracking down. The shader state handler disables all clip planes because
420 * of that - don't do anything here and keep them disabled
422 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
423 static BOOL warned = FALSE;
425 FIXME("Clipping not supported with vertex shaders\n");
432 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
433 * of already set values
436 /* If enabling / disabling all
437 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
439 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
440 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
441 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
442 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
443 glDisable(GL_DEPTH_CLAMP_NV);
444 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
447 disable = 0xffffffff;
449 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
450 glEnable(GL_DEPTH_CLAMP_NV);
451 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
455 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
456 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
457 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
458 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
459 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
460 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
462 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
463 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
464 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
465 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
466 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
467 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
469 /** update clipping status */
471 stateblock->clip_status.ClipUnion = 0;
472 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
474 stateblock->clip_status.ClipUnion = 0;
475 stateblock->clip_status.ClipIntersection = 0;
479 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
480 int glParm = GL_FUNC_ADD;
482 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
483 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
487 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
488 case WINED3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
489 case WINED3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
490 case WINED3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
491 case WINED3DBLENDOP_MIN : glParm = GL_MIN; break;
492 case WINED3DBLENDOP_MAX : glParm = GL_MAX; break;
494 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
497 TRACE("glBlendEquation(%x)\n", glParm);
498 GL_EXTCALL(glBlendEquation(glParm));
499 checkGLcall("glBlendEquation");
503 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
504 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
505 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
506 * specular color. This is wrong:
507 * Separate specular color means the specular colour is maintained separately, whereas
508 * single color means it is merged in. However in both cases they are being used to
510 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
511 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
515 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
516 * Instead, we need to setup the FinalCombiner properly.
518 * The default setup for the FinalCombiner is:
520 * <variable> <input> <mapping> <usage>
521 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
522 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
523 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
524 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
525 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
526 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
527 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
529 * That's pretty much fine as it is, except for variable B, which needs to take
530 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
531 * whether WINED3DRS_SPECULARENABLE is enabled or not.
534 TRACE("Setting specular enable state and materials\n");
535 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
536 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
537 checkGLcall("glMaterialfv");
539 if(stateblock->material.Power > 128.0) {
540 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
541 * and 128.0, although in d3d neither -1 nor 129 produce an error. For values > 128 clamp
542 * them, since 128 results in a hardly visible specular highlight, so it should be safe to
545 WARN("Material power > 128\n");
546 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 128.0);
548 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
550 checkGLcall("glMaterialf(GL_SHININESS");
552 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
553 glEnable(GL_COLOR_SUM_EXT);
555 TRACE("Specular colors cannot be enabled in this version of opengl\n");
557 checkGLcall("glEnable(GL_COLOR_SUM)");
559 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
560 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
561 checkGLcall("glFinalCombinerInputNV()");
564 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
566 /* for the case of enabled lighting: */
567 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
568 checkGLcall("glMaterialfv");
570 /* for the case of disabled lighting: */
571 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
572 glDisable(GL_COLOR_SUM_EXT);
574 TRACE("Specular colors cannot be disabled in this version of opengl\n");
576 checkGLcall("glDisable(GL_COLOR_SUM)");
578 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
579 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
580 checkGLcall("glFinalCombinerInputNV()");
584 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
585 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
586 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
587 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
588 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
589 stateblock->material.Specular.b, stateblock->material.Specular.a);
590 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
591 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
593 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
594 checkGLcall("glMaterialfv(GL_AMBIENT)");
595 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
596 checkGLcall("glMaterialfv(GL_DIFFUSE)");
597 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
598 checkGLcall("glMaterialfv(GL_EMISSION)");
601 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
604 /* Note the texture color applies to all textures whereas
605 * GL_TEXTURE_ENV_COLOR applies to active only
608 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
610 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
611 /* And now the default texture color as well */
612 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
613 /* Note the WINED3DRS value applies to all textures, but GL has one
614 * per texture, so apply it now ready to be used!
616 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
617 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
618 checkGLcall("glActiveTextureARB");
620 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
623 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
624 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
627 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
632 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
633 #if 0 /* Don't use OpenGL 2.0 calls for now */
634 if(GL_EXTCALL(glStencilFuncSeparate) && GL_EXTCALL(glStencilOpSeparate)) {
635 GL_EXTCALL(glStencilFuncSeparate(face, func, ref, mask));
636 checkGLcall("glStencilFuncSeparate(...)");
637 GL_EXTCALL(glStencilOpSeparate(face, stencilFail, depthFail, stencilPass));
638 checkGLcall("glStencilOpSeparate(...)");
642 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
643 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
644 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
645 GL_EXTCALL(glActiveStencilFaceEXT(face));
646 checkGLcall("glActiveStencilFaceEXT(...)");
647 glStencilFunc(func, ref, mask);
648 checkGLcall("glStencilFunc(...)");
649 glStencilOp(stencilFail, depthFail, stencilPass);
650 checkGLcall("glStencilOp(...)");
651 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
652 GL_EXTCALL(glStencilFuncSeparateATI(face, func, ref, mask));
653 checkGLcall("glStencilFuncSeparateATI(...)");
654 GL_EXTCALL(glStencilOpSeparateATI(face, stencilFail, depthFail, stencilPass));
655 checkGLcall("glStencilOpSeparateATI(...)");
657 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
662 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
663 DWORD onesided_enable = FALSE;
664 DWORD twosided_enable = FALSE;
665 GLint func = GL_ALWAYS;
666 GLint func_ccw = GL_ALWAYS;
669 GLint stencilFail = GL_KEEP;
670 GLint depthFail = GL_KEEP;
671 GLint stencilPass = GL_KEEP;
672 GLint stencilFail_ccw = GL_KEEP;
673 GLint depthFail_ccw = GL_KEEP;
674 GLint stencilPass_ccw = GL_KEEP;
676 /* No stencil test without a stencil buffer */
677 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
678 glDisable(GL_STENCIL_TEST);
679 checkGLcall("glDisable GL_STENCIL_TEST");
683 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
684 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
685 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
687 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
689 ref = stateblock->renderState[WINED3DRS_STENCILREF];
690 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
691 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
692 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
693 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
694 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
695 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
696 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
698 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
699 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
700 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
701 onesided_enable, twosided_enable, ref, mask,
702 func, stencilFail, depthFail, stencilPass,
703 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
705 if (twosided_enable) {
706 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask, stencilFail, depthFail, stencilPass);
707 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
709 if (onesided_enable) {
710 glEnable(GL_STENCIL_TEST);
711 checkGLcall("glEnable GL_STENCIL_TEST");
712 glStencilFunc(func, ref, mask);
713 checkGLcall("glStencilFunc(...)");
714 glStencilOp(stencilFail, depthFail, stencilPass);
715 checkGLcall("glStencilOp(...)");
717 glDisable(GL_STENCIL_TEST);
718 checkGLcall("glDisable GL_STENCIL_TEST");
723 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
724 if(stateblock->wineD3DDevice->stencilBufferTarget) {
725 glStencilMask(stateblock->renderState[WINED3DRS_STENCILWRITEMASK]);
729 checkGLcall("glStencilMask");
732 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
733 /* TODO: Put this into the vertex type block once that is in the state table */
734 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
735 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
736 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
737 float fogstart, fogend;
745 /* No fog? Disable it, and we're done :-) */
747 checkGLcall("glDisable GL_FOG");
748 if( use_ps(stateblock->wineD3DDevice)
749 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
750 /* disable fog in the pixel shader
751 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
752 * -1/(e-s) and e/(e-s) respectively.
754 glFogf(GL_FOG_START, 0.0f);
755 checkGLcall("glFogf(GL_FOG_START, fogstart");
756 glFogf(GL_FOG_END, 1.0f);
757 checkGLcall("glFogf(GL_FOG_END, fogend");
762 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
763 fogstart = tmpvalue.f;
764 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
769 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
770 * It can use the Z value of the vertex, or the alpha component of the specular color.
771 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
772 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
773 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
775 * FOGTABLEMODE != NONE:
776 * The Z value is used, with the equation specified, no matter what vertex type.
778 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
779 * Per vertex fog is calculated using the specified fog equation and the parameters
781 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
782 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
783 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
786 * Rules for vertex fog with shaders:
788 * When mixing fixed function functionality with the programmable pipeline, D3D expects
789 * the fog computation to happen during transformation while openGL expects it to happen
790 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
791 * the pixel shader while openGL always expects the pixel shader to handle the blending.
792 * To solve this problem, WineD3D does:
793 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
795 * and 2) disables the fog computation (in either the fixed function or programmable
796 * rasterizer) if using a vertex program.
799 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
804 if( !use_vs(stateblock->wineD3DDevice)
805 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
806 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
810 if (use_vs(stateblock->wineD3DDevice)
811 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
812 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
813 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
817 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
818 glFogi(GL_FOG_MODE, GL_LINEAR);
819 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
824 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
825 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
826 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
827 context->fog_coord = FALSE;
829 context->last_was_foggy_shader = TRUE;
831 else if( use_ps(stateblock->wineD3DDevice) ) {
832 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
833 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
836 context->last_was_foggy_shader = FALSE;
838 /* If both fogmodes are set use the table fog mode */
839 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
840 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
842 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
846 case WINED3DFOG_EXP2:
847 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
852 case WINED3DFOG_LINEAR:
853 fogstart = -1.0f/(fogend-fogstart);
857 case WINED3DFOG_NONE:
858 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
862 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
865 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
866 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
867 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
868 context->fog_coord = FALSE;
871 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
872 * the system will apply only pixel(=table) fog effects."
874 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
875 glHint(GL_FOG_HINT, GL_FASTEST);
876 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
877 context->last_was_foggy_shader = FALSE;
879 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
880 /* If processed vertices are used, fall through to the NONE case */
881 case WINED3DFOG_EXP: {
882 if(!context->last_was_rhw) {
883 glFogi(GL_FOG_MODE, GL_EXP);
884 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
885 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
886 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
887 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
888 context->fog_coord = FALSE;
893 case WINED3DFOG_EXP2: {
894 if(!context->last_was_rhw) {
895 glFogi(GL_FOG_MODE, GL_EXP2);
896 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
897 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
898 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
899 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
900 context->fog_coord = FALSE;
905 case WINED3DFOG_LINEAR: {
906 if(!context->last_was_rhw) {
907 glFogi(GL_FOG_MODE, GL_LINEAR);
908 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
909 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
910 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
911 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
912 context->fog_coord = FALSE;
917 case WINED3DFOG_NONE: {
918 /* Both are none? According to msdn the alpha channel of the specular
919 * color contains a fog factor. Set it in drawStridedSlow.
920 * Same happens with Vertexfog on transformed vertices
922 if(GL_SUPPORT(EXT_FOG_COORD)) {
923 if(context->fog_coord == FALSE) {
924 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
925 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)\n");
926 context->fog_coord = TRUE;
928 glFogi(GL_FOG_MODE, GL_LINEAR);
929 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
933 /* Disable GL fog, handle this in software in drawStridedSlow */
938 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
941 glHint(GL_FOG_HINT, GL_NICEST);
942 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
943 context->last_was_foggy_shader = FALSE;
945 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
947 glFogi(GL_FOG_MODE, GL_EXP);
948 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
949 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
950 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
951 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
952 context->fog_coord = FALSE;
956 case WINED3DFOG_EXP2:
957 glFogi(GL_FOG_MODE, GL_EXP2);
958 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
959 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
960 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
961 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
962 context->fog_coord = FALSE;
966 case WINED3DFOG_LINEAR:
967 glFogi(GL_FOG_MODE, GL_LINEAR);
968 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
969 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
970 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
971 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT");
972 context->fog_coord = FALSE;
976 case WINED3DFOG_NONE: /* Won't happen */
978 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
984 checkGLcall("glEnable GL_FOG");
986 if(fogstart != fogend)
988 glFogfv(GL_FOG_START, &fogstart);
989 checkGLcall("glFogf(GL_FOG_START, fogstart");
990 TRACE("Fog Start == %f\n", fogstart);
992 glFogfv(GL_FOG_END, &fogend);
993 checkGLcall("glFogf(GL_FOG_END, fogend");
994 TRACE("Fog End == %f\n", fogend);
998 glFogf(GL_FOG_START, -1.0 / 0.0);
999 checkGLcall("glFogf(GL_FOG_START, fogstart");
1000 TRACE("Fog Start == %f\n", fogstart);
1002 glFogf(GL_FOG_END, 0.0);
1003 checkGLcall("glFogf(GL_FOG_END, fogend");
1004 TRACE("Fog End == %f\n", fogend);
1008 checkGLcall("glDisable GL_FOG");
1009 if( use_ps(stateblock->wineD3DDevice) ) {
1010 /* disable fog in the pixel shader
1011 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1012 * -1/(e-s) and e/(e-s) respectively.
1014 glFogf(GL_FOG_START, 0.0f);
1015 checkGLcall("glFogf(GL_FOG_START, fogstart");
1016 glFogf(GL_FOG_END, 1.0f);
1017 checkGLcall("glFogf(GL_FOG_END, fogend");
1022 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1023 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1024 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1025 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1026 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1028 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1031 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1032 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1033 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1038 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1040 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1041 glFogfv(GL_FOG_COLOR, &col[0]);
1042 checkGLcall("glFog GL_FOG_COLOR");
1045 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1050 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1051 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1052 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1055 /* TODO: Merge with primitive type + init_materials()!! */
1056 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1057 IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)stateblock->wineD3DDevice;
1059 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1060 BOOL isDiffuseSupplied;
1062 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1063 * The vertex declaration will call this function if the fixed function pipeline is used.
1066 if(isStateDirty(context, STATE_VDECL)) {
1070 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1072 context->num_untracked_materials = 0;
1073 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1074 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1075 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1076 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1077 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1078 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1080 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1081 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1082 Parm = GL_AMBIENT_AND_DIFFUSE;
1086 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1087 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1088 context->num_untracked_materials++;
1090 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1091 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1092 context->num_untracked_materials++;
1094 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1096 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1097 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1098 context->num_untracked_materials++;
1100 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1101 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1102 context->num_untracked_materials++;
1104 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1106 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1107 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1108 context->num_untracked_materials++;
1110 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1115 /* Nothing changed, return. */
1116 if (Parm == context->tracking_parm) return;
1119 glDisable(GL_COLOR_MATERIAL);
1120 checkGLcall("glDisable GL_COLOR_MATERIAL");
1122 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1123 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1124 glEnable(GL_COLOR_MATERIAL);
1125 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1128 /* Apparently calls to glMaterialfv are ignored for properties we're
1129 * tracking with glColorMaterial, so apply those here. */
1130 switch (context->tracking_parm) {
1131 case GL_AMBIENT_AND_DIFFUSE:
1132 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1133 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1134 checkGLcall("glMaterialfv");
1138 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1139 checkGLcall("glMaterialfv");
1143 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1144 checkGLcall("glMaterialfv");
1148 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1149 checkGLcall("glMaterialfv");
1153 /* Only change material color if specular is enabled, otherwise it is set to black */
1154 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1155 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1156 checkGLcall("glMaterialfv");
1158 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1159 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1160 checkGLcall("glMaterialfv");
1165 context->tracking_parm = Parm;
1168 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1171 WINED3DLINEPATTERN lp;
1173 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1175 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1177 if (tmppattern.lp.wRepeatFactor) {
1178 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1179 checkGLcall("glLineStipple(repeat, linepattern)");
1180 glEnable(GL_LINE_STIPPLE);
1181 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1183 glDisable(GL_LINE_STIPPLE);
1184 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1188 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1194 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1195 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1196 TRACE("ZBias value %f\n", tmpvalue.f);
1197 glPolygonOffset(0, -tmpvalue.f);
1198 checkGLcall("glPolygonOffset(0, -Value)");
1199 glEnable(GL_POLYGON_OFFSET_FILL);
1200 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1201 glEnable(GL_POLYGON_OFFSET_LINE);
1202 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1203 glEnable(GL_POLYGON_OFFSET_POINT);
1204 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1206 glDisable(GL_POLYGON_OFFSET_FILL);
1207 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1208 glDisable(GL_POLYGON_OFFSET_LINE);
1209 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1210 glDisable(GL_POLYGON_OFFSET_POINT);
1211 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1216 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1217 if(isStateDirty(context, STATE_VDECL)) {
1220 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1221 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1222 * by zero and is not properly defined in opengl, so avoid it
1224 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1225 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1226 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1227 glEnable(GL_NORMALIZE);
1228 checkGLcall("glEnable(GL_NORMALIZE);");
1230 glDisable(GL_NORMALIZE);
1231 checkGLcall("glDisable(GL_NORMALIZE);");
1235 static void state_psize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1241 /* FIXME: check that pointSize isn't outside glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize ); or -ve */
1242 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1243 TRACE("Set point size to %f\n", tmpvalue.f);
1244 glPointSize(tmpvalue.f);
1245 checkGLcall("glPointSize(...);");
1248 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1254 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1255 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1256 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1257 checkGLcall("glPointParameterfARB(...");
1259 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1260 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1261 checkGLcall("glPointParameterfEXT(...);");
1262 } else if(tmpvalue.f != 1.0) {
1263 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1267 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1273 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1274 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1275 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1276 checkGLcall("glPointParameterfARB(...");
1278 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1279 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1280 checkGLcall("glPointParameterfEXT(...);");
1281 } else if(tmpvalue.f != 64.0) {
1282 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1286 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1287 /* TODO: Group this with the viewport */
1289 * POINTSCALEENABLE controls how point size value is treated. If set to
1290 * true, the point size is scaled with respect to height of viewport.
1291 * When set to false point size is in pixels.
1293 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
1296 /* Default values */
1297 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1300 * Minimum valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
1301 * This means that OpenGL will clamp really small point sizes to 1.0f.
1302 * To correct for this we need to multiply by the scale factor when sizes
1303 * are less than 1.0f. scale_factor = 1.0f / point_size.
1305 GLfloat pointSize = *((float*)&stateblock->renderState[WINED3DRS_POINTSIZE]);
1306 if(pointSize > 0.0f) {
1307 GLfloat scaleFactor;
1309 if(pointSize < 1.0f) {
1310 scaleFactor = pointSize * pointSize;
1315 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1316 att[0] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_A]) /
1317 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1318 att[1] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_B]) /
1319 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1320 att[2] = *((float*)&stateblock->renderState[WINED3DRS_POINTSCALE_C]) /
1321 (stateblock->viewport.Height * stateblock->viewport.Height * scaleFactor);
1325 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1326 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1327 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
1329 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1330 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1331 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
1333 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
1337 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1338 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1340 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1341 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1342 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1343 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1344 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1345 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1346 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1347 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1348 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1349 checkGLcall("glColorMask(...)");
1351 /* depends on WINED3DRS_COLORWRITEENABLE. */
1352 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1353 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1354 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1355 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1356 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1357 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1358 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1362 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1363 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1364 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1365 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1367 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1368 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1372 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1373 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1374 TRACE("Last Pixel Drawing Enabled\n");
1376 static BOOL first = TRUE;
1378 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1381 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1386 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1387 /* TODO: NV_POINT_SPRITE */
1388 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1389 TRACE("Point sprites not supported\n");
1393 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1394 glEnable(GL_POINT_SPRITE_ARB);
1395 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)\n");
1397 glDisable(GL_POINT_SPRITE_ARB);
1398 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)\n");
1402 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1404 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1405 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/FixedFunction/Textures/texturewrapping.asp
1406 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1407 Descussion that ways to turn on WRAPing to solve an opengl conversion problem.
1408 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1410 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1413 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1414 stateblock->renderState[WINED3DRS_WRAP1] ||
1415 stateblock->renderState[WINED3DRS_WRAP2] ||
1416 stateblock->renderState[WINED3DRS_WRAP3] ||
1417 stateblock->renderState[WINED3DRS_WRAP4] ||
1418 stateblock->renderState[WINED3DRS_WRAP5] ||
1419 stateblock->renderState[WINED3DRS_WRAP6] ||
1420 stateblock->renderState[WINED3DRS_WRAP7] ||
1421 stateblock->renderState[WINED3DRS_WRAP8] ||
1422 stateblock->renderState[WINED3DRS_WRAP9] ||
1423 stateblock->renderState[WINED3DRS_WRAP10] ||
1424 stateblock->renderState[WINED3DRS_WRAP11] ||
1425 stateblock->renderState[WINED3DRS_WRAP12] ||
1426 stateblock->renderState[WINED3DRS_WRAP13] ||
1427 stateblock->renderState[WINED3DRS_WRAP14] ||
1428 stateblock->renderState[WINED3DRS_WRAP15] ) {
1429 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1433 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1434 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1435 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1436 glEnable(GL_MULTISAMPLE_ARB);
1437 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1439 glDisable(GL_MULTISAMPLE_ARB);
1440 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1443 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1444 WARN("Multisample antialiasing not supported by gl\n");
1449 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1450 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1451 glEnable(GL_SCISSOR_TEST);
1452 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1454 glDisable(GL_SCISSOR_TEST);
1455 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1459 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1465 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1466 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1467 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1468 glEnable(GL_POLYGON_OFFSET_FILL);
1469 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1470 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1471 checkGLcall("glPolygonOffset(...)");
1473 glDisable(GL_POLYGON_OFFSET_FILL);
1474 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1478 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1479 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1480 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1481 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1483 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1484 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1488 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1490 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1491 FIXME(" Stippled Alpha not supported yet.\n");
1494 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1496 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1497 FIXME(" Antialias not supported yet.\n");
1500 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1502 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1503 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1506 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1508 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1509 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1512 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1520 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1522 static BOOL displayed = FALSE;
1524 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1526 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1532 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1534 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1535 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1538 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1540 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1541 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1544 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1546 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1547 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1551 static void state_srgbwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1552 if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE])
1553 FIXME("Render state WINED3DRS_SRGBWRITEENABLE not yet implemented\n");
1556 static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1558 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
1559 FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
1562 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1563 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1564 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1568 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1569 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1570 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1574 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1575 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1576 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1580 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1581 if(stateblock->renderState[WINED3DRS_ROP2]) {
1582 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1586 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1587 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1588 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1592 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1593 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1594 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1598 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1599 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1600 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1604 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1605 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1606 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1610 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1611 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1612 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1616 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1617 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1618 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1622 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1623 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1624 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1628 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1629 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1630 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1634 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1635 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1636 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1640 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1641 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1642 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1646 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1647 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1648 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1652 /* Activates the texture dimension according to the bound D3D texture.
1653 * Does not care for the colorop or correct gl texture unit(when using nvrc)
1654 * Requires the caller to activate the correct unit before
1656 static void activate_dimensions(DWORD stage, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1657 BOOL bumpmap = FALSE;
1659 if(stage > 0 && (stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1660 stateblock->textureState[stage - 1][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP)) {
1662 context->texShaderBumpMap |= (1 << stage);
1664 context->texShaderBumpMap &= ~(1 << stage);
1667 if(stateblock->textures[stage]) {
1668 switch(stateblock->textureDimensions[stage]) {
1670 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1671 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
1673 glDisable(GL_TEXTURE_3D);
1674 checkGLcall("glDisable(GL_TEXTURE_3D)");
1675 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1676 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1677 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1679 glEnable(GL_TEXTURE_2D);
1680 checkGLcall("glEnable(GL_TEXTURE_2D)");
1684 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1685 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
1687 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1688 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1689 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1691 glDisable(GL_TEXTURE_2D);
1692 checkGLcall("glDisable(GL_TEXTURE_2D)");
1693 glEnable(GL_TEXTURE_3D);
1694 checkGLcall("glEnable(GL_TEXTURE_3D)");
1697 case GL_TEXTURE_CUBE_MAP_ARB:
1698 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1699 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
1701 glDisable(GL_TEXTURE_2D);
1702 checkGLcall("glDisable(GL_TEXTURE_2D)");
1703 glDisable(GL_TEXTURE_3D);
1704 checkGLcall("glDisable(GL_TEXTURE_3D)");
1705 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
1706 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
1711 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1712 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1714 glEnable(GL_TEXTURE_2D);
1715 checkGLcall("glEnable(GL_TEXTURE_2D)");
1716 glDisable(GL_TEXTURE_3D);
1717 checkGLcall("glDisable(GL_TEXTURE_3D)");
1718 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1719 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1720 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1722 /* Binding textures is done by samplers. A dummy texture will be bound */
1727 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1728 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1729 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1730 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1732 TRACE("Setting color op for stage %d\n", stage);
1734 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1735 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1736 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1740 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1742 if (mapped_stage != -1) {
1743 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1744 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1745 FIXME("Attempt to enable unsupported stage!\n");
1748 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1749 checkGLcall("glActiveTextureARB");
1750 } else if (stage > 0) {
1751 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1756 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1757 if(stateblock->lowest_disabled_stage > 0) {
1758 glEnable(GL_REGISTER_COMBINERS_NV);
1759 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1761 glDisable(GL_REGISTER_COMBINERS_NV);
1764 if(stage >= stateblock->lowest_disabled_stage) {
1765 TRACE("Stage disabled\n");
1766 if (mapped_stage != -1) {
1767 /* Disable everything here */
1768 glDisable(GL_TEXTURE_2D);
1769 checkGLcall("glDisable(GL_TEXTURE_2D)");
1770 glDisable(GL_TEXTURE_3D);
1771 checkGLcall("glDisable(GL_TEXTURE_3D)");
1772 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1773 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1774 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1776 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1777 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1784 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1785 * if the sampler for this stage is dirty
1787 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1788 if (tex_used) activate_dimensions(stage, stateblock, context);
1791 /* Set the texture combiners */
1792 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1793 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1794 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1795 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1796 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1797 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1800 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1801 * thus the texture shader may have to be updated
1803 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1804 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1805 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1806 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1807 if(usesBump != usedBump) {
1808 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1809 checkGLcall("glActiveTextureARB");
1810 activate_dimensions(stage + 1, stateblock, context);
1811 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1812 checkGLcall("glActiveTextureARB");
1816 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1817 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1818 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1819 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1820 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1824 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1825 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1826 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1827 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1828 DWORD op, arg1, arg2, arg0;
1830 TRACE("Setting alpha op for stage %d\n", stage);
1831 /* Do not care for enabled / disabled stages, just assign the settigns. colorop disables / enables required stuff */
1832 if (mapped_stage != -1) {
1833 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1834 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1835 FIXME("Attempt to enable unsupported stage!\n");
1838 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1839 checkGLcall("glActiveTextureARB");
1840 } else if (stage > 0) {
1841 /* We can't do anything here */
1842 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1847 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1848 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1849 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1850 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1852 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1853 stateblock->textures[0] && stateblock->textureDimensions[0] == GL_TEXTURE_2D) {
1854 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1856 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1857 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1859 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1860 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1861 * cannot remove the texture's alpha channel entirely.
1863 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1864 * on color keyed surfaces.
1866 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1868 if(op == WINED3DTOP_DISABLE) op = WINED3DTOP_SELECTARG1;
1869 if(op == WINED3DTOP_SELECTARG1) arg1 = WINED3DTA_TEXTURE;
1870 else if(op == WINED3DTOP_SELECTARG2) arg2 = WINED3DTA_TEXTURE;
1874 TRACE("Setting alpha op for stage %d\n", stage);
1875 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1876 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1877 op, arg1, arg2, arg0,
1880 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1881 op, arg1, arg2, arg0);
1885 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1886 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1887 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1889 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
1890 if(stateblock->vertexShader ||
1891 isStateDirty(context, STATE_VDECL)) {
1892 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
1896 if (mapped_stage < 0) return;
1898 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1899 if(mapped_stage >= GL_LIMITS(textures)) {
1902 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1903 checkGLcall("glActiveTextureARB");
1904 } else if (mapped_stage > 0) {
1905 /* We can't do anything here */
1906 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1910 set_texture_matrix((float *)&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1911 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1912 (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU,
1913 context->last_was_rhw,
1914 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
1915 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
1916 WINED3DDECLTYPE_UNUSED);
1920 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
1923 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
1924 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
1925 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1929 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
1930 UINT *offset = stateblock->streamOffset;
1931 unsigned int mapped_stage = 0;
1932 unsigned int textureNo = 0;
1934 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
1935 /* Abort if we don't support the extension. */
1936 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
1937 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1941 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
1942 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
1944 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
1945 if (mapped_stage == -1) continue;
1947 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
1948 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
1949 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
1951 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
1952 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
1953 checkGLcall("glBindBufferARB");
1954 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
1957 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1958 checkGLcall("glClientActiveTextureARB");
1960 /* The coords to supply depend completely on the fvf / vertex shader */
1962 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
1963 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
1964 sd->u.s.texCoords[coordIdx].dwStride,
1965 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
1966 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1968 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
1971 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1972 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
1973 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
1974 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
1979 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1980 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1981 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1983 if (mapped_stage == -1) {
1984 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
1988 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1989 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
1992 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1993 checkGLcall("glActiveTextureARB");
1994 } else if (stage > 0) {
1995 /* We can't do anything here */
1996 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2000 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2002 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2003 * one flag, you can still specify an index value, which the system uses to
2004 * determine the texture wrapping mode.
2005 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2006 * means use the vertex position (camera-space) as the input texture coordinates
2007 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2008 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2009 * to the TEXCOORDINDEX value
2013 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2015 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2016 case WINED3DTSS_TCI_PASSTHRU:
2017 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2018 glDisable(GL_TEXTURE_GEN_S);
2019 glDisable(GL_TEXTURE_GEN_T);
2020 glDisable(GL_TEXTURE_GEN_R);
2021 glDisable(GL_TEXTURE_GEN_Q);
2022 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2025 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2026 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2027 * as the input texture coordinates for this stage's texture transformation. This
2028 * equates roughly to EYE_LINEAR
2031 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2032 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2033 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2034 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2035 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2037 glMatrixMode(GL_MODELVIEW);
2040 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2041 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2042 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2043 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2046 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2047 glEnable(GL_TEXTURE_GEN_S);
2048 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2049 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2050 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2051 glEnable(GL_TEXTURE_GEN_T);
2052 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2053 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2054 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2055 glEnable(GL_TEXTURE_GEN_R);
2056 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2057 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2058 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2062 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2064 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2065 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2066 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2067 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2068 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2069 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2071 glMatrixMode(GL_MODELVIEW);
2074 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2075 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2076 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2077 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2080 glEnable(GL_TEXTURE_GEN_S);
2081 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2082 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2083 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2084 glEnable(GL_TEXTURE_GEN_T);
2085 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2086 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2087 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2088 glEnable(GL_TEXTURE_GEN_R);
2089 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2090 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2091 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2096 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2098 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2099 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2100 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2101 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2102 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2103 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2105 glMatrixMode(GL_MODELVIEW);
2108 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2109 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2110 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2111 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2114 glEnable(GL_TEXTURE_GEN_S);
2115 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2116 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2117 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2118 glEnable(GL_TEXTURE_GEN_T);
2119 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2120 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2121 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2122 glEnable(GL_TEXTURE_GEN_R);
2123 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2124 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2125 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2130 /* Unhandled types: */
2133 /* ? disable GL_TEXTURE_GEN_n ? */
2134 glDisable(GL_TEXTURE_GEN_S);
2135 glDisable(GL_TEXTURE_GEN_T);
2136 glDisable(GL_TEXTURE_GEN_R);
2137 glDisable(GL_TEXTURE_GEN_Q);
2138 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2142 /* Update the texture matrix */
2143 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2144 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2147 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2148 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2149 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2150 * and do all the things linked to it
2151 * TODO: Tidy that up to reload only the arrays of the changed unit
2153 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2155 unloadTexCoords(stateblock);
2156 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2160 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2161 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2163 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2164 * has an update pending
2166 if(isStateDirty(context, STATE_VDECL) ||
2167 isStateDirty(context, STATE_PIXELSHADER)) {
2171 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2174 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2175 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2181 if(stateblock->pixelShader && stage != 0 &&
2182 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) {
2183 /* The pixel shader has to know the luminance scale. Do a constants update if it
2184 * isn't scheduled anyway
2186 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2187 !isStateDirty(context, STATE_PIXELSHADER)) {
2188 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2192 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2193 if(tmpvalue.f != 0.0) {
2194 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2198 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2199 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2205 if(stateblock->pixelShader && stage != 0 &&
2206 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams == stage) {
2207 /* The pixel shader has to know the luminance offset. Do a constants update if it
2208 * isn't scheduled anyway
2210 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2211 !isStateDirty(context, STATE_PIXELSHADER)) {
2212 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2216 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2217 if(tmpvalue.f != 0.0) {
2218 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2222 static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2223 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2225 if(stage >= GL_LIMITS(texture_stages)) {
2229 if(stateblock->textureState[stage][WINED3DTSS_RESULTARG] != WINED3DTA_CURRENT) {
2230 FIXME("WINED3DTSS_RESULTARG not supported yet\n");
2234 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2235 DWORD sampler = state - STATE_SAMPLER(0);
2236 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2242 TRACE("Sampler: %d\n", sampler);
2243 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2244 * only has to bind textures and set the per texture states
2247 if (mapped_stage == -1) {
2248 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2252 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2253 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2256 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2257 checkGLcall("glActiveTextureARB");
2258 } else if (sampler > 0) {
2259 /* We can't do anything here */
2260 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2264 if(stateblock->textures[sampler]) {
2265 BOOL texIsPow2 = FALSE;
2267 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2268 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2269 * scaling is reapplied or removed, the texture matrix has to be reapplied
2271 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2272 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
2273 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
2274 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {
2277 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2278 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->pow2scalingFactor != 1.0) {
2283 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2284 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2285 context->lastWasPow2Texture[sampler] = texIsPow2;
2289 IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
2290 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2292 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2293 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2294 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2295 GL_TEXTURE_LOD_BIAS_EXT,
2297 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2300 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2301 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2302 /* Using a pixel shader? Verify the sampler types */
2304 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2305 * dimensions because the shader knows from which texture type to sample from. For the sake of
2306 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2307 * dimensions. This should make wrong sampling sources visible :-)
2309 glEnable(stateblock->textureDimensions[sampler]);
2310 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2311 } else if(sampler < stateblock->lowest_disabled_stage) {
2312 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2313 activate_dimensions(sampler, stateblock, context);
2316 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2317 /* If color keying is enabled update the alpha test, it depends on the existence
2318 * of a color key in stage 0
2320 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2323 } else if(sampler < GL_LIMITS(texture_stages)) {
2324 if(sampler < stateblock->lowest_disabled_stage) {
2325 /* TODO: What should I do with pixel shaders here ??? */
2326 if(!isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3DTSS_COLOROP))) {
2327 activate_dimensions(sampler, stateblock, context);
2329 } /* Otherwise tex_colorop disables the stage */
2330 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2331 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2335 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2336 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2337 BOOL use_pshader = use_ps(device);
2338 BOOL use_vshader = use_vs(device);
2339 BOOL update_fog = FALSE;
2343 if(!context->last_was_pshader) {
2344 /* Former draw without a pixel shader, some samplers
2345 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2346 * make sure to enable them
2348 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2349 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2350 sampler(STATE_SAMPLER(i), stateblock, context);
2355 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2356 * if a different texture was bound. I don't have to do anything.
2360 /* Compile and bind the shader */
2361 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2363 /* Disabled the pixel shader - color ops weren't applied
2364 * while it was enabled, so re-apply them.
2366 for(i=0; i < MAX_TEXTURES; i++) {
2367 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2368 tex_colorop(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2371 if(context->last_was_pshader)
2375 if(!isStateDirty(context, StateTable[STATE_VSHADER].representative)) {
2376 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2378 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2379 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2384 state_fog(state, stateblock, context);
2386 context->last_was_pshader = use_pshader;
2389 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2390 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2392 if(stateblock->pixelShader && stage != 0 &&
2393 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) {
2394 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2397 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2398 !isStateDirty(context, STATE_PIXELSHADER)) {
2399 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2403 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2404 if(stage >= GL_LIMITS(texture_stages)) {
2405 WARN("Bump env matrix of unsupported stage set\n");
2406 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2407 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2408 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2410 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI,
2411 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00])));
2412 checkGLcall("glTexBumpParameterfvATI");
2414 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2415 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2416 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2417 * map offseting is done in the stage reading the bump mapped texture, and the perturbation
2418 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2419 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2421 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2423 if(mapped_stage < GL_LIMITS(textures)) {
2424 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2425 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2427 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV,
2428 (float *) &(stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]));
2429 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)\n");
2434 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2435 /* This function is called by transform_view below if the view matrix was changed too
2437 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2438 * does not always update the world matrix, only on a switch between transformed
2439 * and untrannsformed draws. It *may* happen that the world matrix is set 2 times during one
2440 * draw, but that should be rather rare and cheaper in total.
2442 glMatrixMode(GL_MODELVIEW);
2443 checkGLcall("glMatrixMode");
2445 if(context->last_was_rhw) {
2447 checkGLcall("glLoadIdentity()");
2449 /* In the general case, the view matrix is the identity matrix */
2450 if (stateblock->wineD3DDevice->view_ident) {
2451 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2452 checkGLcall("glLoadMatrixf");
2454 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2455 checkGLcall("glLoadMatrixf");
2456 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2457 checkGLcall("glMultMatrixf");
2462 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2463 UINT index = state - STATE_CLIPPLANE(0);
2465 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2469 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2470 glMatrixMode(GL_MODELVIEW);
2472 glLoadMatrixf((float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2474 TRACE("Clipplane [%f,%f,%f,%f]\n",
2475 stateblock->clipplane[index][0],
2476 stateblock->clipplane[index][1],
2477 stateblock->clipplane[index][2],
2478 stateblock->clipplane[index][3]);
2479 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2480 checkGLcall("glClipPlane");
2485 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2486 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2488 TRACE("Setting world matrix %d\n", matrix);
2490 if(matrix >= GL_LIMITS(blends)) {
2491 WARN("Unsupported blend matrix set\n");
2493 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2497 /* GL_MODELVIEW0_ARB: 0x1700
2498 * GL_MODELVIEW1_ARB: 0x0x850a
2499 * GL_MODELVIEW2_ARB: 0x8722
2500 * GL_MODELVIEW3_ARB: 0x8723
2502 * GL_MODELVIEW31_ARB: 0x873F
2504 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2505 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2507 glMatrixMode(glMat);
2508 checkGLcall("glMatrixMode(glMat)");
2510 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2511 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2513 if(stateblock->wineD3DDevice->view_ident) {
2514 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2515 checkGLcall("glLoadMatrixf")
2517 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2518 checkGLcall("glLoadMatrixf")
2519 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2520 checkGLcall("glMultMatrixf")
2524 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2525 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2528 case WINED3DVBF_1WEIGHTS:
2529 case WINED3DVBF_2WEIGHTS:
2530 case WINED3DVBF_3WEIGHTS:
2531 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2532 glEnable(GL_VERTEX_BLEND_ARB);
2533 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2535 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2536 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2538 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2540 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2542 for(i = 1; i < GL_LIMITS(blends); i++) {
2543 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2544 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2547 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2550 /* TODO: Implement vertex blending in drawStridedSlow */
2551 FIXME("Vertex blending enabled, but not supported by hardware\n");
2555 case WINED3DVBF_DISABLE:
2556 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2557 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2558 glDisable(GL_VERTEX_BLEND_ARB);
2559 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2561 TRACE("Vertex blending disabled\n");
2565 case WINED3DVBF_TWEENING:
2566 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2567 * vertex weights in the vertices?
2568 * For now we don't report that as supported, so a warn should suffice
2570 WARN("Tweening not supported yet\n");
2575 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2578 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2579 * NOTE: We have to reset the positions even if the light/plane is not currently
2580 * enabled, since the call to enable it will not reset the position.
2581 * NOTE2: Apparently texture transforms do NOT need reapplying
2584 PLIGHTINFOEL *light = NULL;
2586 glMatrixMode(GL_MODELVIEW);
2587 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2588 glLoadMatrixf((float *)(float *) &stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2589 checkGLcall("glLoadMatrixf(...)");
2591 /* Reset lights. TODO: Call light apply func */
2592 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2593 light = stateblock->activeLights[k];
2594 if(!light) continue;
2595 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2596 checkGLcall("glLightfv posn");
2597 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2598 checkGLcall("glLightfv dirn");
2601 /* Reset Clipping Planes */
2602 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2603 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2604 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2608 if(context->last_was_rhw) {
2610 checkGLcall("glLoadIdentity()");
2611 /* No need to update the world matrix, the identity is fine */
2615 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2616 * No need to do it here if the state is scheduled for update.
2618 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2619 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2622 /* Avoid looping over a number of matrices if the app never used the functionality */
2623 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2624 for(k = 1; k < GL_LIMITS(blends); k++) {
2625 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2626 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2632 static const GLfloat invymat[16] = {
2633 1.0f, 0.0f, 0.0f, 0.0f,
2634 0.0f, -1.0f, 0.0f, 0.0f,
2635 0.0f, 0.0f, 1.0f, 0.0f,
2636 0.0f, 0.0f, 0.0f, 1.0f};
2638 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2639 glMatrixMode(GL_PROJECTION);
2640 checkGLcall("glMatrixMode(GL_PROJECTION)");
2642 checkGLcall("glLoadIdentity");
2644 if(context->last_was_rhw) {
2645 double X, Y, height, width, minZ, maxZ;
2647 X = stateblock->viewport.X;
2648 Y = stateblock->viewport.Y;
2649 height = stateblock->viewport.Height;
2650 width = stateblock->viewport.Width;
2651 minZ = stateblock->viewport.MinZ;
2652 maxZ = stateblock->viewport.MaxZ;
2654 if(!stateblock->wineD3DDevice->untransformed) {
2655 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2656 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2657 * suppress depth clipping. This can be done because it is an orthogonal projection and
2658 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2659 * Persia 3D need this.
2661 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2662 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2663 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2666 * Also note that this breaks z comparison against z values filled in with clear,
2667 * but no app depending on that and disabled clipping has been found yet. Comparing
2668 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2671 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2672 * but this would break Z buffer operation. Raising the range to something less than
2673 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2676 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2677 if(stateblock->wineD3DDevice->render_offscreen) {
2678 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2680 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2683 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2684 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2685 * unmodified to opengl.
2687 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2688 * replacement shader.
2690 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2691 if(stateblock->wineD3DDevice->render_offscreen) {
2692 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2694 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2697 checkGLcall("glOrtho");
2699 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2700 glTranslatef(0.5, 0.5, 0);
2701 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2702 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2703 * render everything upside down when rendering offscreen. */
2704 if (stateblock->wineD3DDevice->render_offscreen) {
2705 glMultMatrixf(invymat);
2706 checkGLcall("glMultMatrixf(invymat)");
2709 /* The rule is that the window coordinate 0 does not correspond to the
2710 beginning of the first pixel, but the center of the first pixel.
2711 As a consequence if you want to correctly draw one line exactly from
2712 the left to the right end of the viewport (with all matrices set to
2713 be identity), the x coords of both ends of the line would be not
2714 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2717 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2718 divide by the Width/Height, so we need the half range(1.0) to translate by
2721 The other fun is that d3d's output z range after the transformation is [0;1],
2722 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2723 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2724 of Z buffer precision and the clear values do not match in the z test. Thus scale
2725 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2727 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2728 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2729 glScalef(1.0, 1.0, 2.0);
2731 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2732 * render everything upside down when rendering offscreen. */
2733 if (stateblock->wineD3DDevice->render_offscreen) {
2734 glMultMatrixf(invymat);
2735 checkGLcall("glMultMatrixf(invymat)");
2737 glMultMatrixf((float *) &stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2738 checkGLcall("glLoadMatrixf");
2742 /* This should match any arrays loaded in loadVertexData.
2743 * stateblock impl is required for GL_SUPPORT
2744 * TODO: Only load / unload arrays if we have to.
2746 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2747 glDisableClientState(GL_VERTEX_ARRAY);
2748 glDisableClientState(GL_NORMAL_ARRAY);
2749 glDisableClientState(GL_COLOR_ARRAY);
2750 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2751 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2753 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2754 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2755 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2756 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2758 unloadTexCoords(stateblock);
2761 /* This should match any arrays loaded in loadNumberedArrays
2762 * TODO: Only load / unload arrays if we have to.
2764 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2765 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2769 /* Leave all the attribs disabled */
2770 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2771 /* MESA does not support it right not */
2772 if (glGetError() != GL_NO_ERROR)
2774 for (i = 0; i < maxAttribs; ++i) {
2775 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2776 checkGLcall("glDisableVertexAttribArrayARB(reg);");
2780 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2781 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2783 UINT *offset = stateblock->streamOffset;
2785 /* Default to no instancing */
2786 stateblock->wineD3DDevice->instancedDraw = FALSE;
2788 for (i = 0; i < MAX_ATTRIBS; i++) {
2790 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2793 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2794 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2795 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2796 stateblock->wineD3DDevice->instancedDraw = TRUE;
2800 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2802 if(strided->u.input[i].dwStride) {
2803 if(curVBO != strided->u.input[i].VBO) {
2804 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2805 checkGLcall("glBindBufferARB");
2806 curVBO = strided->u.input[i].VBO;
2808 GL_EXTCALL(glVertexAttribPointerARB(i,
2809 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2810 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2811 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2812 strided->u.input[i].dwStride,
2813 strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
2814 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2816 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2817 * set up the attribute statically. But we have to figure out the system memory address.
2819 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2820 if(strided->u.input[i].VBO) {
2821 IWineD3DVertexBufferImpl *vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2822 ptr += (long) vb->resource.allocatedMemory;
2824 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2826 switch(strided->u.input[i].dwType) {
2827 case WINED3DDECLTYPE_FLOAT1:
2828 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2830 case WINED3DDECLTYPE_FLOAT2:
2831 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2833 case WINED3DDECLTYPE_FLOAT3:
2834 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2836 case WINED3DDECLTYPE_FLOAT4:
2837 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2840 case WINED3DDECLTYPE_UBYTE4:
2841 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2843 case WINED3DDECLTYPE_UBYTE4N:
2844 case WINED3DDECLTYPE_D3DCOLOR:
2845 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2848 case WINED3DDECLTYPE_SHORT2:
2849 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2851 case WINED3DDECLTYPE_SHORT4:
2852 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2855 case WINED3DDECLTYPE_SHORT2N:
2857 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2858 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2861 case WINED3DDECLTYPE_USHORT2N:
2863 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2864 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2867 case WINED3DDECLTYPE_SHORT4N:
2868 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2870 case WINED3DDECLTYPE_USHORT4N:
2871 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2874 case WINED3DDECLTYPE_UDEC3:
2875 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2876 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2878 case WINED3DDECLTYPE_DEC3N:
2879 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2880 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2883 case WINED3DDECLTYPE_FLOAT16_2:
2884 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2885 * byte float according to the IEEE standard
2887 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2889 case WINED3DDECLTYPE_FLOAT16_4:
2890 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2893 case WINED3DDECLTYPE_UNUSED:
2895 ERR("Unexpected declaration in stride 0 attributes\n");
2903 /* Used from 2 different functions, and too big to justify making it inlined */
2904 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
2905 UINT *offset = stateblock->streamOffset;
2906 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2908 TRACE("Using fast vertex array code\n");
2910 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
2911 stateblock->wineD3DDevice->instancedDraw = FALSE;
2913 /* Blend Data ---------------------------------------------- */
2914 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
2915 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
2917 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2918 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2919 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2921 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
2922 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
2924 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
2926 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
2927 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
2928 sd->u.s.blendWeights.dwStride,
2929 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
2931 if(curVBO != sd->u.s.blendWeights.VBO) {
2932 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
2933 checkGLcall("glBindBufferARB");
2934 curVBO = sd->u.s.blendWeights.VBO;
2937 GL_EXTCALL(glWeightPointerARB)(
2938 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2939 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2940 sd->u.s.blendWeights.dwStride,
2941 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
2943 checkGLcall("glWeightPointerARB");
2945 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
2946 static BOOL showfixme = TRUE;
2948 FIXME("blendMatrixIndices support\n");
2952 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2953 /* FIXME("TODO\n");*/
2956 GL_EXTCALL(glVertexWeightPointerEXT)(
2957 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
2958 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
2959 sd->u.s.blendWeights.dwStride,
2960 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
2961 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
2962 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2963 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
2967 /* TODO: support blends in drawStridedSlow
2968 * No need to write a FIXME here, this is done after the general vertex decl decoding
2970 WARN("unsupported blending in openGl\n");
2973 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2974 static const GLbyte one = 1;
2975 GL_EXTCALL(glWeightbvARB(1, &one));
2976 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
2980 #if 0 /* FOG ----------------------------------------------*/
2981 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
2983 if (GL_SUPPORT(EXT_FOG_COORD) {
2984 glEnableClientState(GL_FOG_COORDINATE_EXT);
2985 (GL_EXTCALL)(FogCoordPointerEXT)(
2986 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
2987 sd->u.s.fog.dwStride,
2988 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
2990 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
2991 /* FIXME: fixme once */
2992 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
2995 if (GL_SUPPRT(EXT_FOR_COORD) {
2996 /* make sure fog is disabled */
2997 glDisableClientState(GL_FOG_COORDINATE_EXT);
3002 #if 0 /* tangents ----------------------------------------------*/
3003 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3004 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3006 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3007 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3008 glEnable(GL_TANGENT_ARRAY_EXT);
3009 (GL_EXTCALL)(TangentPointerEXT)(
3010 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3011 sd->u.s.tangent.dwStride,
3012 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3014 glDisable(GL_TANGENT_ARRAY_EXT);
3016 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3017 glEnable(GL_BINORMAL_ARRAY_EXT);
3018 (GL_EXTCALL)(BinormalPointerEXT)(
3019 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3020 sd->u.s.binormal.dwStride,
3021 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3023 glDisable(GL_BINORMAL_ARRAY_EXT);
3027 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3028 /* FIXME: fixme once */
3029 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3032 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3033 /* make sure fog is disabled */
3034 glDisable(GL_TANGENT_ARRAY_EXT);
3035 glDisable(GL_BINORMAL_ARRAY_EXT);
3040 /* Point Size ----------------------------------------------*/
3041 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3043 /* no such functionality in the fixed function GL pipeline */
3044 TRACE("Cannot change ptSize here in openGl\n");
3045 /* TODO: Implement this function in using shaders if they are available */
3049 /* Vertex Pointers -----------------------------------------*/
3050 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3051 /* Note dwType == float3 or float4 == 2 or 3 */
3052 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3053 sd->u.s.position.dwStride,
3054 sd->u.s.position.dwType + 1,
3055 sd->u.s.position.lpData));
3057 if(curVBO != sd->u.s.position.VBO) {
3058 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3059 checkGLcall("glBindBufferARB");
3060 curVBO = sd->u.s.position.VBO;
3063 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3064 handling for rhw mode should not impact screen position whereas in GL it does.
3065 This may result in very slightly distored textures in rhw mode, but
3066 a very minimal different. There's always the other option of
3067 fixing the view matrix to prevent w from having any effect
3069 This only applies to user pointer sources, in VBOs the vertices are fixed up
3071 if(sd->u.s.position.VBO == 0) {
3072 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3073 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3074 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3077 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3078 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3079 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3081 checkGLcall("glVertexPointer(...)");
3082 glEnableClientState(GL_VERTEX_ARRAY);
3083 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3086 /* Normals -------------------------------------------------*/
3087 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3088 /* Note dwType == float3 or float4 == 2 or 3 */
3089 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3090 sd->u.s.normal.dwStride,
3091 sd->u.s.normal.lpData));
3092 if(curVBO != sd->u.s.normal.VBO) {
3093 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3094 checkGLcall("glBindBufferARB");
3095 curVBO = sd->u.s.normal.VBO;
3098 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3099 sd->u.s.normal.dwStride,
3100 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3101 checkGLcall("glNormalPointer(...)");
3102 glEnableClientState(GL_NORMAL_ARRAY);
3103 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3106 glNormal3f(0, 0, 0);
3107 checkGLcall("glNormal3f(0, 0, 0)");
3110 /* Diffuse Colour --------------------------------------------*/
3111 /* WARNING: Data here MUST be in RGBA format, so cannot */
3112 /* go directly into fast mode from app pgm, because */
3113 /* directx requires data in BGRA format. */
3114 /* currently fixupVertices swizels the format, but this isn't */
3115 /* very practical when using VBOS */
3116 /* NOTE: Unless we write a vertex shader to swizel the colour */
3117 /* , or the user doesn't care and wants the speed advantage */
3119 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3120 /* Note dwType == float3 or float4 == 2 or 3 */
3121 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3122 sd->u.s.diffuse.dwStride,
3123 sd->u.s.diffuse.lpData));
3125 if(curVBO != sd->u.s.diffuse.VBO) {
3126 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3127 checkGLcall("glBindBufferARB");
3128 curVBO = sd->u.s.diffuse.VBO;
3130 glColorPointer(4, GL_UNSIGNED_BYTE,
3131 sd->u.s.diffuse.dwStride,
3132 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3133 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3134 glEnableClientState(GL_COLOR_ARRAY);
3135 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3138 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3139 checkGLcall("glColor4f(1, 1, 1, 1)");
3142 /* Specular Colour ------------------------------------------*/
3143 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3144 TRACE("setting specular colour\n");
3145 /* Note dwType == float3 or float4 == 2 or 3 */
3146 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3147 sd->u.s.specular.dwStride,
3148 sd->u.s.specular.lpData));
3149 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3150 if(curVBO != sd->u.s.specular.VBO) {
3151 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3152 checkGLcall("glBindBufferARB");
3153 curVBO = sd->u.s.specular.VBO;
3155 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
3156 sd->u.s.specular.dwStride,
3157 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3158 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3159 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3160 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3163 /* Missing specular color is not critical, no warnings */
3164 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3168 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3169 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3170 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3173 /* Missing specular color is not critical, no warnings */
3174 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3178 /* Texture coords -------------------------------------------*/
3179 loadTexCoords(stateblock, sd, &curVBO);
3182 static inline void drawPrimitiveTraceDataLocations(
3183 WineDirect3DVertexStridedData *dataLocations) {
3185 /* Dump out what parts we have supplied */
3186 TRACE("Strided Data:\n");
3187 TRACE_STRIDED((dataLocations), position);
3188 TRACE_STRIDED((dataLocations), blendWeights);
3189 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3190 TRACE_STRIDED((dataLocations), normal);
3191 TRACE_STRIDED((dataLocations), pSize);
3192 TRACE_STRIDED((dataLocations), diffuse);
3193 TRACE_STRIDED((dataLocations), specular);
3194 TRACE_STRIDED((dataLocations), texCoords[0]);
3195 TRACE_STRIDED((dataLocations), texCoords[1]);
3196 TRACE_STRIDED((dataLocations), texCoords[2]);
3197 TRACE_STRIDED((dataLocations), texCoords[3]);
3198 TRACE_STRIDED((dataLocations), texCoords[4]);
3199 TRACE_STRIDED((dataLocations), texCoords[5]);
3200 TRACE_STRIDED((dataLocations), texCoords[6]);
3201 TRACE_STRIDED((dataLocations), texCoords[7]);
3202 TRACE_STRIDED((dataLocations), position2);
3203 TRACE_STRIDED((dataLocations), normal2);
3204 TRACE_STRIDED((dataLocations), tangent);
3205 TRACE_STRIDED((dataLocations), binormal);
3206 TRACE_STRIDED((dataLocations), tessFactor);
3207 TRACE_STRIDED((dataLocations), fog);
3208 TRACE_STRIDED((dataLocations), depth);
3209 TRACE_STRIDED((dataLocations), sample);
3214 /* Helper for vertexdeclaration() */
3215 static inline void handleStreams(IWineD3DStateBlockImpl *stateblock, BOOL useVertexShaderFunction, WineD3DContext *context) {
3216 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3218 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3220 if(device->up_strided) {
3221 /* Note: this is a ddraw fixed-function code path */
3222 TRACE("================ Strided Input ===================\n");
3223 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3226 drawPrimitiveTraceDataLocations(dataLocations);
3229 /* Note: This is a fixed function or shader codepath.
3230 * This means it must handle both types of strided data.
3231 * Shaders must go through here to zero the strided data, even if they
3232 * don't set any declaration at all
3234 TRACE("================ Vertex Declaration ===================\n");
3235 memset(dataLocations, 0, sizeof(*dataLocations));
3236 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3237 useVertexShaderFunction, dataLocations, &fixup);
3240 if (dataLocations->u.s.position_transformed) {
3241 useVertexShaderFunction = FALSE;
3244 /* Unload the old arrays before loading the new ones to get old junk out */
3245 if(context->numberedArraysLoaded) {
3246 unloadNumberedArrays(stateblock);
3247 context->numberedArraysLoaded = FALSE;
3249 if(context->namedArraysLoaded) {
3250 unloadVertexData(stateblock);
3251 context->namedArraysLoaded = FALSE;
3254 if(useVertexShaderFunction) {
3255 TRACE("Loading numbered arrays\n");
3256 loadNumberedArrays(stateblock, dataLocations);
3257 device->useDrawStridedSlow = FALSE;
3258 context->numberedArraysLoaded = TRUE;
3260 (dataLocations->u.s.pSize.lpData == NULL &&
3261 dataLocations->u.s.diffuse.lpData == NULL &&
3262 dataLocations->u.s.specular.lpData == NULL)) {
3263 /* Load the vertex data using named arrays */
3264 TRACE("Loading vertex data\n");
3265 loadVertexData(stateblock, dataLocations);
3266 device->useDrawStridedSlow = FALSE;
3267 context->namedArraysLoaded = TRUE;
3269 TRACE("Not loading vertex data\n");
3270 device->useDrawStridedSlow = TRUE;
3273 /* Generate some fixme's if unsupported functionality is being used */
3274 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3275 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3276 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3277 FIXME("Tweening is only valid with vertex shaders\n");
3279 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3280 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3282 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3283 FIXME("Extended attributes are only valid with vertex shaders\n");
3285 #undef BUFFER_OR_DATA
3288 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3289 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3290 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3291 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3293 /* Some stuff is in the device until we have per context tracking */
3294 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3295 BOOL wasrhw = context->last_was_rhw;
3297 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3298 * here simply check whether a shader was set, or the user disabled shaders
3300 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3301 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3302 useVertexShaderFunction = TRUE;
3304 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3307 } else if(context->last_was_foggy_shader) {
3311 handleStreams(stateblock, useVertexShaderFunction, context);
3313 transformed = device->strided_streams.u.s.position_transformed;
3314 if (transformed) useVertexShaderFunction = FALSE;
3316 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3320 /* Reapply lighting if it is not scheduled for reapplication already */
3321 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3322 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3326 context->last_was_rhw = TRUE;
3329 /* Untransformed, so relies on the view and projection matrices */
3330 context->last_was_rhw = FALSE;
3331 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3332 device->untransformed = TRUE;
3334 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3335 * Not needed as long as only hw shaders are supported
3338 /* This sets the shader output position correction constants.
3339 * TODO: Move to the viewport state
3341 if (useVertexShaderFunction) {
3342 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3346 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3347 * off this function will be called again anyway to make sure they're properly set
3349 if(!useVertexShaderFunction) {
3350 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3351 * or transformed / untransformed was switched
3353 if(wasrhw != context->last_was_rhw &&
3354 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3355 !isStateDirty(context, STATE_VIEWPORT)) {
3356 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3358 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3361 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3362 * this check will fail and the matrix not applied again. This is OK because a simple
3363 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3364 * needs of the vertex declaration.
3366 * World and view matrix go into the same gl matrix, so only apply them when neither is
3369 if(transformed != wasrhw &&
3370 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3371 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3372 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3375 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3376 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3379 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3380 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3382 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3383 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3386 /* We compile the shader here because we need the vertex declaration
3387 * in order to determine if we need to do any swizzling for D3DCOLOR
3388 * registers. If the shader is already compiled this call will do nothing. */
3389 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3391 if(!context->last_was_vshader) {
3393 static BOOL warned = FALSE;
3394 /* Disable all clip planes to get defined results on all drivers. See comment in the
3395 * state_clipping state handler
3397 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3398 glDisable(GL_CLIP_PLANE0 + i);
3399 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3402 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3403 FIXME("Clipping not supported with vertex shaders\n");
3409 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3412 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3413 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3415 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3416 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3420 context->last_was_vshader = useVertexShaderFunction;
3423 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3425 if(!useVertexShaderFunction) {
3427 for(i = 0; i < MAX_TEXTURES; i++) {
3428 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3429 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3435 static void viewport(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3436 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3437 checkGLcall("glDepthRange");
3438 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3440 if(stateblock->wineD3DDevice->render_offscreen) {
3441 glViewport(stateblock->viewport.X,
3442 stateblock->viewport.Y,
3443 stateblock->viewport.Width, stateblock->viewport.Height);
3445 glViewport(stateblock->viewport.X,
3446 (((IWineD3DSurfaceImpl *)stateblock->wineD3DDevice->render_targets[0])->currentDesc.Height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3447 stateblock->viewport.Width, stateblock->viewport.Height);
3450 checkGLcall("glViewport");
3452 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3453 stateblock->wineD3DDevice->posFixup[3] = -1.0 / stateblock->viewport.Height;
3454 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3455 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3460 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3461 UINT Index = state - STATE_ACTIVELIGHT(0);
3462 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3465 glDisable(GL_LIGHT0 + Index);
3466 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3469 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3471 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3472 glMatrixMode(GL_MODELVIEW);
3474 glLoadMatrixf((float *)&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3477 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3478 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3479 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3480 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3481 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3482 checkGLcall("glLightfv");
3485 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3486 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3487 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3488 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3489 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3490 checkGLcall("glLightfv");
3493 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3494 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3495 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3496 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3497 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3498 checkGLcall("glLightfv");
3500 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3501 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3503 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3506 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3507 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3508 * Attenuation0 to NaN and crashes in the gl lib
3511 switch (lightInfo->OriginalParms.Type) {
3512 case WINED3DLIGHT_POINT:
3514 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3515 checkGLcall("glLightfv");
3516 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3517 checkGLcall("glLightf");
3518 /* Attenuation - Are these right? guessing... */
3519 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3520 checkGLcall("glLightf");
3521 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3522 checkGLcall("glLightf");
3523 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3524 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3525 checkGLcall("glLightf");
3529 case WINED3DLIGHT_SPOT:
3531 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3532 checkGLcall("glLightfv");
3534 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3535 checkGLcall("glLightfv");
3536 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3537 checkGLcall("glLightf");
3538 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3539 checkGLcall("glLightf");
3540 /* Attenuation - Are these right? guessing... */
3541 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3542 checkGLcall("glLightf");
3543 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3544 checkGLcall("glLightf");
3545 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3546 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3547 checkGLcall("glLightf");
3551 case WINED3DLIGHT_DIRECTIONAL:
3553 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3554 checkGLcall("glLightfv");
3555 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3556 checkGLcall("glLightf");
3557 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3558 checkGLcall("glLightf");
3562 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3565 /* Restore the modelview matrix */
3568 glEnable(GL_LIGHT0 + Index);
3569 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3575 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3576 IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) stateblock->wineD3DDevice->swapchains[0];
3577 RECT *pRect = &stateblock->scissorRect;
3581 GetClientRect(swapchain->win_handle, &windowRect);
3582 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3583 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3585 winHeight = windowRect.bottom - windowRect.top;
3586 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - winHeight,
3587 pRect->right - pRect->left, pRect->bottom - pRect->top);
3589 if (stateblock->wineD3DDevice->render_offscreen) {
3590 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3592 glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3594 checkGLcall("glScissor");
3597 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3598 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3599 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3600 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3602 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3603 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3608 const struct StateEntry StateTable[] =
3610 /* State name representative, apply function */
3611 { /* 0, Undefined */ 0, state_undefined },
3612 { /* 1, WINED3DRS_TEXTUREHANDLE */ 0 /* Handled in ddraw */, state_undefined },
3613 { /* 2, WINED3DRS_ANTIALIAS */ STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias },
3614 { /* 3, WINED3DRS_TEXTUREADDRESS */ 0 /* Handled in ddraw */, state_undefined },
3615 { /* 4, WINED3DRS_TEXTUREPERSPECTIVE */ STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective },
3616 { /* 5, WINED3DRS_WRAPU */ STATE_RENDER(WINED3DRS_WRAPU), state_wrapu },
3617 { /* 6, WINED3DRS_WRAPV */ STATE_RENDER(WINED3DRS_WRAPV), state_wrapv },
3618 { /* 7, WINED3DRS_ZENABLE */ STATE_RENDER(WINED3DRS_ZENABLE), state_zenable },
3619 { /* 8, WINED3DRS_FILLMODE */ STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode },
3620 { /* 9, WINED3DRS_SHADEMODE */ STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode },
3621 { /* 10, WINED3DRS_LINEPATTERN */ STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern },
3622 { /* 11, WINED3DRS_MONOENABLE */ STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable },
3623 { /* 12, WINED3DRS_ROP2 */ STATE_RENDER(WINED3DRS_ROP2), state_rop2 },
3624 { /* 13, WINED3DRS_PLANEMASK */ STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask },
3625 { /* 14, WINED3DRS_ZWRITEENABLE */ STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable },
3626 { /* 15, WINED3DRS_ALPHATESTENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3627 { /* 16, WINED3DRS_LASTPIXEL */ STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel },
3628 { /* 17, WINED3DRS_TEXTUREMAG */ 0 /* Handled in ddraw */, state_undefined },
3629 { /* 18, WINED3DRS_TEXTUREMIN */ 0 /* Handled in ddraw */, state_undefined },
3630 { /* 19, WINED3DRS_SRCBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3631 { /* 20, WINED3DRS_DESTBLEND */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3632 { /* 21, WINED3DRS_TEXTUREMAPBLEND */ 0 /* Handled in ddraw */, state_undefined },
3633 { /* 22, WINED3DRS_CULLMODE */ STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode },
3634 { /* 23, WINED3DRS_ZFUNC */ STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc },
3635 { /* 24, WINED3DRS_ALPHAREF */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3636 { /* 25, WINED3DRS_ALPHAFUNC */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3637 { /* 26, WINED3DRS_DITHERENABLE */ STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable },
3638 { /* 27, WINED3DRS_ALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3639 { /* 28, WINED3DRS_FOGENABLE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3640 { /* 29, WINED3DRS_SPECULARENABLE */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},
3641 { /* 30, WINED3DRS_ZVISIBLE */ 0 /* Not supported according to the msdn */, state_nogl },
3642 { /* 31, WINED3DRS_SUBPIXEL */ STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel },
3643 { /* 32, WINED3DRS_SUBPIXELX */ STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx },
3644 { /* 33, WINED3DRS_STIPPLEDALPHA */ STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha },
3645 { /* 34, WINED3DRS_FOGCOLOR */ STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor },
3646 { /* 35, WINED3DRS_FOGTABLEMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3647 { /* 36, WINED3DRS_FOGSTART */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3648 { /* 37, WINED3DRS_FOGEND */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3649 { /* 38, WINED3DRS_FOGDENSITY */ STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity },
3650 { /* 39, WINED3DRS_STIPPLEENABLE */ STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable },
3651 { /* 40, WINED3DRS_EDGEANTIALIAS */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3652 { /* 41, WINED3DRS_COLORKEYENABLE */ STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha },
3653 { /* 42, undefined */ 0, state_undefined },
3654 { /* 43, WINED3DRS_BORDERCOLOR */ STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor },
3655 { /* 44, WINED3DRS_TEXTUREADDRESSU */ 0, /* Handled in ddraw */ state_undefined },
3656 { /* 45, WINED3DRS_TEXTUREADDRESSV */ 0, /* Handled in ddraw */ state_undefined },
3657 { /* 46, WINED3DRS_MIPMAPLODBIAS */ STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias },
3658 { /* 47, WINED3DRS_ZBIAS */ STATE_RENDER(WINED3DRS_ZBIAS), state_zbias },
3659 { /* 48, WINED3DRS_RANGEFOGENABLE */ STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog },
3660 { /* 49, WINED3DRS_ANISOTROPY */ STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy },
3661 { /* 50, WINED3DRS_FLUSHBATCH */ STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch },
3662 { /* 51, WINED3DRS_TRANSLUCENTSORTINDEPENDENT */ STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi },
3663 { /* 52, WINED3DRS_STENCILENABLE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3664 { /* 53, WINED3DRS_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3665 { /* 54, WINED3DRS_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3666 { /* 55, WINED3DRS_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3667 { /* 56, WINED3DRS_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3668 { /* 57, WINED3DRS_STENCILREF */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3669 { /* 58, WINED3DRS_STENCILMASK */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3670 { /* 59, WINED3DRS_STENCILWRITEMASK */ STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite },
3671 { /* 60, WINED3DRS_TEXTUREFACTOR */ STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor },
3672 { /* 61, Undefined */ 0, state_undefined },
3673 { /* 62, Undefined */ 0, state_undefined },
3674 { /* 63, Undefined */ 0, state_undefined },
3675 { /* 64, WINED3DRS_STIPPLEPATTERN00 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3676 { /* 65, WINED3DRS_STIPPLEPATTERN01 */ 0 /* Obsolete, should he handled by ddraw */, state_undefined },
3677 { /* 66, WINED3DRS_STIPPLEPATTERN02 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3678 { /* 67, WINED3DRS_STIPPLEPATTERN03 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3679 { /* 68, WINED3DRS_STIPPLEPATTERN04 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3680 { /* 69, WINED3DRS_STIPPLEPATTERN05 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3681 { /* 70, WINED3DRS_STIPPLEPATTERN06 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3682 { /* 71, WINED3DRS_STIPPLEPATTERN07 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3683 { /* 72, WINED3DRS_STIPPLEPATTERN08 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3684 { /* 73, WINED3DRS_STIPPLEPATTERN09 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3685 { /* 74, WINED3DRS_STIPPLEPATTERN10 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3686 { /* 75, WINED3DRS_STIPPLEPATTERN11 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3687 { /* 76, WINED3DRS_STIPPLEPATTERN12 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3688 { /* 77, WINED3DRS_STIPPLEPATTERN13 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3689 { /* 78, WINED3DRS_STIPPLEPATTERN14 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3690 { /* 79, WINED3DRS_STIPPLEPATTERN15 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3691 { /* 80, WINED3DRS_STIPPLEPATTERN16 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3692 { /* 81, WINED3DRS_STIPPLEPATTERN17 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3693 { /* 82, WINED3DRS_STIPPLEPATTERN18 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3694 { /* 83, WINED3DRS_STIPPLEPATTERN19 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3695 { /* 84, WINED3DRS_STIPPLEPATTERN20 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3696 { /* 85, WINED3DRS_STIPPLEPATTERN21 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3697 { /* 86, WINED3DRS_STIPPLEPATTERN22 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3698 { /* 87, WINED3DRS_STIPPLEPATTERN23 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3699 { /* 88, WINED3DRS_STIPPLEPATTERN24 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3700 { /* 89, WINED3DRS_STIPPLEPATTERN25 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3701 { /* 90, WINED3DRS_STIPPLEPATTERN26 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3702 { /* 91, WINED3DRS_STIPPLEPATTERN27 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3703 { /* 92, WINED3DRS_STIPPLEPATTERN28 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3704 { /* 93, WINED3DRS_STIPPLEPATTERN29 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3705 { /* 94, WINED3DRS_STIPPLEPATTERN30 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3706 { /* 95, WINED3DRS_STIPPLEPATTERN31 */ 0 /* Obsolete, should be handled by ddraw */, state_undefined },
3707 { /* 96, Undefined */ 0, state_undefined },
3708 { /* 97, Undefined */ 0, state_undefined },
3709 { /* 98, Undefined */ 0, state_undefined },
3710 { /* 99, Undefined */ 0, state_undefined },
3711 { /*100, Undefined */ 0, state_undefined },
3712 { /*101, Undefined */ 0, state_undefined },
3713 { /*102, Undefined */ 0, state_undefined },
3714 { /*103, Undefined */ 0, state_undefined },
3715 { /*104, Undefined */ 0, state_undefined },
3716 { /*105, Undefined */ 0, state_undefined },
3717 { /*106, Undefined */ 0, state_undefined },
3718 { /*107, Undefined */ 0, state_undefined },
3719 { /*108, Undefined */ 0, state_undefined },
3720 { /*109, Undefined */ 0, state_undefined },
3721 { /*110, Undefined */ 0, state_undefined },
3722 { /*111, Undefined */ 0, state_undefined },
3723 { /*112, Undefined */ 0, state_undefined },
3724 { /*113, Undefined */ 0, state_undefined },
3725 { /*114, Undefined */ 0, state_undefined },
3726 { /*115, Undefined */ 0, state_undefined },
3727 { /*116, Undefined */ 0, state_undefined },
3728 { /*117, Undefined */ 0, state_undefined },
3729 { /*118, Undefined */ 0, state_undefined },
3730 { /*119, Undefined */ 0, state_undefined },
3731 { /*120, Undefined */ 0, state_undefined },
3732 { /*121, Undefined */ 0, state_undefined },
3733 { /*122, Undefined */ 0, state_undefined },
3734 { /*123, Undefined */ 0, state_undefined },
3735 { /*124, Undefined */ 0, state_undefined },
3736 { /*125, Undefined */ 0, state_undefined },
3737 { /*126, Undefined */ 0, state_undefined },
3738 { /*127, Undefined */ 0, state_undefined },
3740 { /*128, WINED3DRS_WRAP0 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3741 { /*129, WINED3DRS_WRAP1 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3742 { /*130, WINED3DRS_WRAP2 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3743 { /*131, WINED3DRS_WRAP3 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3744 { /*132, WINED3DRS_WRAP4 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3745 { /*133, WINED3DRS_WRAP5 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3746 { /*134, WINED3DRS_WRAP6 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3747 { /*135, WINED3DRS_WRAP7 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3748 { /*136, WINED3DRS_CLIPPING */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3749 { /*137, WINED3DRS_LIGHTING */ STATE_RENDER(WINED3DRS_LIGHTING), state_lighting },
3750 { /*138, WINED3DRS_EXTENTS */ STATE_RENDER(WINED3DRS_EXTENTS), state_extents },
3751 { /*139, WINED3DRS_AMBIENT */ STATE_RENDER(WINED3DRS_AMBIENT), state_ambient },
3752 { /*140, WINED3DRS_FOGVERTEXMODE */ STATE_RENDER(WINED3DRS_FOGENABLE), state_fog },
3753 { /*141, WINED3DRS_COLORVERTEX */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3754 { /*142, WINED3DRS_LOCALVIEWER */ STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer },
3755 { /*143, WINED3DRS_NORMALIZENORMALS */ STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize },
3756 { /*144, WINED3DRS_COLORKEYBLENDENABLE */ STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend },
3757 { /*145, WINED3DRS_DIFFUSEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3758 { /*146, WINED3DRS_SPECULARMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3759 { /*147, WINED3DRS_AMBIENTMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3760 { /*148, WINED3DRS_EMISSIVEMATERIALSOURCE */ STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat },
3761 { /*149, Undefined */ 0, state_undefined },
3762 { /*150, Undefined */ 0, state_undefined },
3763 { /*151, WINED3DRS_VERTEXBLEND */ STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend },
3764 { /*152, WINED3DRS_CLIPPLANEENABLE */ STATE_RENDER(WINED3DRS_CLIPPING), state_clipping },
3765 { /*153, WINED3DRS_SOFTWAREVERTEXPROCESSING */ 0, state_nogl },
3766 { /*154, WINED3DRS_POINTSIZE */ STATE_RENDER(WINED3DRS_POINTSIZE), state_psize },
3767 { /*155, WINED3DRS_POINTSIZE_MIN */ STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin },
3768 { /*156, WINED3DRS_POINTSPRITEENABLE */ STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite },
3769 { /*157, WINED3DRS_POINTSCALEENABLE */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3770 { /*158, WINED3DRS_POINTSCALE_A */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3771 { /*159, WINED3DRS_POINTSCALE_B */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3772 { /*160, WINED3DRS_POINTSCALE_C */ STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale },
3773 { /*161, WINED3DRS_MULTISAMPLEANTIALIAS */ STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa },
3774 { /*162, WINED3DRS_MULTISAMPLEMASK */ STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask },
3775 { /*163, WINED3DRS_PATCHEDGESTYLE */ STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle},
3776 { /*164, WINED3DRS_PATCHSEGMENTS */ STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments },
3777 { /*165, WINED3DRS_DEBUGMONITORTOKEN */ STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_nogl },
3778 { /*166, WINED3DRS_POINTSIZE_MAX */ STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax },
3779 { /*167, WINED3DRS_INDEXEDVERTEXBLENDENABLE */ 0, state_nogl },
3780 { /*168, WINED3DRS_COLORWRITEENABLE */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3781 { /*169, Undefined */ 0, state_undefined },
3782 { /*170, WINED3DRS_TWEENFACTOR */ 0, state_nogl },
3783 { /*171, WINED3DRS_BLENDOP */ STATE_RENDER(WINED3DRS_BLENDOP), state_blendop },
3784 { /*172, WINED3DRS_POSITIONDEGREE */ STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree},
3785 { /*173, WINED3DRS_NORMALDEGREE */ STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree },
3786 /*172, WINED3DRS_POSITIONORDER */ /* Value assigned to 2 state names */
3787 /*173, WINED3DRS_NORMALORDER */ /* Value assigned to 2 state names */
3788 { /*174, WINED3DRS_SCISSORTESTENABLE */ STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor },
3789 { /*175, WINED3DRS_SLOPESCALEDEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3790 { /*176, WINED3DRS_ANTIALIASEDLINEENABLE */ STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend },
3791 { /*177, undefined */ 0, state_undefined },
3792 { /*178, WINED3DRS_MINTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3793 { /*179, WINED3DRS_MAXTESSELLATIONLEVEL */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3794 { /*180, WINED3DRS_ADAPTIVETESS_X */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3795 { /*181, WINED3DRS_ADAPTIVETESS_Y */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3796 { /*182, WINED3DRS_ADAPTIVETESS_Z */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3797 { /*183, WINED3DRS_ADAPTIVETESS_W */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3798 { /*184, WINED3DRS_ENABLEADAPTIVETESSELLATION */ STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation },
3799 { /*185, WINED3DRS_TWOSIDEDSTENCILMODE */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3800 { /*186, WINED3DRS_CCW_STENCILFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3801 { /*187, WINED3DRS_CCW_STENCILZFAIL */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3802 { /*188, WINED3DRS_CCW_STENCILPASS */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3803 { /*189, WINED3DRS_CCW_STENCILFUNC */ STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil },
3804 { /*190, WINED3DRS_COLORWRITEENABLE1 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3805 { /*191, WINED3DRS_COLORWRITEENABLE2 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3806 { /*192, WINED3DRS_COLORWRITEENABLE3 */ STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite },
3807 { /*193, WINED3DRS_BLENDFACTOR */ STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor },
3808 { /*194, WINED3DRS_SRGBWRITEENABLE */ STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), state_srgbwrite },
3809 { /*195, WINED3DRS_DEPTHBIAS */ STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias },
3810 { /*196, undefined */ 0, state_undefined },
3811 { /*197, undefined */ 0, state_undefined },
3812 { /*198, WINED3DRS_WRAP8 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3813 { /*199, WINED3DRS_WRAP9 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3814 { /*200, WINED3DRS_WRAP10 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3815 { /*201, WINED3DRS_WRAP11 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3816 { /*202, WINED3DRS_WRAP12 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3817 { /*203, WINED3DRS_WRAP13 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3818 { /*204, WINED3DRS_WRAP14 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3819 { /*205, WINED3DRS_WRAP15 */ STATE_RENDER(WINED3DRS_WRAP0), state_wrap },
3820 { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3821 { /*207, WINED3DRS_SRCBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3822 { /*208, WINED3DRS_DESTBLENDALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3823 { /*209, WINED3DRS_BLENDOPALPHA */ STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), state_separateblend },
3824 /* Texture stage states */
3825 { /*0, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3826 { /*0, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3827 { /*0, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3828 { /*0, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3829 { /*0, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3830 { /*0, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3831 { /*0, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3832 { /*0, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3833 { /*0, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3834 { /*0, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3835 { /*0, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3836 { /*0, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3837 { /*0, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3838 { /*0, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3839 { /*0, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3840 { /*0, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3841 { /*0, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3842 { /*0, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3843 { /*0, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3844 { /*0, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3845 { /*0, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3846 { /*0, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3847 { /*0, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3848 { /*0, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
3849 { /*0, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3850 { /*0, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop },
3851 { /*0, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop },
3852 { /*0, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), tex_resultarg },
3853 { /*0, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3854 { /*0, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3855 { /*0, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3856 { /*0, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3858 { /*1, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3859 { /*1, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3860 { /*1, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3861 { /*1, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3862 { /*1, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3863 { /*1, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3864 { /*1, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3865 { /*1, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3866 { /*1, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3867 { /*1, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3868 { /*1, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3869 { /*1, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3870 { /*1, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3871 { /*1, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3872 { /*1, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3873 { /*1, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3874 { /*1, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3875 { /*1, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3876 { /*1, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3877 { /*1, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3878 { /*1, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3879 { /*1, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3880 { /*1, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3881 { /*1, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
3882 { /*1, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3883 { /*1, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop },
3884 { /*1, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop },
3885 { /*1, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), tex_resultarg },
3886 { /*1, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3887 { /*1, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3888 { /*1, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3889 { /*1, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3891 { /*2, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3892 { /*2, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3893 { /*2, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3894 { /*2, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3895 { /*2, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3896 { /*2, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3897 { /*2, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3898 { /*2, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3899 { /*2, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3900 { /*2, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3901 { /*2, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3902 { /*2, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3903 { /*2, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3904 { /*2, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3905 { /*2, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3906 { /*2, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3907 { /*2, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3908 { /*2, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3909 { /*2, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3910 { /*2, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3911 { /*2, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3912 { /*2, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3913 { /*2, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3914 { /*2, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
3915 { /*2, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3916 { /*2, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop },
3917 { /*2, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop },
3918 { /*2, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), tex_resultarg },
3919 { /*2, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3920 { /*2, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3921 { /*2, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3922 { /*2, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3924 { /*3, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3925 { /*3, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3926 { /*3, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3927 { /*3, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3928 { /*3, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3929 { /*3, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3930 { /*3, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3931 { /*3, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3932 { /*3, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3933 { /*3, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3934 { /*3, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3935 { /*3, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3936 { /*3, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3937 { /*3, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3938 { /*3, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3939 { /*3, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3940 { /*3, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3941 { /*3, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3942 { /*3, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3943 { /*3, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3944 { /*3, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3945 { /*3, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3946 { /*3, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3947 { /*3, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
3948 { /*3, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3949 { /*3, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop },
3950 { /*3, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop },
3951 { /*3, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), tex_resultarg },
3952 { /*3, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3953 { /*3, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3954 { /*3, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3955 { /*3, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3957 { /*4, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3958 { /*4, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3959 { /*4, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3960 { /*4, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3961 { /*4, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3962 { /*4, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3963 { /*4, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3964 { /*4, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3965 { /*4, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3966 { /*4, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3967 { /*4, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
3968 { /*4, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3969 { /*4, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3970 { /*4, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3971 { /*4, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3972 { /*4, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3973 { /*4, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3974 { /*4, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3975 { /*4, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3976 { /*4, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3977 { /*4, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3978 { /*4, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
3979 { /*4, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
3980 { /*4, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
3981 { /*4, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3982 { /*4, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop },
3983 { /*4, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop },
3984 { /*4, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), tex_resultarg },
3985 { /*4, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3986 { /*4, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3987 { /*4, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
3988 { /*4, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
3990 { /*5, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3991 { /*5, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3992 { /*5, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
3993 { /*5, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3994 { /*5, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3995 { /*5, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
3996 { /*5, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3997 { /*5, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3998 { /*5, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
3999 { /*5, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4000 { /*5, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4001 { /*5, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4002 { /*5, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4003 { /*5, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4004 { /*5, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4005 { /*5, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4006 { /*5, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4007 { /*5, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4008 { /*5, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4009 { /*5, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4010 { /*5, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4011 { /*5, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4012 { /*5, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4013 { /*5, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4014 { /*5, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4015 { /*5, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop },
4016 { /*5, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop },
4017 { /*5, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), tex_resultarg },
4018 { /*5, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4019 { /*5, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4020 { /*5, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4021 { /*5, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4023 { /*6, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4024 { /*6, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4025 { /*6, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4026 { /*6, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4027 { /*6, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4028 { /*6, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4029 { /*6, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4030 { /*6, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4031 { /*6, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4032 { /*6, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4033 { /*6, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4034 { /*6, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4035 { /*6, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4036 { /*6, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4037 { /*6, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4038 { /*6, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4039 { /*6, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4040 { /*6, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4041 { /*6, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4042 { /*6, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4043 { /*6, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4044 { /*6, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4045 { /*6, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4046 { /*6, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4047 { /*6, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4048 { /*6, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop },
4049 { /*6, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop },
4050 { /*6, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), tex_resultarg },
4051 { /*6, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4052 { /*6, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4053 { /*6, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4054 { /*6, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4056 { /*7, 01, WINED3DTSS_COLOROP */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4057 { /*7, 02, WINED3DTSS_COLORARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4058 { /*7, 03, WINED3DTSS_COLORARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4059 { /*7, 04, WINED3DTSS_ALPHAOP */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4060 { /*7, 05, WINED3DTSS_ALPHAARG1 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4061 { /*7, 06, WINED3DTSS_ALPHAARG2 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4062 { /*7, 07, WINED3DTSS_BUMPENVMAT00 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4063 { /*7, 08, WINED3DTSS_BUMPENVMAT01 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4064 { /*7, 09, WINED3DTSS_BUMPENVMAT10 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4065 { /*7, 10, WINED3DTSS_BUMPENVMAT11 */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat },
4066 { /*7, 11, WINED3DTSS_TEXCOORDINDEX */ STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex },
4067 { /*7, 12, WINED3DTSS_ADDRESS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4068 { /*7, 13, WINED3DTSS_ADDRESSU */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4069 { /*7, 14, WINED3DTSS_ADDRESSV */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4070 { /*7, 15, WINED3DTSS_BORDERCOLOR */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4071 { /*7, 16, WINED3DTSS_MAGFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4072 { /*7, 17, WINED3DTSS_MINFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4073 { /*7, 18, WINED3DTSS_MIPFILTER */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4074 { /*7, 19, WINED3DTSS_MIPMAPLODBIAS */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4075 { /*7, 20, WINED3DTSS_MAXMIPLEVEL */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4076 { /*7, 21, WINED3DTSS_MAXANISOTROPY */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4077 { /*7, 22, WINED3DTSS_BUMPENVLSCALE */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale },
4078 { /*7, 23, WINED3DTSS_BUMPENVLOFFSET */ STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset },
4079 { /*7, 24, WINED3DTSS_TEXTURETRANSFORMFLAGS */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4080 { /*7, 25, WINED3DTSS_ADDRESSW */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4081 { /*7, 26, WINED3DTSS_COLORARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop },
4082 { /*7, 27, WINED3DTSS_ALPHAARG0 */ STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop },
4083 { /*7, 28, WINED3DTSS_RESULTARG */ STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), tex_resultarg },
4084 { /*7, 29, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4085 { /*7, 30, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4086 { /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
4087 { /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
4088 /* Sampler states */
4089 { /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
4090 { /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
4091 { /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
4092 { /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
4093 { /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
4094 { /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
4095 { /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
4096 { /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
4097 { /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
4098 { /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
4099 { /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
4100 { /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
4101 { /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
4102 { /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
4103 { /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
4104 { /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
4105 { /*16, Vertex sampler 0 */ STATE_SAMPLER(16), sampler },
4106 { /*17, Vertex sampler 1 */ STATE_SAMPLER(17), sampler },
4107 { /*18, Vertex sampler 2 */ STATE_SAMPLER(18), sampler },
4108 { /*19, Vertex sampler 3 */ STATE_SAMPLER(19), sampler },
4110 { /* , Pixel Shader */ STATE_PIXELSHADER, pixelshader },
4111 /* Transform states follow */
4112 { /* 1, undefined */ 0, state_undefined },
4113 { /* 2, WINED3DTS_VIEW */ STATE_TRANSFORM(WINED3DTS_VIEW), transform_view },
4114 { /* 3, WINED3DTS_PROJECTION */ STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection},
4115 { /* 4, undefined */ 0, state_undefined },
4116 { /* 5, undefined */ 0, state_undefined },
4117 { /* 6, undefined */ 0, state_undefined },
4118 { /* 7, undefined */ 0, state_undefined },
4119 { /* 8, undefined */ 0, state_undefined },
4120 { /* 9, undefined */ 0, state_undefined },
4121 { /* 10, undefined */ 0, state_undefined },
4122 { /* 11, undefined */ 0, state_undefined },
4123 { /* 12, undefined */ 0, state_undefined },
4124 { /* 13, undefined */ 0, state_undefined },
4125 { /* 14, undefined */ 0, state_undefined },
4126 { /* 15, undefined */ 0, state_undefined },
4127 { /* 16, WINED3DTS_TEXTURE0 */ STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture },
4128 { /* 17, WINED3DTS_TEXTURE1 */ STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture },
4129 { /* 18, WINED3DTS_TEXTURE2 */ STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture },
4130 { /* 19, WINED3DTS_TEXTURE3 */ STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture },
4131 { /* 20, WINED3DTS_TEXTURE4 */ STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture },
4132 { /* 21, WINED3DTS_TEXTURE5 */ STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture },
4133 { /* 22, WINED3DTS_TEXTURE6 */ STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture },
4134 { /* 23, WINED3DTS_TEXTURE7 */ STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture },
4135 /* A huge gap between TEXTURE7 and WORLDMATRIX(0) :-( But entries are needed to catch then if a broken app sets them */
4136 { /* 24, undefined */ 0, state_undefined },
4137 { /* 25, undefined */ 0, state_undefined },
4138 { /* 26, undefined */ 0, state_undefined },
4139 { /* 27, undefined */ 0, state_undefined },
4140 { /* 28, undefined */ 0, state_undefined },
4141 { /* 29, undefined */ 0, state_undefined },
4142 { /* 30, undefined */ 0, state_undefined },
4143 { /* 31, undefined */ 0, state_undefined },
4144 { /* 32, undefined */ 0, state_undefined },
4145 { /* 33, undefined */ 0, state_undefined },
4146 { /* 34, undefined */ 0, state_undefined },
4147 { /* 35, undefined */ 0, state_undefined },
4148 { /* 36, undefined */ 0, state_undefined },
4149 { /* 37, undefined */ 0, state_undefined },
4150 { /* 38, undefined */ 0, state_undefined },
4151 { /* 39, undefined */ 0, state_undefined },
4152 { /* 40, undefined */ 0, state_undefined },
4153 { /* 41, undefined */ 0, state_undefined },
4154 { /* 42, undefined */ 0, state_undefined },
4155 { /* 43, undefined */ 0, state_undefined },
4156 { /* 44, undefined */ 0, state_undefined },
4157 { /* 45, undefined */ 0, state_undefined },
4158 { /* 46, undefined */ 0, state_undefined },
4159 { /* 47, undefined */ 0, state_undefined },
4160 { /* 48, undefined */ 0, state_undefined },
4161 { /* 49, undefined */ 0, state_undefined },
4162 { /* 50, undefined */ 0, state_undefined },
4163 { /* 51, undefined */ 0, state_undefined },
4164 { /* 52, undefined */ 0, state_undefined },
4165 { /* 53, undefined */ 0, state_undefined },
4166 { /* 54, undefined */ 0, state_undefined },
4167 { /* 55, undefined */ 0, state_undefined },
4168 { /* 56, undefined */ 0, state_undefined },
4169 { /* 57, undefined */ 0, state_undefined },
4170 { /* 58, undefined */ 0, state_undefined },
4171 { /* 59, undefined */ 0, state_undefined },
4172 { /* 60, undefined */ 0, state_undefined },
4173 { /* 61, undefined */ 0, state_undefined },
4174 { /* 62, undefined */ 0, state_undefined },
4175 { /* 63, undefined */ 0, state_undefined },
4176 { /* 64, undefined */ 0, state_undefined },
4177 { /* 65, undefined */ 0, state_undefined },
4178 { /* 66, undefined */ 0, state_undefined },
4179 { /* 67, undefined */ 0, state_undefined },
4180 { /* 68, undefined */ 0, state_undefined },
4181 { /* 69, undefined */ 0, state_undefined },
4182 { /* 70, undefined */ 0, state_undefined },
4183 { /* 71, undefined */ 0, state_undefined },
4184 { /* 72, undefined */ 0, state_undefined },
4185 { /* 73, undefined */ 0, state_undefined },
4186 { /* 74, undefined */ 0, state_undefined },
4187 { /* 75, undefined */ 0, state_undefined },
4188 { /* 76, undefined */ 0, state_undefined },
4189 { /* 77, undefined */ 0, state_undefined },
4190 { /* 78, undefined */ 0, state_undefined },
4191 { /* 79, undefined */ 0, state_undefined },
4192 { /* 80, undefined */ 0, state_undefined },
4193 { /* 81, undefined */ 0, state_undefined },
4194 { /* 82, undefined */ 0, state_undefined },
4195 { /* 83, undefined */ 0, state_undefined },
4196 { /* 84, undefined */ 0, state_undefined },
4197 { /* 85, undefined */ 0, state_undefined },
4198 { /* 86, undefined */ 0, state_undefined },
4199 { /* 87, undefined */ 0, state_undefined },
4200 { /* 88, undefined */ 0, state_undefined },
4201 { /* 89, undefined */ 0, state_undefined },
4202 { /* 90, undefined */ 0, state_undefined },
4203 { /* 91, undefined */ 0, state_undefined },
4204 { /* 92, undefined */ 0, state_undefined },
4205 { /* 93, undefined */ 0, state_undefined },
4206 { /* 94, undefined */ 0, state_undefined },
4207 { /* 95, undefined */ 0, state_undefined },
4208 { /* 96, undefined */ 0, state_undefined },
4209 { /* 97, undefined */ 0, state_undefined },
4210 { /* 98, undefined */ 0, state_undefined },
4211 { /* 99, undefined */ 0, state_undefined },
4212 { /*100, undefined */ 0, state_undefined },
4213 { /*101, undefined */ 0, state_undefined },
4214 { /*102, undefined */ 0, state_undefined },
4215 { /*103, undefined */ 0, state_undefined },
4216 { /*104, undefined */ 0, state_undefined },
4217 { /*105, undefined */ 0, state_undefined },
4218 { /*106, undefined */ 0, state_undefined },
4219 { /*107, undefined */ 0, state_undefined },
4220 { /*108, undefined */ 0, state_undefined },
4221 { /*109, undefined */ 0, state_undefined },
4222 { /*110, undefined */ 0, state_undefined },
4223 { /*111, undefined */ 0, state_undefined },
4224 { /*112, undefined */ 0, state_undefined },
4225 { /*113, undefined */ 0, state_undefined },
4226 { /*114, undefined */ 0, state_undefined },
4227 { /*115, undefined */ 0, state_undefined },
4228 { /*116, undefined */ 0, state_undefined },
4229 { /*117, undefined */ 0, state_undefined },
4230 { /*118, undefined */ 0, state_undefined },
4231 { /*119, undefined */ 0, state_undefined },
4232 { /*120, undefined */ 0, state_undefined },
4233 { /*121, undefined */ 0, state_undefined },
4234 { /*122, undefined */ 0, state_undefined },
4235 { /*123, undefined */ 0, state_undefined },
4236 { /*124, undefined */ 0, state_undefined },
4237 { /*125, undefined */ 0, state_undefined },
4238 { /*126, undefined */ 0, state_undefined },
4239 { /*127, undefined */ 0, state_undefined },
4240 { /*128, undefined */ 0, state_undefined },
4241 { /*129, undefined */ 0, state_undefined },
4242 { /*130, undefined */ 0, state_undefined },
4243 { /*131, undefined */ 0, state_undefined },
4244 { /*132, undefined */ 0, state_undefined },
4245 { /*133, undefined */ 0, state_undefined },
4246 { /*134, undefined */ 0, state_undefined },
4247 { /*135, undefined */ 0, state_undefined },
4248 { /*136, undefined */ 0, state_undefined },
4249 { /*137, undefined */ 0, state_undefined },
4250 { /*138, undefined */ 0, state_undefined },
4251 { /*139, undefined */ 0, state_undefined },
4252 { /*140, undefined */ 0, state_undefined },
4253 { /*141, undefined */ 0, state_undefined },
4254 { /*142, undefined */ 0, state_undefined },
4255 { /*143, undefined */ 0, state_undefined },
4256 { /*144, undefined */ 0, state_undefined },
4257 { /*145, undefined */ 0, state_undefined },
4258 { /*146, undefined */ 0, state_undefined },
4259 { /*147, undefined */ 0, state_undefined },
4260 { /*148, undefined */ 0, state_undefined },
4261 { /*149, undefined */ 0, state_undefined },
4262 { /*150, undefined */ 0, state_undefined },
4263 { /*151, undefined */ 0, state_undefined },
4264 { /*152, undefined */ 0, state_undefined },
4265 { /*153, undefined */ 0, state_undefined },
4266 { /*154, undefined */ 0, state_undefined },
4267 { /*155, undefined */ 0, state_undefined },
4268 { /*156, undefined */ 0, state_undefined },
4269 { /*157, undefined */ 0, state_undefined },
4270 { /*158, undefined */ 0, state_undefined },
4271 { /*159, undefined */ 0, state_undefined },
4272 { /*160, undefined */ 0, state_undefined },
4273 { /*161, undefined */ 0, state_undefined },
4274 { /*162, undefined */ 0, state_undefined },
4275 { /*163, undefined */ 0, state_undefined },
4276 { /*164, undefined */ 0, state_undefined },
4277 { /*165, undefined */ 0, state_undefined },
4278 { /*166, undefined */ 0, state_undefined },
4279 { /*167, undefined */ 0, state_undefined },
4280 { /*168, undefined */ 0, state_undefined },
4281 { /*169, undefined */ 0, state_undefined },
4282 { /*170, undefined */ 0, state_undefined },
4283 { /*171, undefined */ 0, state_undefined },
4284 { /*172, undefined */ 0, state_undefined },
4285 { /*173, undefined */ 0, state_undefined },
4286 { /*174, undefined */ 0, state_undefined },
4287 { /*175, undefined */ 0, state_undefined },
4288 { /*176, undefined */ 0, state_undefined },
4289 { /*177, undefined */ 0, state_undefined },
4290 { /*178, undefined */ 0, state_undefined },
4291 { /*179, undefined */ 0, state_undefined },
4292 { /*180, undefined */ 0, state_undefined },
4293 { /*181, undefined */ 0, state_undefined },
4294 { /*182, undefined */ 0, state_undefined },
4295 { /*183, undefined */ 0, state_undefined },
4296 { /*184, undefined */ 0, state_undefined },
4297 { /*185, undefined */ 0, state_undefined },
4298 { /*186, undefined */ 0, state_undefined },
4299 { /*187, undefined */ 0, state_undefined },
4300 { /*188, undefined */ 0, state_undefined },
4301 { /*189, undefined */ 0, state_undefined },
4302 { /*190, undefined */ 0, state_undefined },
4303 { /*191, undefined */ 0, state_undefined },
4304 { /*192, undefined */ 0, state_undefined },
4305 { /*193, undefined */ 0, state_undefined },
4306 { /*194, undefined */ 0, state_undefined },
4307 { /*195, undefined */ 0, state_undefined },
4308 { /*196, undefined */ 0, state_undefined },
4309 { /*197, undefined */ 0, state_undefined },
4310 { /*198, undefined */ 0, state_undefined },
4311 { /*199, undefined */ 0, state_undefined },
4312 { /*200, undefined */ 0, state_undefined },
4313 { /*201, undefined */ 0, state_undefined },
4314 { /*202, undefined */ 0, state_undefined },
4315 { /*203, undefined */ 0, state_undefined },
4316 { /*204, undefined */ 0, state_undefined },
4317 { /*205, undefined */ 0, state_undefined },
4318 { /*206, undefined */ 0, state_undefined },
4319 { /*207, undefined */ 0, state_undefined },
4320 { /*208, undefined */ 0, state_undefined },
4321 { /*209, undefined */ 0, state_undefined },
4322 { /*210, undefined */ 0, state_undefined },
4323 { /*211, undefined */ 0, state_undefined },
4324 { /*212, undefined */ 0, state_undefined },
4325 { /*213, undefined */ 0, state_undefined },
4326 { /*214, undefined */ 0, state_undefined },
4327 { /*215, undefined */ 0, state_undefined },
4328 { /*216, undefined */ 0, state_undefined },
4329 { /*217, undefined */ 0, state_undefined },
4330 { /*218, undefined */ 0, state_undefined },
4331 { /*219, undefined */ 0, state_undefined },
4332 { /*220, undefined */ 0, state_undefined },
4333 { /*221, undefined */ 0, state_undefined },
4334 { /*222, undefined */ 0, state_undefined },
4335 { /*223, undefined */ 0, state_undefined },
4336 { /*224, undefined */ 0, state_undefined },
4337 { /*225, undefined */ 0, state_undefined },
4338 { /*226, undefined */ 0, state_undefined },
4339 { /*227, undefined */ 0, state_undefined },
4340 { /*228, undefined */ 0, state_undefined },
4341 { /*229, undefined */ 0, state_undefined },
4342 { /*230, undefined */ 0, state_undefined },
4343 { /*231, undefined */ 0, state_undefined },
4344 { /*232, undefined */ 0, state_undefined },
4345 { /*233, undefined */ 0, state_undefined },
4346 { /*234, undefined */ 0, state_undefined },
4347 { /*235, undefined */ 0, state_undefined },
4348 { /*236, undefined */ 0, state_undefined },
4349 { /*237, undefined */ 0, state_undefined },
4350 { /*238, undefined */ 0, state_undefined },
4351 { /*239, undefined */ 0, state_undefined },
4352 { /*240, undefined */ 0, state_undefined },
4353 { /*241, undefined */ 0, state_undefined },
4354 { /*242, undefined */ 0, state_undefined },
4355 { /*243, undefined */ 0, state_undefined },
4356 { /*244, undefined */ 0, state_undefined },
4357 { /*245, undefined */ 0, state_undefined },
4358 { /*246, undefined */ 0, state_undefined },
4359 { /*247, undefined */ 0, state_undefined },
4360 { /*248, undefined */ 0, state_undefined },
4361 { /*249, undefined */ 0, state_undefined },
4362 { /*250, undefined */ 0, state_undefined },
4363 { /*251, undefined */ 0, state_undefined },
4364 { /*252, undefined */ 0, state_undefined },
4365 { /*253, undefined */ 0, state_undefined },
4366 { /*254, undefined */ 0, state_undefined },
4367 { /*255, undefined */ 0, state_undefined },
4369 { /*256, WINED3DTS_WORLDMATRIX(0) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), transform_world },
4370 { /*257, WINED3DTS_WORLDMATRIX(1) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(1)), transform_worldex },
4371 { /*258, WINED3DTS_WORLDMATRIX(2) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(2)), transform_worldex },
4372 { /*259, WINED3DTS_WORLDMATRIX(3) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(3)), transform_worldex },
4373 { /*260, WINED3DTS_WORLDMATRIX(4) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(4)), transform_worldex },
4374 { /*261, WINED3DTS_WORLDMATRIX(5) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(5)), transform_worldex },
4375 { /*262, WINED3DTS_WORLDMATRIX(6) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(6)), transform_worldex },
4376 { /*263, WINED3DTS_WORLDMATRIX(7) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(7)), transform_worldex },
4377 { /*264, WINED3DTS_WORLDMATRIX(8) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(8)), transform_worldex },
4378 { /*265, WINED3DTS_WORLDMATRIX(9) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(9)), transform_worldex },
4379 { /*266, WINED3DTS_WORLDMATRIX(10) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(10)), transform_worldex },
4380 { /*267, WINED3DTS_WORLDMATRIX(11) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(11)), transform_worldex },
4381 { /*268, WINED3DTS_WORLDMATRIX(12) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(12)), transform_worldex },
4382 { /*269, WINED3DTS_WORLDMATRIX(13) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(13)), transform_worldex },
4383 { /*270, WINED3DTS_WORLDMATRIX(14) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(14)), transform_worldex },
4384 { /*271, WINED3DTS_WORLDMATRIX(15) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(15)), transform_worldex },
4385 { /*272, WINED3DTS_WORLDMATRIX(16) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(16)), transform_worldex },
4386 { /*273, WINED3DTS_WORLDMATRIX(17) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(17)), transform_worldex },
4387 { /*274, WINED3DTS_WORLDMATRIX(18) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(18)), transform_worldex },
4388 { /*275, WINED3DTS_WORLDMATRIX(19) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(19)), transform_worldex },
4389 { /*276, WINED3DTS_WORLDMATRIX(20) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(20)), transform_worldex },
4390 { /*277, WINED3DTS_WORLDMATRIX(21) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(21)), transform_worldex },
4391 { /*278, WINED3DTS_WORLDMATRIX(22) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(22)), transform_worldex },
4392 { /*279, WINED3DTS_WORLDMATRIX(23) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(23)), transform_worldex },
4393 { /*280, WINED3DTS_WORLDMATRIX(24) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(24)), transform_worldex },
4394 { /*281, WINED3DTS_WORLDMATRIX(25) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(25)), transform_worldex },
4395 { /*282, WINED3DTS_WORLDMATRIX(26) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(26)), transform_worldex },
4396 { /*283, WINED3DTS_WORLDMATRIX(27) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(27)), transform_worldex },
4397 { /*284, WINED3DTS_WORLDMATRIX(28) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(28)), transform_worldex },
4398 { /*285, WINED3DTS_WORLDMATRIX(29) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(29)), transform_worldex },
4399 { /*286, WINED3DTS_WORLDMATRIX(30) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(30)), transform_worldex },
4400 { /*287, WINED3DTS_WORLDMATRIX(31) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(31)), transform_worldex },
4401 { /*288, WINED3DTS_WORLDMATRIX(32) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(32)), transform_worldex },
4402 { /*289, WINED3DTS_WORLDMATRIX(33) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(33)), transform_worldex },
4403 { /*290, WINED3DTS_WORLDMATRIX(34) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(34)), transform_worldex },
4404 { /*291, WINED3DTS_WORLDMATRIX(35) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(35)), transform_worldex },
4405 { /*292, WINED3DTS_WORLDMATRIX(36) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(36)), transform_worldex },
4406 { /*293, WINED3DTS_WORLDMATRIX(37) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(37)), transform_worldex },
4407 { /*294, WINED3DTS_WORLDMATRIX(38) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(38)), transform_worldex },
4408 { /*295, WINED3DTS_WORLDMATRIX(39) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(39)), transform_worldex },
4409 { /*296, WINED3DTS_WORLDMATRIX(40) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(40)), transform_worldex },
4410 { /*297, WINED3DTS_WORLDMATRIX(41) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(41)), transform_worldex },
4411 { /*298, WINED3DTS_WORLDMATRIX(42) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(42)), transform_worldex },
4412 { /*299, WINED3DTS_WORLDMATRIX(43) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(43)), transform_worldex },
4413 { /*300, WINED3DTS_WORLDMATRIX(44) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(44)), transform_worldex },
4414 { /*301, WINED3DTS_WORLDMATRIX(45) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(45)), transform_worldex },
4415 { /*302, WINED3DTS_WORLDMATRIX(46) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(46)), transform_worldex },
4416 { /*303, WINED3DTS_WORLDMATRIX(47) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(47)), transform_worldex },
4417 { /*304, WINED3DTS_WORLDMATRIX(48) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(48)), transform_worldex },
4418 { /*305, WINED3DTS_WORLDMATRIX(49) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(49)), transform_worldex },
4419 { /*306, WINED3DTS_WORLDMATRIX(50) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(50)), transform_worldex },
4420 { /*307, WINED3DTS_WORLDMATRIX(51) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(51)), transform_worldex },
4421 { /*308, WINED3DTS_WORLDMATRIX(52) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(52)), transform_worldex },
4422 { /*309, WINED3DTS_WORLDMATRIX(53) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(53)), transform_worldex },
4423 { /*310, WINED3DTS_WORLDMATRIX(54) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(54)), transform_worldex },
4424 { /*311, WINED3DTS_WORLDMATRIX(55) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(55)), transform_worldex },
4425 { /*312, WINED3DTS_WORLDMATRIX(56) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(56)), transform_worldex },
4426 { /*313, WINED3DTS_WORLDMATRIX(57) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(57)), transform_worldex },
4427 { /*314, WINED3DTS_WORLDMATRIX(58) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(58)), transform_worldex },
4428 { /*315, WINED3DTS_WORLDMATRIX(59) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(59)), transform_worldex },
4429 { /*316, WINED3DTS_WORLDMATRIX(60) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(60)), transform_worldex },
4430 { /*317, WINED3DTS_WORLDMATRIX(61) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(61)), transform_worldex },
4431 { /*318, WINED3DTS_WORLDMATRIX(62) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(62)), transform_worldex },
4432 { /*319, WINED3DTS_WORLDMATRIX(63) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(63)), transform_worldex },
4433 { /*320, WINED3DTS_WORLDMATRIX(64) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(64)), transform_worldex },
4434 { /*321, WINED3DTS_WORLDMATRIX(65) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(65)), transform_worldex },
4435 { /*322, WINED3DTS_WORLDMATRIX(66) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(66)), transform_worldex },
4436 { /*323, WINED3DTS_WORLDMATRIX(67) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(67)), transform_worldex },
4437 { /*324, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(68)), transform_worldex },
4438 { /*325, WINED3DTS_WORLDMATRIX(68) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(69)), transform_worldex },
4439 { /*326, WINED3DTS_WORLDMATRIX(70) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(70)), transform_worldex },
4440 { /*327, WINED3DTS_WORLDMATRIX(71) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(71)), transform_worldex },
4441 { /*328, WINED3DTS_WORLDMATRIX(72) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(72)), transform_worldex },
4442 { /*329, WINED3DTS_WORLDMATRIX(73) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(73)), transform_worldex },
4443 { /*330, WINED3DTS_WORLDMATRIX(74) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(74)), transform_worldex },
4444 { /*331, WINED3DTS_WORLDMATRIX(75) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(75)), transform_worldex },
4445 { /*332, WINED3DTS_WORLDMATRIX(76) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(76)), transform_worldex },
4446 { /*333, WINED3DTS_WORLDMATRIX(77) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(77)), transform_worldex },
4447 { /*334, WINED3DTS_WORLDMATRIX(78) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(78)), transform_worldex },
4448 { /*335, WINED3DTS_WORLDMATRIX(79) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(79)), transform_worldex },
4449 { /*336, WINED3DTS_WORLDMATRIX(80) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(80)), transform_worldex },
4450 { /*337, WINED3DTS_WORLDMATRIX(81) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(81)), transform_worldex },
4451 { /*338, WINED3DTS_WORLDMATRIX(82) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(82)), transform_worldex },
4452 { /*339, WINED3DTS_WORLDMATRIX(83) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(83)), transform_worldex },
4453 { /*340, WINED3DTS_WORLDMATRIX(84) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(84)), transform_worldex },
4454 { /*341, WINED3DTS_WORLDMATRIX(85) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(85)), transform_worldex },
4455 { /*341, WINED3DTS_WORLDMATRIX(86) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(86)), transform_worldex },
4456 { /*343, WINED3DTS_WORLDMATRIX(87) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(87)), transform_worldex },
4457 { /*344, WINED3DTS_WORLDMATRIX(88) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(88)), transform_worldex },
4458 { /*345, WINED3DTS_WORLDMATRIX(89) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(89)), transform_worldex },
4459 { /*346, WINED3DTS_WORLDMATRIX(90) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(90)), transform_worldex },
4460 { /*347, WINED3DTS_WORLDMATRIX(91) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(91)), transform_worldex },
4461 { /*348, WINED3DTS_WORLDMATRIX(92) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(92)), transform_worldex },
4462 { /*349, WINED3DTS_WORLDMATRIX(93) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(93)), transform_worldex },
4463 { /*350, WINED3DTS_WORLDMATRIX(94) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(94)), transform_worldex },
4464 { /*351, WINED3DTS_WORLDMATRIX(95) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(95)), transform_worldex },
4465 { /*352, WINED3DTS_WORLDMATRIX(96) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(96)), transform_worldex },
4466 { /*353, WINED3DTS_WORLDMATRIX(97) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(97)), transform_worldex },
4467 { /*354, WINED3DTS_WORLDMATRIX(98) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(98)), transform_worldex },
4468 { /*355, WINED3DTS_WORLDMATRIX(99) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(99)), transform_worldex },
4469 { /*356, WINED3DTS_WORLDMATRIX(100) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex },
4470 { /*357, WINED3DTS_WORLDMATRIX(101) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex },
4471 { /*358, WINED3DTS_WORLDMATRIX(102) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex },
4472 { /*359, WINED3DTS_WORLDMATRIX(103) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex },
4473 { /*360, WINED3DTS_WORLDMATRIX(104) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex },
4474 { /*361, WINED3DTS_WORLDMATRIX(105) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex },
4475 { /*362, WINED3DTS_WORLDMATRIX(106) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex },
4476 { /*363, WINED3DTS_WORLDMATRIX(107) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex },
4477 { /*364, WINED3DTS_WORLDMATRIX(108) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex },
4478 { /*365, WINED3DTS_WORLDMATRIX(109) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex },
4479 { /*366, WINED3DTS_WORLDMATRIX(110) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex },
4480 { /*367, WINED3DTS_WORLDMATRIX(111) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex },
4481 { /*368, WINED3DTS_WORLDMATRIX(112) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex },
4482 { /*369, WINED3DTS_WORLDMATRIX(113) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex },
4483 { /*370, WINED3DTS_WORLDMATRIX(114) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex },
4484 { /*371, WINED3DTS_WORLDMATRIX(115) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex },
4485 { /*372, WINED3DTS_WORLDMATRIX(116) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex },
4486 { /*373, WINED3DTS_WORLDMATRIX(117) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex },
4487 { /*374, WINED3DTS_WORLDMATRIX(118) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex },
4488 { /*375, WINED3DTS_WORLDMATRIX(119) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex },
4489 { /*376, WINED3DTS_WORLDMATRIX(120) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex },
4490 { /*377, WINED3DTS_WORLDMATRIX(121) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex },
4491 { /*378, WINED3DTS_WORLDMATRIX(122) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex },
4492 { /*379, WINED3DTS_WORLDMATRIX(123) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex },
4493 { /*380, WINED3DTS_WORLDMATRIX(124) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex },
4494 { /*381, WINED3DTS_WORLDMATRIX(125) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex },
4495 { /*382, WINED3DTS_WORLDMATRIX(126) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex },
4496 { /*383, WINED3DTS_WORLDMATRIX(127) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex },
4497 { /*384, WINED3DTS_WORLDMATRIX(128) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex },
4498 { /*385, WINED3DTS_WORLDMATRIX(129) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex },
4499 { /*386, WINED3DTS_WORLDMATRIX(130) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex },
4500 { /*387, WINED3DTS_WORLDMATRIX(131) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex },
4501 { /*388, WINED3DTS_WORLDMATRIX(132) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex },
4502 { /*389, WINED3DTS_WORLDMATRIX(133) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex },
4503 { /*390, WINED3DTS_WORLDMATRIX(134) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex },
4504 { /*391, WINED3DTS_WORLDMATRIX(135) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex },
4505 { /*392, WINED3DTS_WORLDMATRIX(136) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex },
4506 { /*393, WINED3DTS_WORLDMATRIX(137) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex },
4507 { /*394, WINED3DTS_WORLDMATRIX(138) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex },
4508 { /*395, WINED3DTS_WORLDMATRIX(139) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex },
4509 { /*396, WINED3DTS_WORLDMATRIX(140) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex },
4510 { /*397, WINED3DTS_WORLDMATRIX(141) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex },
4511 { /*398, WINED3DTS_WORLDMATRIX(142) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex },
4512 { /*399, WINED3DTS_WORLDMATRIX(143) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex },
4513 { /*400, WINED3DTS_WORLDMATRIX(144) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex },
4514 { /*401, WINED3DTS_WORLDMATRIX(145) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex },
4515 { /*402, WINED3DTS_WORLDMATRIX(146) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex },
4516 { /*403, WINED3DTS_WORLDMATRIX(147) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex },
4517 { /*404, WINED3DTS_WORLDMATRIX(148) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex },
4518 { /*405, WINED3DTS_WORLDMATRIX(149) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex },
4519 { /*406, WINED3DTS_WORLDMATRIX(150) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex },
4520 { /*407, WINED3DTS_WORLDMATRIX(151) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex },
4521 { /*408, WINED3DTS_WORLDMATRIX(152) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex },
4522 { /*409, WINED3DTS_WORLDMATRIX(153) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex },
4523 { /*410, WINED3DTS_WORLDMATRIX(154) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex },
4524 { /*411, WINED3DTS_WORLDMATRIX(155) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex },
4525 { /*412, WINED3DTS_WORLDMATRIX(156) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex },
4526 { /*413, WINED3DTS_WORLDMATRIX(157) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex },
4527 { /*414, WINED3DTS_WORLDMATRIX(158) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex },
4528 { /*415, WINED3DTS_WORLDMATRIX(159) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex },
4529 { /*416, WINED3DTS_WORLDMATRIX(160) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex },
4530 { /*417, WINED3DTS_WORLDMATRIX(161) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex },
4531 { /*418, WINED3DTS_WORLDMATRIX(162) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex },
4532 { /*419, WINED3DTS_WORLDMATRIX(163) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex },
4533 { /*420, WINED3DTS_WORLDMATRIX(164) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex },
4534 { /*421, WINED3DTS_WORLDMATRIX(165) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex },
4535 { /*422, WINED3DTS_WORLDMATRIX(166) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex },
4536 { /*423, WINED3DTS_WORLDMATRIX(167) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex },
4537 { /*424, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex },
4538 { /*425, WINED3DTS_WORLDMATRIX(168) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex },
4539 { /*426, WINED3DTS_WORLDMATRIX(170) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex },
4540 { /*427, WINED3DTS_WORLDMATRIX(171) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex },
4541 { /*428, WINED3DTS_WORLDMATRIX(172) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex },
4542 { /*429, WINED3DTS_WORLDMATRIX(173) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex },
4543 { /*430, WINED3DTS_WORLDMATRIX(174) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex },
4544 { /*431, WINED3DTS_WORLDMATRIX(175) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex },
4545 { /*432, WINED3DTS_WORLDMATRIX(176) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex },
4546 { /*433, WINED3DTS_WORLDMATRIX(177) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex },
4547 { /*434, WINED3DTS_WORLDMATRIX(178) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex },
4548 { /*435, WINED3DTS_WORLDMATRIX(179) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex },
4549 { /*436, WINED3DTS_WORLDMATRIX(180) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex },
4550 { /*437, WINED3DTS_WORLDMATRIX(181) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex },
4551 { /*438, WINED3DTS_WORLDMATRIX(182) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex },
4552 { /*439, WINED3DTS_WORLDMATRIX(183) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex },
4553 { /*440, WINED3DTS_WORLDMATRIX(184) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex },
4554 { /*441, WINED3DTS_WORLDMATRIX(185) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex },
4555 { /*441, WINED3DTS_WORLDMATRIX(186) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex },
4556 { /*443, WINED3DTS_WORLDMATRIX(187) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex },
4557 { /*444, WINED3DTS_WORLDMATRIX(188) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex },
4558 { /*445, WINED3DTS_WORLDMATRIX(189) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex },
4559 { /*446, WINED3DTS_WORLDMATRIX(190) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex },
4560 { /*447, WINED3DTS_WORLDMATRIX(191) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex },
4561 { /*448, WINED3DTS_WORLDMATRIX(192) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex },
4562 { /*449, WINED3DTS_WORLDMATRIX(193) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex },
4563 { /*450, WINED3DTS_WORLDMATRIX(194) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex },
4564 { /*451, WINED3DTS_WORLDMATRIX(195) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex },
4565 { /*452, WINED3DTS_WORLDMATRIX(196) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex },
4566 { /*453, WINED3DTS_WORLDMATRIX(197) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex },
4567 { /*454, WINED3DTS_WORLDMATRIX(198) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex },
4568 { /*455, WINED3DTS_WORLDMATRIX(199) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex },
4569 { /*356, WINED3DTS_WORLDMATRIX(200) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex },
4570 { /*457, WINED3DTS_WORLDMATRIX(201) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex },
4571 { /*458, WINED3DTS_WORLDMATRIX(202) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex },
4572 { /*459, WINED3DTS_WORLDMATRIX(203) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex },
4573 { /*460, WINED3DTS_WORLDMATRIX(204) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex },
4574 { /*461, WINED3DTS_WORLDMATRIX(205) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex },
4575 { /*462, WINED3DTS_WORLDMATRIX(206) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex },
4576 { /*463, WINED3DTS_WORLDMATRIX(207) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex },
4577 { /*464, WINED3DTS_WORLDMATRIX(208) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex },
4578 { /*465, WINED3DTS_WORLDMATRIX(209) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex },
4579 { /*466, WINED3DTS_WORLDMATRIX(210) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex },
4580 { /*467, WINED3DTS_WORLDMATRIX(211) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex },
4581 { /*468, WINED3DTS_WORLDMATRIX(212) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex },
4582 { /*469, WINED3DTS_WORLDMATRIX(213) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex },
4583 { /*470, WINED3DTS_WORLDMATRIX(214) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex },
4584 { /*471, WINED3DTS_WORLDMATRIX(215) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex },
4585 { /*472, WINED3DTS_WORLDMATRIX(216) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex },
4586 { /*473, WINED3DTS_WORLDMATRIX(217) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex },
4587 { /*474, WINED3DTS_WORLDMATRIX(218) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex },
4588 { /*475, WINED3DTS_WORLDMATRIX(219) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex },
4589 { /*476, WINED3DTS_WORLDMATRIX(220) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex },
4590 { /*477, WINED3DTS_WORLDMATRIX(221) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex },
4591 { /*478, WINED3DTS_WORLDMATRIX(222) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex },
4592 { /*479, WINED3DTS_WORLDMATRIX(223) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex },
4593 { /*480, WINED3DTS_WORLDMATRIX(224) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex },
4594 { /*481, WINED3DTS_WORLDMATRIX(225) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex },
4595 { /*482, WINED3DTS_WORLDMATRIX(226) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex },
4596 { /*483, WINED3DTS_WORLDMATRIX(227) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex },
4597 { /*484, WINED3DTS_WORLDMATRIX(228) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex },
4598 { /*485, WINED3DTS_WORLDMATRIX(229) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex },
4599 { /*486, WINED3DTS_WORLDMATRIX(230) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex },
4600 { /*487, WINED3DTS_WORLDMATRIX(231) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex },
4601 { /*488, WINED3DTS_WORLDMATRIX(232) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex },
4602 { /*489, WINED3DTS_WORLDMATRIX(233) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex },
4603 { /*490, WINED3DTS_WORLDMATRIX(234) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex },
4604 { /*491, WINED3DTS_WORLDMATRIX(235) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex },
4605 { /*492, WINED3DTS_WORLDMATRIX(236) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex },
4606 { /*493, WINED3DTS_WORLDMATRIX(237) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex },
4607 { /*494, WINED3DTS_WORLDMATRIX(238) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex },
4608 { /*495, WINED3DTS_WORLDMATRIX(239) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex },
4609 { /*496, WINED3DTS_WORLDMATRIX(240) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex },
4610 { /*497, WINED3DTS_WORLDMATRIX(241) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex },
4611 { /*498, WINED3DTS_WORLDMATRIX(242) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex },
4612 { /*499, WINED3DTS_WORLDMATRIX(243) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex },
4613 { /*500, WINED3DTS_WORLDMATRIX(244) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex },
4614 { /*501, WINED3DTS_WORLDMATRIX(245) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex },
4615 { /*502, WINED3DTS_WORLDMATRIX(246) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex },
4616 { /*503, WINED3DTS_WORLDMATRIX(247) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex },
4617 { /*504, WINED3DTS_WORLDMATRIX(248) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex },
4618 { /*505, WINED3DTS_WORLDMATRIX(249) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex },
4619 { /*506, WINED3DTS_WORLDMATRIX(250) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex },
4620 { /*507, WINED3DTS_WORLDMATRIX(251) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex },
4621 { /*508, WINED3DTS_WORLDMATRIX(252) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex },
4622 { /*509, WINED3DTS_WORLDMATRIX(253) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex },
4623 { /*510, WINED3DTS_WORLDMATRIX(254) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex },
4624 { /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
4625 /* Various Vertex states follow */
4626 { /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
4627 { /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
4628 { /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
4629 { /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
4630 { /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
4631 { /* , STATE_VERTEXSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4632 { /* , STATE_PIXELSHADERCONSTANT */ STATE_VERTEXSHADERCONSTANT, shaderconstant },
4634 { /* , STATE_ACTIVELIGHT(0) */ STATE_ACTIVELIGHT(0), light },
4635 { /* , STATE_ACTIVELIGHT(1) */ STATE_ACTIVELIGHT(1), light },
4636 { /* , STATE_ACTIVELIGHT(2) */ STATE_ACTIVELIGHT(2), light },
4637 { /* , STATE_ACTIVELIGHT(3) */ STATE_ACTIVELIGHT(3), light },
4638 { /* , STATE_ACTIVELIGHT(4) */ STATE_ACTIVELIGHT(4), light },
4639 { /* , STATE_ACTIVELIGHT(5) */ STATE_ACTIVELIGHT(5), light },
4640 { /* , STATE_ACTIVELIGHT(6) */ STATE_ACTIVELIGHT(6), light },
4641 { /* , STATE_ACTIVELIGHT(7) */ STATE_ACTIVELIGHT(7), light },
4643 { /* Scissor rect */ STATE_SCISSORRECT, scissorrect },
4645 { /* STATE_CLIPPLANE(0) */ STATE_CLIPPLANE(0), clipplane },
4646 { /* STATE_CLIPPLANE(1) */ STATE_CLIPPLANE(1), clipplane },
4647 { /* STATE_CLIPPLANE(2) */ STATE_CLIPPLANE(2), clipplane },
4648 { /* STATE_CLIPPLANE(3) */ STATE_CLIPPLANE(3), clipplane },
4649 { /* STATE_CLIPPLANE(4) */ STATE_CLIPPLANE(4), clipplane },
4650 { /* STATE_CLIPPLANE(5) */ STATE_CLIPPLANE(5), clipplane },
4651 { /* STATE_CLIPPLANE(6) */ STATE_CLIPPLANE(6), clipplane },
4652 { /* STATE_CLIPPLANE(7) */ STATE_CLIPPLANE(7), clipplane },
4653 { /* STATE_CLIPPLANE(8) */ STATE_CLIPPLANE(8), clipplane },
4654 { /* STATE_CLIPPLANE(9) */ STATE_CLIPPLANE(9), clipplane },
4655 { /* STATE_CLIPPLANE(10) */ STATE_CLIPPLANE(10), clipplane },
4656 { /* STATE_CLIPPLANE(11) */ STATE_CLIPPLANE(11), clipplane },
4657 { /* STATE_CLIPPLANE(12) */ STATE_CLIPPLANE(12), clipplane },
4658 { /* STATE_CLIPPLANE(13) */ STATE_CLIPPLANE(13), clipplane },
4659 { /* STATE_CLIPPLANE(14) */ STATE_CLIPPLANE(14), clipplane },
4660 { /* STATE_CLIPPLANE(15) */ STATE_CLIPPLANE(15), clipplane },
4661 { /* STATE_CLIPPLANE(16) */ STATE_CLIPPLANE(16), clipplane },
4662 { /* STATE_CLIPPLANE(17) */ STATE_CLIPPLANE(17), clipplane },
4663 { /* STATE_CLIPPLANE(18) */ STATE_CLIPPLANE(18), clipplane },
4664 { /* STATE_CLIPPLANE(19) */ STATE_CLIPPLANE(19), clipplane },
4665 { /* STATE_CLIPPLANE(20) */ STATE_CLIPPLANE(20), clipplane },
4666 { /* STATE_CLIPPLANE(21) */ STATE_CLIPPLANE(21), clipplane },
4667 { /* STATE_CLIPPLANE(22) */ STATE_CLIPPLANE(22), clipplane },
4668 { /* STATE_CLIPPLANE(23) */ STATE_CLIPPLANE(23), clipplane },
4669 { /* STATE_CLIPPLANE(24) */ STATE_CLIPPLANE(24), clipplane },
4670 { /* STATE_CLIPPLANE(25) */ STATE_CLIPPLANE(25), clipplane },
4671 { /* STATE_CLIPPLANE(26) */ STATE_CLIPPLANE(26), clipplane },
4672 { /* STATE_CLIPPLANE(27) */ STATE_CLIPPLANE(27), clipplane },
4673 { /* STATE_CLIPPLANE(28) */ STATE_CLIPPLANE(28), clipplane },
4674 { /* STATE_CLIPPLANE(29) */ STATE_CLIPPLANE(29), clipplane },
4675 { /* STATE_CLIPPLANE(30) */ STATE_CLIPPLANE(30), clipplane },
4676 { /* STATE_CLIPPLANE(31) */ STATE_CLIPPLANE(31), clipplane },
4678 { /* STATE_MATERIAL */ STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable},