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-2008 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_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
45 if(STATE_IS_RENDER(state)) {
46 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
49 /* Shouldn't have an unknown type here */
50 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56 * list without causing confusing terminal output. Deliberately no special debug name here
57 * because its undefined.
59 WARN("undefined state %d\n", state);
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
66 case WINED3DFILL_POINT:
67 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
70 case WINED3DFILL_WIREFRAME:
71 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
74 case WINED3DFILL_SOLID:
75 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
96 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
97 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
98 stateblock->wineD3DDevice->strided_streams.u.s.position_transformed) ? TRUE : FALSE;
100 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
101 glEnable(GL_LIGHTING);
102 checkGLcall("glEnable GL_LIGHTING");
104 glDisable(GL_LIGHTING);
105 checkGLcall("glDisable GL_LIGHTING");
109 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
110 /* No z test without depth stencil buffers */
111 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
112 TRACE("No Z buffer - disabling depth test\n");
113 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
114 checkGLcall("glDisable GL_DEPTH_TEST");
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
138 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
141 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
142 case WINED3DCULL_NONE:
143 glDisable(GL_CULL_FACE);
144 checkGLcall("glDisable GL_CULL_FACE");
147 glEnable(GL_CULL_FACE);
148 checkGLcall("glEnable GL_CULL_FACE");
149 glCullFace(GL_FRONT);
150 checkGLcall("glCullFace(GL_FRONT)");
152 case WINED3DCULL_CCW:
153 glEnable(GL_CULL_FACE);
154 checkGLcall("glEnable GL_CULL_FACE");
156 checkGLcall("glCullFace(GL_BACK)");
159 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
163 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
164 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
165 case WINED3DSHADE_FLAT:
166 glShadeModel(GL_FLAT);
167 checkGLcall("glShadeModel(GL_FLAT)");
169 case WINED3DSHADE_GOURAUD:
170 glShadeModel(GL_SMOOTH);
171 checkGLcall("glShadeModel(GL_SMOOTH)");
173 case WINED3DSHADE_PHONG:
174 FIXME("WINED3DSHADE_PHONG isn't supported\n");
177 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
181 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
182 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
184 checkGLcall("glEnable GL_DITHER");
186 glDisable(GL_DITHER);
187 checkGLcall("glDisable GL_DITHER");
191 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
192 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
193 * this has to be merged with ZENABLE and ZFUNC
195 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
197 checkGLcall("glDepthMask(1)");
200 checkGLcall("glDepthMask(0)");
204 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
205 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
208 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
209 static BOOL once = FALSE;
210 /* There are a few issues with this: First, our inability to
211 * select a proper Z depth, most of the time we're stuck with
212 * D24S8, even if the app selects D32 or D16. There seem to be
213 * some other precision problems which have to be debugged to
214 * make NOTEQUAL and EQUAL work properly
218 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
223 checkGLcall("glDepthFunc");
227 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
229 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
231 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
232 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
233 checkGLcall("glLightModel for MODEL_AMBIENT");
236 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
237 int srcBlend = GL_ZERO;
238 int dstBlend = GL_ZERO;
239 const StaticPixelFormatDesc *rtFormat;
240 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
242 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
243 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
244 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
245 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
246 const GlPixelFormatDesc *glDesc;
247 getFormatDescEntry(target->resource.format, &GLINFO_LOCATION, &glDesc);
249 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
250 * The d3d9 visual test confirms the behavior. */
251 if(!(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) {
253 checkGLcall("glDisable GL_BLEND");
257 checkGLcall("glEnable GL_BLEND");
261 checkGLcall("glDisable GL_BLEND");
262 /* Nothing more to do - get out */
266 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
267 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
268 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
269 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
270 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
271 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
272 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
273 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
274 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
276 /* To compensate the lack of format switching with backbuffer offscreen rendering,
277 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
278 * if the render target doesn't support alpha blending. A nonexistent alpha channel
279 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
281 case WINED3DBLEND_DESTALPHA :
282 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
283 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
285 case WINED3DBLEND_INVDESTALPHA :
286 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
287 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
290 case WINED3DBLEND_SRCALPHASAT :
291 dstBlend = GL_SRC_ALPHA_SATURATE;
292 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
295 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
296 * values which are still valid up to d3d9. They should not occur as dest blend values
298 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
299 srcBlend = GL_SRC_ALPHA;
300 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
303 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
304 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
305 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
308 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
309 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
311 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
314 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
315 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
316 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
317 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
318 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
319 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
320 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
321 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
322 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
323 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
325 case WINED3DBLEND_DESTALPHA :
326 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
327 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
329 case WINED3DBLEND_INVDESTALPHA :
330 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
331 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
334 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
335 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
338 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
339 dstBlend = GL_SRC_ALPHA;
342 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
343 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
345 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
348 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
349 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
350 glEnable(GL_LINE_SMOOTH);
351 checkGLcall("glEnable(GL_LINE_SMOOTH)");
352 if(srcBlend != GL_SRC_ALPHA) {
353 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
355 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
356 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
359 glDisable(GL_LINE_SMOOTH);
360 checkGLcall("glDisable(GL_LINE_SMOOTH)");
363 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
364 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
365 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
368 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
369 int srcBlendAlpha = GL_ZERO;
370 int dstBlendAlpha = GL_ZERO;
372 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
373 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
374 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
378 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
379 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
380 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
381 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
382 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
383 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
384 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
385 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
386 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
387 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
388 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
389 case WINED3DBLEND_SRCALPHASAT :
390 dstBlend = GL_SRC_ALPHA_SATURATE;
391 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
393 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
394 * values which are still valid up to d3d9. They should not occur as dest blend values
396 case WINED3DBLEND_BOTHSRCALPHA :
397 dstBlendAlpha = GL_SRC_ALPHA;
398 srcBlendAlpha = GL_SRC_ALPHA;
399 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
401 case WINED3DBLEND_BOTHINVSRCALPHA :
402 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
403 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
404 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
406 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
407 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
409 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
412 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
413 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
414 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
415 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
416 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
417 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
418 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
419 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
420 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
421 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
422 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
423 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
424 case WINED3DBLEND_BOTHSRCALPHA :
425 srcBlendAlpha = GL_SRC_ALPHA;
426 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
428 case WINED3DBLEND_BOTHINVSRCALPHA :
429 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
430 dstBlendAlpha = GL_SRC_ALPHA;
432 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
433 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
435 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
438 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
439 checkGLcall("glBlendFuncSeparateEXT");
441 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
442 glBlendFunc(srcBlend, dstBlend);
443 checkGLcall("glBlendFunc");
446 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
447 so it may need updating */
448 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
449 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
450 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
454 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
455 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
458 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
461 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
462 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
463 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
464 checkGLcall("glBlendColor");
467 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
470 BOOL enable_ckey = FALSE;
472 IWineD3DSurfaceImpl *surf;
474 /* Find out if the texture on the first stage has a ckey set
475 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
476 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
477 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
478 * in case it finds some texture+colorkeyenable combination which needs extra care.
480 if(stateblock->textures[0] && (
481 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
482 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
483 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
485 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
486 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
487 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
488 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
489 * surface has alpha bits
491 if(fmt->alphaMask == 0x00000000) {
497 if(enable_ckey || context->last_was_ckey) {
498 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
499 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
501 context->last_was_ckey = enable_ckey;
503 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
504 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
505 glEnable(GL_ALPHA_TEST);
506 checkGLcall("glEnable GL_ALPHA_TEST");
508 glDisable(GL_ALPHA_TEST);
509 checkGLcall("glDisable GL_ALPHA_TEST");
510 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
516 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
517 glParm = GL_NOTEQUAL;
520 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
521 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
524 glAlphaFunc(glParm, ref);
525 checkGLcall("glAlphaFunc");
529 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
530 DWORD enable = 0xFFFFFFFF;
531 DWORD disable = 0x00000000;
533 if (use_vs(stateblock->wineD3DDevice)) {
534 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
535 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
536 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
537 * of that - don't do anything here and keep them disabled
539 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
540 static BOOL warned = FALSE;
542 FIXME("Clipping not supported with vertex shaders\n");
549 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
550 * of already set values
553 /* If enabling / disabling all
554 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
556 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
557 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
558 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
559 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
560 glDisable(GL_DEPTH_CLAMP_NV);
561 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
564 disable = 0xffffffff;
566 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
567 glEnable(GL_DEPTH_CLAMP_NV);
568 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
572 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
573 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
574 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
575 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
576 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
577 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
579 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
580 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
581 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
582 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
583 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
584 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
586 /** update clipping status */
588 stateblock->clip_status.ClipUnion = 0;
589 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
591 stateblock->clip_status.ClipUnion = 0;
592 stateblock->clip_status.ClipIntersection = 0;
596 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
597 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
600 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
601 int blendEquation = GL_FUNC_ADD;
602 int blendEquationAlpha = GL_FUNC_ADD;
604 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
605 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
606 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
610 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
611 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
612 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
613 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
614 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
615 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
617 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
620 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
621 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
622 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
623 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
624 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
625 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
627 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
630 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
631 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
632 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
633 checkGLcall("glBlendEquationSeparateEXT");
635 TRACE("glBlendEquation(%x)\n", blendEquation);
636 GL_EXTCALL(glBlendEquationEXT(blendEquation));
637 checkGLcall("glBlendEquation");
642 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
643 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
644 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
645 * specular color. This is wrong:
646 * Separate specular color means the specular colour is maintained separately, whereas
647 * single color means it is merged in. However in both cases they are being used to
649 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
650 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
654 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
655 * Instead, we need to setup the FinalCombiner properly.
657 * The default setup for the FinalCombiner is:
659 * <variable> <input> <mapping> <usage>
660 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
661 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
662 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
663 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
664 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
665 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
668 * That's pretty much fine as it is, except for variable B, which needs to take
669 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
670 * whether WINED3DRS_SPECULARENABLE is enabled or not.
673 TRACE("Setting specular enable state and materials\n");
674 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
675 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
676 checkGLcall("glMaterialfv");
678 if(stateblock->material.Power > GL_LIMITS(shininess)) {
679 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
680 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
681 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
682 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
683 * them, it should be safe to do so without major visual distortions.
685 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
686 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
688 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
690 checkGLcall("glMaterialf(GL_SHININESS)");
692 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
693 glEnable(GL_COLOR_SUM_EXT);
695 TRACE("Specular colors cannot be enabled in this version of opengl\n");
697 checkGLcall("glEnable(GL_COLOR_SUM)");
699 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
700 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
701 checkGLcall("glFinalCombinerInputNV()");
704 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
706 /* for the case of enabled lighting: */
707 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
708 checkGLcall("glMaterialfv");
710 /* for the case of disabled lighting: */
711 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
712 glDisable(GL_COLOR_SUM_EXT);
714 TRACE("Specular colors cannot be disabled in this version of opengl\n");
716 checkGLcall("glDisable(GL_COLOR_SUM)");
718 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
719 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
720 checkGLcall("glFinalCombinerInputNV()");
724 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
725 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
726 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
727 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
728 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
729 stateblock->material.Specular.b, stateblock->material.Specular.a);
730 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
731 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
733 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
734 checkGLcall("glMaterialfv(GL_AMBIENT)");
735 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
736 checkGLcall("glMaterialfv(GL_DIFFUSE)");
737 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
738 checkGLcall("glMaterialfv(GL_EMISSION)");
741 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
744 /* Note the texture color applies to all textures whereas
745 * GL_TEXTURE_ENV_COLOR applies to active only
748 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
750 /* And now the default texture color as well */
751 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
752 /* Note the WINED3DRS value applies to all textures, but GL has one
753 * per texture, so apply it now ready to be used!
755 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
756 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
757 checkGLcall("glActiveTextureARB");
759 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
762 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
763 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
768 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
769 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
770 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
771 GL_EXTCALL(glActiveStencilFaceEXT(face));
772 checkGLcall("glActiveStencilFaceEXT(...)");
773 glStencilFunc(func, ref, mask);
774 checkGLcall("glStencilFunc(...)");
775 glStencilOp(stencilFail, depthFail, stencilPass);
776 checkGLcall("glStencilOp(...)");
780 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
781 DWORD onesided_enable = FALSE;
782 DWORD twosided_enable = FALSE;
783 GLint func = GL_ALWAYS;
784 GLint func_ccw = GL_ALWAYS;
787 GLint stencilFail = GL_KEEP;
788 GLint depthFail = GL_KEEP;
789 GLint stencilPass = GL_KEEP;
790 GLint stencilFail_ccw = GL_KEEP;
791 GLint depthFail_ccw = GL_KEEP;
792 GLint stencilPass_ccw = GL_KEEP;
794 /* No stencil test without a stencil buffer */
795 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
796 glDisable(GL_STENCIL_TEST);
797 checkGLcall("glDisable GL_STENCIL_TEST");
801 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
802 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
803 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
805 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
806 func_ccw = GL_ALWAYS;
807 ref = stateblock->renderState[WINED3DRS_STENCILREF];
808 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
809 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
810 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
811 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
812 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
813 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
814 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
816 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
817 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
818 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
819 onesided_enable, twosided_enable, ref, mask,
820 func, stencilFail, depthFail, stencilPass,
821 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
823 if (twosided_enable && onesided_enable) {
824 glEnable(GL_STENCIL_TEST);
825 checkGLcall("glEnable GL_STENCIL_TEST");
827 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
828 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
829 * which has an effect on the code below too. If we apply the front face
830 * afterwards, we are sure that the active stencil face is set to front,
831 * and other stencil functions which do not use two sided stencil do not have
834 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
835 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
836 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
837 stencilFail, depthFail, stencilPass);
838 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
839 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
840 checkGLcall("glStencilFuncSeparateATI(...)");
841 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
842 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
843 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
844 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
846 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
848 } else if(onesided_enable) {
849 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
850 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
851 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
854 /* This code disables the ATI extension as well, since the standard stencil functions are equal
855 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
857 glEnable(GL_STENCIL_TEST);
858 checkGLcall("glEnable GL_STENCIL_TEST");
859 glStencilFunc(func, ref, mask);
860 checkGLcall("glStencilFunc(...)");
861 glStencilOp(stencilFail, depthFail, stencilPass);
862 checkGLcall("glStencilOp(...)");
864 glDisable(GL_STENCIL_TEST);
865 checkGLcall("glDisable GL_STENCIL_TEST");
869 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
872 if(stateblock->wineD3DDevice->stencilBufferTarget) {
873 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
878 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
879 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
881 checkGLcall("glStencilMask");
882 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
883 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
887 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
890 if(stateblock->wineD3DDevice->stencilBufferTarget) {
891 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
897 checkGLcall("glStencilMask");
900 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
901 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
902 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
903 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
904 float fogstart, fogend;
912 /* No fog? Disable it, and we're done :-) */
914 checkGLcall("glDisable GL_FOG");
915 if( use_ps(stateblock->wineD3DDevice)
916 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
917 /* disable fog in the pixel shader
918 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
919 * -1/(e-s) and e/(e-s) respectively.
921 glFogf(GL_FOG_START, 0.0f);
922 checkGLcall("glFogf(GL_FOG_START, fogstart)");
923 glFogf(GL_FOG_END, 1.0f);
924 checkGLcall("glFogf(GL_FOG_END, fogend)");
929 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
930 fogstart = tmpvalue.f;
931 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
936 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
937 * It can use the Z value of the vertex, or the alpha component of the specular color.
938 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
939 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
940 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
942 * FOGTABLEMODE != NONE:
943 * The Z value is used, with the equation specified, no matter what vertex type.
945 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
946 * Per vertex fog is calculated using the specified fog equation and the parameters
948 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
949 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
950 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
953 * Rules for vertex fog with shaders:
955 * When mixing fixed function functionality with the programmable pipeline, D3D expects
956 * the fog computation to happen during transformation while openGL expects it to happen
957 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
958 * the pixel shader while openGL always expects the pixel shader to handle the blending.
959 * To solve this problem, WineD3D does:
960 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
962 * and 2) disables the fog computation (in either the fixed function or programmable
963 * rasterizer) if using a vertex program.
966 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
971 if( !use_vs(stateblock->wineD3DDevice)
972 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
973 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
977 if (use_vs(stateblock->wineD3DDevice)
978 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
979 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
980 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
984 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
985 glFogi(GL_FOG_MODE, GL_LINEAR);
986 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
991 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
992 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
993 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
994 context->fog_coord = FALSE;
996 context->last_was_foggy_shader = TRUE;
998 else if( use_ps(stateblock->wineD3DDevice) ) {
999 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1000 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
1002 WINED3DFOGMODE mode;
1003 context->last_was_foggy_shader = FALSE;
1005 /* If both fogmodes are set use the table fog mode */
1006 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1007 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
1009 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1012 case WINED3DFOG_EXP:
1013 case WINED3DFOG_EXP2:
1014 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1019 case WINED3DFOG_LINEAR:
1020 fogstart = -1.0f/(fogend-fogstart);
1021 fogend *= -fogstart;
1024 case WINED3DFOG_NONE:
1025 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1029 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1032 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1033 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1034 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1035 context->fog_coord = FALSE;
1038 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1039 * the system will apply only pixel(=table) fog effects."
1041 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1042 glHint(GL_FOG_HINT, GL_FASTEST);
1043 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1044 context->last_was_foggy_shader = FALSE;
1046 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1047 /* If processed vertices are used, fall through to the NONE case */
1048 case WINED3DFOG_EXP: {
1049 if(!context->last_was_rhw) {
1050 glFogi(GL_FOG_MODE, GL_EXP);
1051 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1052 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1053 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1054 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1055 context->fog_coord = FALSE;
1060 case WINED3DFOG_EXP2: {
1061 if(!context->last_was_rhw) {
1062 glFogi(GL_FOG_MODE, GL_EXP2);
1063 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1064 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1065 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1066 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1067 context->fog_coord = FALSE;
1072 case WINED3DFOG_LINEAR: {
1073 if(!context->last_was_rhw) {
1074 glFogi(GL_FOG_MODE, GL_LINEAR);
1075 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1076 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1077 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1078 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1079 context->fog_coord = FALSE;
1084 case WINED3DFOG_NONE: {
1085 /* Both are none? According to msdn the alpha channel of the specular
1086 * color contains a fog factor. Set it in drawStridedSlow.
1087 * Same happens with Vertexfog on transformed vertices
1089 if(GL_SUPPORT(EXT_FOG_COORD)) {
1090 if(context->fog_coord == FALSE) {
1091 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1092 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1093 context->fog_coord = TRUE;
1095 glFogi(GL_FOG_MODE, GL_LINEAR);
1096 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1100 /* Disable GL fog, handle this in software in drawStridedSlow */
1105 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1108 glHint(GL_FOG_HINT, GL_NICEST);
1109 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1110 context->last_was_foggy_shader = FALSE;
1112 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1113 case WINED3DFOG_EXP:
1114 glFogi(GL_FOG_MODE, GL_EXP);
1115 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1116 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1117 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1118 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1119 context->fog_coord = FALSE;
1123 case WINED3DFOG_EXP2:
1124 glFogi(GL_FOG_MODE, GL_EXP2);
1125 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1126 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1127 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1128 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1129 context->fog_coord = FALSE;
1133 case WINED3DFOG_LINEAR:
1134 glFogi(GL_FOG_MODE, GL_LINEAR);
1135 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1136 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1137 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1138 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1139 context->fog_coord = FALSE;
1143 case WINED3DFOG_NONE: /* Won't happen */
1145 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1151 checkGLcall("glEnable GL_FOG");
1153 if(fogstart != fogend)
1155 glFogfv(GL_FOG_START, &fogstart);
1156 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1157 TRACE("Fog Start == %f\n", fogstart);
1159 glFogfv(GL_FOG_END, &fogend);
1160 checkGLcall("glFogf(GL_FOG_END, fogend)");
1161 TRACE("Fog End == %f\n", fogend);
1165 glFogf(GL_FOG_START, -1.0 / 0.0);
1166 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1167 TRACE("Fog Start == %f\n", fogstart);
1169 glFogf(GL_FOG_END, 0.0);
1170 checkGLcall("glFogf(GL_FOG_END, fogend)");
1171 TRACE("Fog End == %f\n", fogend);
1175 checkGLcall("glDisable GL_FOG");
1176 if( use_ps(stateblock->wineD3DDevice) ) {
1177 /* disable fog in the pixel shader
1178 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1179 * -1/(e-s) and e/(e-s) respectively.
1181 glFogf(GL_FOG_START, 0.0f);
1182 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1183 glFogf(GL_FOG_END, 1.0f);
1184 checkGLcall("glFogf(GL_FOG_END, fogend)");
1189 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1190 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1191 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1195 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1196 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1197 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1198 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1200 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1201 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1205 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1207 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1208 glFogfv(GL_FOG_COLOR, &col[0]);
1209 checkGLcall("glFog GL_FOG_COLOR");
1212 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1217 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1218 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1219 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1222 /* TODO: Merge with primitive type + init_materials()!! */
1223 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1224 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1226 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1227 BOOL isDiffuseSupplied;
1229 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1230 * The vertex declaration will call this function if the fixed function pipeline is used.
1233 if(isStateDirty(context, STATE_VDECL)) {
1237 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1239 context->num_untracked_materials = 0;
1240 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1241 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1242 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1243 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1244 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1245 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1247 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1248 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1249 Parm = GL_AMBIENT_AND_DIFFUSE;
1253 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1254 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1255 context->num_untracked_materials++;
1257 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1258 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1259 context->num_untracked_materials++;
1261 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1263 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1264 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1265 context->num_untracked_materials++;
1267 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1268 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1269 context->num_untracked_materials++;
1271 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1273 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1274 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1275 context->num_untracked_materials++;
1277 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1282 /* Nothing changed, return. */
1283 if (Parm == context->tracking_parm) return;
1286 glDisable(GL_COLOR_MATERIAL);
1287 checkGLcall("glDisable GL_COLOR_MATERIAL");
1289 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1290 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1291 glEnable(GL_COLOR_MATERIAL);
1292 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1295 /* Apparently calls to glMaterialfv are ignored for properties we're
1296 * tracking with glColorMaterial, so apply those here. */
1297 switch (context->tracking_parm) {
1298 case GL_AMBIENT_AND_DIFFUSE:
1299 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1300 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1301 checkGLcall("glMaterialfv");
1305 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1306 checkGLcall("glMaterialfv");
1310 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1311 checkGLcall("glMaterialfv");
1315 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1316 checkGLcall("glMaterialfv");
1320 /* Only change material color if specular is enabled, otherwise it is set to black */
1321 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1322 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1323 checkGLcall("glMaterialfv");
1325 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1326 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1327 checkGLcall("glMaterialfv");
1332 context->tracking_parm = Parm;
1335 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1338 WINED3DLINEPATTERN lp;
1340 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1342 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1344 if (tmppattern.lp.wRepeatFactor) {
1345 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1346 checkGLcall("glLineStipple(repeat, linepattern)");
1347 glEnable(GL_LINE_STIPPLE);
1348 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1350 glDisable(GL_LINE_STIPPLE);
1351 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1355 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1361 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1362 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1363 TRACE("ZBias value %f\n", tmpvalue.f);
1364 glPolygonOffset(0, -tmpvalue.f);
1365 checkGLcall("glPolygonOffset(0, -Value)");
1366 glEnable(GL_POLYGON_OFFSET_FILL);
1367 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1368 glEnable(GL_POLYGON_OFFSET_LINE);
1369 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1370 glEnable(GL_POLYGON_OFFSET_POINT);
1371 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1373 glDisable(GL_POLYGON_OFFSET_FILL);
1374 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1375 glDisable(GL_POLYGON_OFFSET_LINE);
1376 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1377 glDisable(GL_POLYGON_OFFSET_POINT);
1378 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1383 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1384 if(isStateDirty(context, STATE_VDECL)) {
1387 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1388 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1389 * by zero and is not properly defined in opengl, so avoid it
1391 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1392 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1393 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1394 glEnable(GL_NORMALIZE);
1395 checkGLcall("glEnable(GL_NORMALIZE);");
1397 glDisable(GL_NORMALIZE);
1398 checkGLcall("glDisable(GL_NORMALIZE);");
1402 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1408 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1409 if(tmpvalue.f != 1.0) {
1410 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1414 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1420 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1421 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1422 checkGLcall("glPointParameterfEXT(...)");
1425 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1431 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1432 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1433 checkGLcall("glPointParameterfARB(...)");
1436 static void state_psizemax_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1442 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1443 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1444 checkGLcall("glPointParameterfARB(...)");
1447 static void state_psizemax_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1453 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1454 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1455 checkGLcall("glPointParameterfEXT(...)");
1458 static void state_psizemax_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1464 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1465 if(tmpvalue.f != 64.0) {
1466 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1470 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1471 /* TODO: Group this with the viewport */
1473 * POINTSCALEENABLE controls how point size value is treated. If set to
1474 * true, the point size is scaled with respect to height of viewport.
1475 * When set to false point size is in pixels.
1478 /* Default values */
1479 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1483 } pointSize, A, B, C;
1485 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1486 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1487 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1488 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1490 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1491 GLfloat scaleFactor;
1492 float h = stateblock->viewport.Height;
1494 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1496 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1497 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1498 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1499 * are less than 1.0f. scale_factor = 1.0f / point_size.
1501 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1502 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1503 * is 1.0, but then accepts points below that and draws too small points
1505 pointSize.f = GL_LIMITS(pointsizemin);
1506 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1507 /* gl already scales the input to glPointSize,
1508 * d3d scales the result after the point size scale.
1509 * If the point size is bigger than the max size, use the
1510 * scaling to scale it bigger, and set the gl point size to max
1512 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1513 TRACE("scale: %f\n", scaleFactor);
1514 pointSize.f = GL_LIMITS(pointsize);
1518 scaleFactor = pow(h * scaleFactor, 2);
1520 att[0] = A.f / scaleFactor;
1521 att[1] = B.f / scaleFactor;
1522 att[2] = C.f / scaleFactor;
1525 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1526 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1527 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1529 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1530 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1531 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1532 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1533 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1536 glPointSize(pointSize.f);
1537 checkGLcall("glPointSize(...);");
1540 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1541 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1543 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1544 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1545 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1546 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1547 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1548 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1549 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1550 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1551 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1552 checkGLcall("glColorMask(...)");
1554 /* depends on WINED3DRS_COLORWRITEENABLE. */
1555 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1556 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1557 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1558 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1559 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1560 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1561 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1565 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1566 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1567 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1568 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1570 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1571 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1575 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1576 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1577 TRACE("Last Pixel Drawing Enabled\n");
1579 static BOOL first = TRUE;
1581 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1584 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1589 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1590 /* TODO: NV_POINT_SPRITE */
1591 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1592 TRACE("Point sprites not supported\n");
1596 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1597 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1598 glEnable(GL_POINT_SPRITE_ARB);
1599 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1601 glDisable(GL_POINT_SPRITE_ARB);
1602 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1606 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1608 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1609 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1610 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1611 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1613 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1616 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1617 stateblock->renderState[WINED3DRS_WRAP1] ||
1618 stateblock->renderState[WINED3DRS_WRAP2] ||
1619 stateblock->renderState[WINED3DRS_WRAP3] ||
1620 stateblock->renderState[WINED3DRS_WRAP4] ||
1621 stateblock->renderState[WINED3DRS_WRAP5] ||
1622 stateblock->renderState[WINED3DRS_WRAP6] ||
1623 stateblock->renderState[WINED3DRS_WRAP7] ||
1624 stateblock->renderState[WINED3DRS_WRAP8] ||
1625 stateblock->renderState[WINED3DRS_WRAP9] ||
1626 stateblock->renderState[WINED3DRS_WRAP10] ||
1627 stateblock->renderState[WINED3DRS_WRAP11] ||
1628 stateblock->renderState[WINED3DRS_WRAP12] ||
1629 stateblock->renderState[WINED3DRS_WRAP13] ||
1630 stateblock->renderState[WINED3DRS_WRAP14] ||
1631 stateblock->renderState[WINED3DRS_WRAP15] ) {
1632 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1636 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1637 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1638 WARN("Multisample antialiasing not supported by gl\n");
1642 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1643 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1644 glEnable(GL_MULTISAMPLE_ARB);
1645 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1647 glDisable(GL_MULTISAMPLE_ARB);
1648 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1652 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1653 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1654 glEnable(GL_SCISSOR_TEST);
1655 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1657 glDisable(GL_SCISSOR_TEST);
1658 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1662 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1668 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1669 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1670 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1671 glEnable(GL_POLYGON_OFFSET_FILL);
1672 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1673 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1674 checkGLcall("glPolygonOffset(...)");
1676 glDisable(GL_POLYGON_OFFSET_FILL);
1677 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1681 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1682 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1683 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1684 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1686 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1687 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1691 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1693 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1694 FIXME(" Stippled Alpha not supported yet.\n");
1697 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1699 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1700 FIXME(" Antialias not supported yet.\n");
1703 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1705 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1706 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1709 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1711 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1712 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1715 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1723 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1725 static BOOL displayed = FALSE;
1727 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1729 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1735 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1737 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1738 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1741 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1743 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1744 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1747 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1749 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1750 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1753 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1754 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1755 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1759 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1760 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1761 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1765 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1766 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1767 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1771 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1772 if(stateblock->renderState[WINED3DRS_ROP2]) {
1773 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1777 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1778 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1779 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1783 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1784 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1785 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1789 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1790 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1791 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1795 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1796 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1797 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1801 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1802 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1803 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1807 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1808 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1809 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1813 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1814 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1815 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1819 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1820 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1821 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1825 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1826 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1827 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1831 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1832 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1833 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1837 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1838 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1839 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1843 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1844 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1845 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1846 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1848 TRACE("Setting color op for stage %d\n", stage);
1850 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1851 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1852 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1856 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1858 if (mapped_stage != -1) {
1859 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1860 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1861 FIXME("Attempt to enable unsupported stage!\n");
1864 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1865 checkGLcall("glActiveTextureARB");
1866 } else if (stage > 0) {
1867 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1872 if(stage >= stateblock->lowest_disabled_stage) {
1873 TRACE("Stage disabled\n");
1874 if (mapped_stage != -1) {
1875 /* Disable everything here */
1876 glDisable(GL_TEXTURE_2D);
1877 checkGLcall("glDisable(GL_TEXTURE_2D)");
1878 glDisable(GL_TEXTURE_3D);
1879 checkGLcall("glDisable(GL_TEXTURE_3D)");
1880 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1881 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1882 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1884 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1885 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1886 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1893 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1894 * if the sampler for this stage is dirty
1896 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1897 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
1900 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1901 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1902 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1903 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1904 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1907 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1908 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1909 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1910 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1911 DWORD op, arg1, arg2, arg0;
1913 TRACE("Setting alpha op for stage %d\n", stage);
1914 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
1915 if (mapped_stage != -1) {
1916 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1917 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1918 FIXME("Attempt to enable unsupported stage!\n");
1921 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1922 checkGLcall("glActiveTextureARB");
1923 } else if (stage > 0) {
1924 /* We can't do anything here */
1925 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1930 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1931 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1932 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1933 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1935 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1936 stateblock->textures[0] &&
1937 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
1938 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1940 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1941 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1943 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1944 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1945 * cannot remove the texture's alpha channel entirely.
1947 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1948 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
1949 * draw things like translucent text and perform other blending effects.
1951 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
1952 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
1953 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
1954 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
1955 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
1956 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
1957 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
1958 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
1960 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1962 if(op == WINED3DTOP_DISABLE) {
1963 arg1 = WINED3DTA_TEXTURE;
1964 op = WINED3DTOP_SELECTARG1;
1966 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
1967 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1968 arg2 = WINED3DTA_TEXTURE;
1969 op = WINED3DTOP_MODULATE;
1971 else arg1 = WINED3DTA_TEXTURE;
1973 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
1974 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1975 arg1 = WINED3DTA_TEXTURE;
1976 op = WINED3DTOP_MODULATE;
1978 else arg2 = WINED3DTA_TEXTURE;
1983 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
1984 * this if block here, and the other code(color keying, texture unit selection) are the same
1986 TRACE("Setting alpha op for stage %d\n", stage);
1987 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1988 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1989 op, arg1, arg2, arg0,
1991 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
1993 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1994 op, arg1, arg2, arg0);
1998 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1999 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
2000 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2003 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2004 if(use_vs(stateblock->wineD3DDevice) ||
2005 isStateDirty(context, STATE_VDECL)) {
2006 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
2010 if (mapped_stage == -1) return;
2012 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2013 if(mapped_stage >= GL_LIMITS(textures)) {
2016 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2017 checkGLcall("glActiveTextureARB");
2018 } else if (mapped_stage > 0) {
2019 /* We can't do anything here */
2020 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2023 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
2025 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
2026 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
2028 context->last_was_rhw,
2029 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
2030 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
2031 WINED3DDECLTYPE_UNUSED);
2033 /* The sampler applying function calls us if this changes */
2034 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
2036 FIXME("Non-power2 texture being used with generated texture coords\n");
2038 TRACE("Non power two matrix multiply fixup\n");
2039 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
2043 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
2046 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
2047 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2048 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2052 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2053 UINT *offset = stateblock->streamOffset;
2054 unsigned int mapped_stage = 0;
2055 unsigned int textureNo = 0;
2057 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2058 /* Abort if we don't support the extension. */
2059 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2060 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2064 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2065 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2067 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2068 if (mapped_stage == -1) continue;
2070 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2071 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2072 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2074 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2075 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2076 checkGLcall("glBindBufferARB");
2077 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2080 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2081 checkGLcall("glClientActiveTextureARB");
2083 /* The coords to supply depend completely on the fvf / vertex shader */
2085 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2086 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2087 sd->u.s.texCoords[coordIdx].dwStride,
2088 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2089 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2091 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2094 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2095 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2096 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2097 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2102 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2103 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2104 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2106 if (mapped_stage == -1) {
2107 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2111 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2112 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2115 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2116 checkGLcall("glActiveTextureARB");
2117 } else if (stage > 0) {
2118 /* We can't do anything here */
2119 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2123 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2125 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2126 * one flag, you can still specify an index value, which the system uses to
2127 * determine the texture wrapping mode.
2128 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2129 * means use the vertex position (camera-space) as the input texture coordinates
2130 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2131 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2132 * to the TEXCOORDINDEX value
2136 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2138 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2139 case WINED3DTSS_TCI_PASSTHRU:
2140 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2141 glDisable(GL_TEXTURE_GEN_S);
2142 glDisable(GL_TEXTURE_GEN_T);
2143 glDisable(GL_TEXTURE_GEN_R);
2144 glDisable(GL_TEXTURE_GEN_Q);
2145 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2148 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2149 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2150 * as the input texture coordinates for this stage's texture transformation. This
2151 * equates roughly to EYE_LINEAR
2154 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2155 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2156 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2157 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2158 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2160 glMatrixMode(GL_MODELVIEW);
2163 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2164 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2165 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2166 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2169 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2170 glEnable(GL_TEXTURE_GEN_S);
2171 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2172 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2173 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2174 glEnable(GL_TEXTURE_GEN_T);
2175 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2176 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2177 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2178 glEnable(GL_TEXTURE_GEN_R);
2179 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2180 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2181 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2185 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2187 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2188 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2189 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2190 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2191 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2192 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2194 glMatrixMode(GL_MODELVIEW);
2197 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2198 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2199 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2200 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2203 glEnable(GL_TEXTURE_GEN_S);
2204 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2205 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2206 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2207 glEnable(GL_TEXTURE_GEN_T);
2208 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2209 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2210 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2211 glEnable(GL_TEXTURE_GEN_R);
2212 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2213 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2214 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2219 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2221 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2222 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2223 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2224 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2225 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2226 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2228 glMatrixMode(GL_MODELVIEW);
2231 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2232 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2233 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2234 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2237 glEnable(GL_TEXTURE_GEN_S);
2238 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2239 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2240 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2241 glEnable(GL_TEXTURE_GEN_T);
2242 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2243 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2244 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2245 glEnable(GL_TEXTURE_GEN_R);
2246 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2247 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2248 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2253 /* Unhandled types: */
2256 /* ? disable GL_TEXTURE_GEN_n ? */
2257 glDisable(GL_TEXTURE_GEN_S);
2258 glDisable(GL_TEXTURE_GEN_T);
2259 glDisable(GL_TEXTURE_GEN_R);
2260 glDisable(GL_TEXTURE_GEN_Q);
2261 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2265 /* Update the texture matrix */
2266 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2267 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2270 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2271 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2272 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2273 * and do all the things linked to it
2274 * TODO: Tidy that up to reload only the arrays of the changed unit
2276 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2278 unloadTexCoords(stateblock);
2279 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2283 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2284 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2286 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2287 * has an update pending
2289 if(isStateDirty(context, STATE_VDECL) ||
2290 isStateDirty(context, STATE_PIXELSHADER)) {
2294 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2297 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2298 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2304 if(stateblock->pixelShader && stage != 0 &&
2305 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2306 /* The pixel shader has to know the luminance scale. Do a constants update if it
2307 * isn't scheduled anyway
2309 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2310 !isStateDirty(context, STATE_PIXELSHADER)) {
2311 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2315 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2316 if(tmpvalue.f != 0.0) {
2317 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2321 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2322 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2328 if(stateblock->pixelShader && stage != 0 &&
2329 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2330 /* The pixel shader has to know the luminance offset. Do a constants update if it
2331 * isn't scheduled anyway
2333 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2334 !isStateDirty(context, STATE_PIXELSHADER)) {
2335 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2339 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2340 if(tmpvalue.f != 0.0) {
2341 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2345 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2346 BOOL texIsPow2 = FALSE;
2347 DWORD sampler = state - STATE_SAMPLER(0);
2348 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
2350 if(!texture) return;
2351 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2352 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2353 * scaling is reapplied or removed, the texture matrix has to be reapplied
2355 * The mapped stage is alrady active because the sampler() function below, which is part of the
2358 if(sampler < MAX_TEXTURES) {
2359 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2360 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2361 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
2362 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
2365 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2366 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
2371 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2372 context->lastWasPow2Texture[sampler] = texIsPow2;
2373 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2378 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2379 DWORD sampler = state - STATE_SAMPLER(0);
2380 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2386 TRACE("Sampler: %d\n", sampler);
2387 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2388 * only has to bind textures and set the per texture states
2391 if (mapped_stage == -1) {
2392 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2396 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2397 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2400 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2401 checkGLcall("glActiveTextureARB");
2402 } else if (sampler > 0) {
2403 /* We can't do anything here */
2404 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2408 if(stateblock->textures[sampler]) {
2409 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
2410 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2412 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2413 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2414 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2415 GL_TEXTURE_LOD_BIAS_EXT,
2417 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
2420 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2421 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2422 /* Using a pixel shader? Verify the sampler types */
2424 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2425 * dimensions because the shader knows from which texture type to sample from. For the sake of
2426 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2427 * dimensions. This should make wrong sampling sources visible :-)
2429 glEnable(stateblock->textureDimensions[sampler]);
2430 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2431 } else if(sampler < stateblock->lowest_disabled_stage) {
2432 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2433 /* If color keying is enabled update the alpha test, it depends on the existence
2434 * of a color key in stage 0
2436 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2439 } else if(mapped_stage < GL_LIMITS(textures)) {
2440 if(sampler < stateblock->lowest_disabled_stage) {
2441 /* TODO: What should I do with pixel shaders here ??? */
2442 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2443 /* If color keying is enabled update the alpha test, it depends on the existence
2444 * of a color key in stage 0
2446 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2448 } /* Otherwise tex_colorop disables the stage */
2449 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2450 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2454 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2455 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2456 BOOL use_pshader = use_ps(device);
2457 BOOL use_vshader = use_vs(device);
2458 BOOL update_fog = FALSE;
2462 if(!context->last_was_pshader) {
2463 /* Former draw without a pixel shader, some samplers
2464 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2465 * make sure to enable them
2467 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2468 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2469 sampler(STATE_SAMPLER(i), stateblock, context);
2474 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2475 * if a different texture was bound. I don't have to do anything.
2479 /* Compile and bind the shader */
2480 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2482 /* Disabled the pixel shader - color ops weren't applied
2483 * while it was enabled, so re-apply them.
2485 for(i=0; i < MAX_TEXTURES; i++) {
2486 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2487 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
2488 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2491 if(context->last_was_pshader)
2495 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
2496 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2498 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2499 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2504 state_fog(state, stateblock, context);
2506 context->last_was_pshader = use_pshader;
2509 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2510 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2511 if(stateblock->pixelShader && stage != 0 &&
2512 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
2513 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2516 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2517 !isStateDirty(context, STATE_PIXELSHADER)) {
2518 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2523 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2524 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2527 if(stage >= GL_LIMITS(texture_stages)) {
2528 WARN("Bump env matrix of unsupported stage set\n");
2529 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2530 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2531 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2533 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2534 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2535 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2536 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2537 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, (float *) mat));
2538 checkGLcall("glTexBumpParameterfvATI");
2541 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2542 /* This function is called by transform_view below if the view matrix was changed too
2544 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2545 * does not always update the world matrix, only on a switch between transformed
2546 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
2547 * draw, but that should be rather rare and cheaper in total.
2549 glMatrixMode(GL_MODELVIEW);
2550 checkGLcall("glMatrixMode");
2552 if(context->last_was_rhw) {
2554 checkGLcall("glLoadIdentity()");
2556 /* In the general case, the view matrix is the identity matrix */
2557 if (stateblock->wineD3DDevice->view_ident) {
2558 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2559 checkGLcall("glLoadMatrixf");
2561 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2562 checkGLcall("glLoadMatrixf");
2563 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2564 checkGLcall("glMultMatrixf");
2569 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2570 UINT index = state - STATE_CLIPPLANE(0);
2572 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2576 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2577 glMatrixMode(GL_MODELVIEW);
2579 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2581 TRACE("Clipplane [%f,%f,%f,%f]\n",
2582 stateblock->clipplane[index][0],
2583 stateblock->clipplane[index][1],
2584 stateblock->clipplane[index][2],
2585 stateblock->clipplane[index][3]);
2586 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2587 checkGLcall("glClipPlane");
2592 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2593 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2595 TRACE("Setting world matrix %d\n", matrix);
2597 if(matrix >= GL_LIMITS(blends)) {
2598 WARN("Unsupported blend matrix set\n");
2600 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2604 /* GL_MODELVIEW0_ARB: 0x1700
2605 * GL_MODELVIEW1_ARB: 0x0x850a
2606 * GL_MODELVIEW2_ARB: 0x8722
2607 * GL_MODELVIEW3_ARB: 0x8723
2609 * GL_MODELVIEW31_ARB: 0x873F
2611 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2612 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2614 glMatrixMode(glMat);
2615 checkGLcall("glMatrixMode(glMat)");
2617 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2618 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2620 if(stateblock->wineD3DDevice->view_ident) {
2621 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2622 checkGLcall("glLoadMatrixf")
2624 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2625 checkGLcall("glLoadMatrixf")
2626 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2627 checkGLcall("glMultMatrixf")
2631 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2632 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2635 case WINED3DVBF_1WEIGHTS:
2636 case WINED3DVBF_2WEIGHTS:
2637 case WINED3DVBF_3WEIGHTS:
2638 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2639 glEnable(GL_VERTEX_BLEND_ARB);
2640 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2642 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2643 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2645 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2647 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2649 for(i = 1; i < GL_LIMITS(blends); i++) {
2650 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2651 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2654 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2657 static BOOL once = FALSE;
2660 /* TODO: Implement vertex blending in drawStridedSlow */
2661 FIXME("Vertex blending enabled, but not supported by hardware\n");
2666 case WINED3DVBF_DISABLE:
2667 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2668 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2669 glDisable(GL_VERTEX_BLEND_ARB);
2670 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2672 TRACE("Vertex blending disabled\n");
2676 case WINED3DVBF_TWEENING:
2677 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2678 * vertex weights in the vertices?
2679 * For now we don't report that as supported, so a warn should suffice
2681 WARN("Tweening not supported yet\n");
2686 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2689 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2690 * NOTE: We have to reset the positions even if the light/plane is not currently
2691 * enabled, since the call to enable it will not reset the position.
2692 * NOTE2: Apparently texture transforms do NOT need reapplying
2695 PLIGHTINFOEL *light = NULL;
2697 glMatrixMode(GL_MODELVIEW);
2698 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2699 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2700 checkGLcall("glLoadMatrixf(...)");
2702 /* Reset lights. TODO: Call light apply func */
2703 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2704 light = stateblock->activeLights[k];
2705 if(!light) continue;
2706 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2707 checkGLcall("glLightfv posn");
2708 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2709 checkGLcall("glLightfv dirn");
2712 /* Reset Clipping Planes */
2713 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2714 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2715 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2719 if(context->last_was_rhw) {
2721 checkGLcall("glLoadIdentity()");
2722 /* No need to update the world matrix, the identity is fine */
2726 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2727 * No need to do it here if the state is scheduled for update.
2729 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2730 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2733 /* Avoid looping over a number of matrices if the app never used the functionality */
2734 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2735 for(k = 1; k < GL_LIMITS(blends); k++) {
2736 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2737 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2743 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2744 glMatrixMode(GL_PROJECTION);
2745 checkGLcall("glMatrixMode(GL_PROJECTION)");
2747 checkGLcall("glLoadIdentity");
2749 if(context->last_was_rhw) {
2750 double X, Y, height, width, minZ, maxZ;
2752 X = stateblock->viewport.X;
2753 Y = stateblock->viewport.Y;
2754 height = stateblock->viewport.Height;
2755 width = stateblock->viewport.Width;
2756 minZ = stateblock->viewport.MinZ;
2757 maxZ = stateblock->viewport.MaxZ;
2759 if(!stateblock->wineD3DDevice->untransformed) {
2760 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2761 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2762 * suppress depth clipping. This can be done because it is an orthogonal projection and
2763 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2764 * Persia 3D need this.
2766 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2767 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2768 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2771 * Also note that this breaks z comparison against z values filled in with clear,
2772 * but no app depending on that and disabled clipping has been found yet. Comparing
2773 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2776 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2777 * but this would break Z buffer operation. Raising the range to something less than
2778 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2781 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2782 if(stateblock->wineD3DDevice->render_offscreen) {
2783 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2785 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2788 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2789 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2790 * unmodified to opengl.
2792 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2793 * replacement shader.
2795 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2796 if(stateblock->wineD3DDevice->render_offscreen) {
2797 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2799 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2802 checkGLcall("glOrtho");
2804 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2805 glTranslatef(0.5, 0.5, 0);
2806 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2807 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2808 * render everything upside down when rendering offscreen. */
2809 if (stateblock->wineD3DDevice->render_offscreen) {
2810 glScalef(1.0, -1.0, 1.0);
2811 checkGLcall("glScalef");
2814 /* The rule is that the window coordinate 0 does not correspond to the
2815 beginning of the first pixel, but the center of the first pixel.
2816 As a consequence if you want to correctly draw one line exactly from
2817 the left to the right end of the viewport (with all matrices set to
2818 be identity), the x coords of both ends of the line would be not
2819 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2822 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2823 divide by the Width/Height, so we need the half range(1.0) to translate by
2826 The other fun is that d3d's output z range after the transformation is [0;1],
2827 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2828 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2829 of Z buffer precision and the clear values do not match in the z test. Thus scale
2830 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2832 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2833 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2834 if (stateblock->wineD3DDevice->render_offscreen) {
2835 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2836 * render everything upside down when rendering offscreen. */
2837 glScalef(1.0, -1.0, 2.0);
2839 glScalef(1.0, 1.0, 2.0);
2841 checkGLcall("glScalef");
2843 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2844 checkGLcall("glLoadMatrixf");
2848 /* This should match any arrays loaded in loadVertexData.
2849 * stateblock impl is required for GL_SUPPORT
2850 * TODO: Only load / unload arrays if we have to.
2852 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2853 glDisableClientState(GL_VERTEX_ARRAY);
2854 glDisableClientState(GL_NORMAL_ARRAY);
2855 glDisableClientState(GL_COLOR_ARRAY);
2856 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2857 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2859 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2860 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2861 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2862 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2864 unloadTexCoords(stateblock);
2867 /* This should match any arrays loaded in loadNumberedArrays
2868 * TODO: Only load / unload arrays if we have to.
2870 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2871 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2872 GLint maxAttribs = 16;
2875 /* Leave all the attribs disabled */
2876 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2877 /* MESA does not support it right not */
2878 if (glGetError() != GL_NO_ERROR)
2880 for (i = 0; i < maxAttribs; ++i) {
2881 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2882 checkGLcall("glDisableVertexAttribArrayARB(reg)");
2883 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
2884 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
2885 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
2886 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
2887 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
2889 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
2890 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
2894 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2895 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2897 UINT *offset = stateblock->streamOffset;
2898 IWineD3DVertexBufferImpl *vb;
2899 DWORD_PTR shift_index;
2901 /* Default to no instancing */
2902 stateblock->wineD3DDevice->instancedDraw = FALSE;
2904 for (i = 0; i < MAX_ATTRIBS; i++) {
2906 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2909 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2910 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2911 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2912 stateblock->wineD3DDevice->instancedDraw = TRUE;
2916 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2918 if(strided->u.input[i].dwStride) {
2919 if(curVBO != strided->u.input[i].VBO) {
2920 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2921 checkGLcall("glBindBufferARB");
2922 curVBO = strided->u.input[i].VBO;
2924 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2925 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
2926 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
2927 * vbo we won't be load converted attributes anyway
2929 if(curVBO && vb->conv_shift) {
2930 TRACE("Loading attribute from shifted buffer\n");
2931 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
2932 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
2933 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
2934 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
2935 shift_index = shift_index % strided->u.input[i].dwStride;
2936 GL_EXTCALL(glVertexAttribPointerARB(i,
2937 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2938 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2939 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2942 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
2943 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2944 offset[strided->u.input[i].streamNo]));
2947 GL_EXTCALL(glVertexAttribPointerARB(i,
2948 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2949 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2950 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2951 strided->u.input[i].dwStride,
2953 strided->u.input[i].lpData +
2954 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2955 offset[strided->u.input[i].streamNo]) );
2957 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2959 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2960 * set up the attribute statically. But we have to figure out the system memory address.
2962 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2963 if(strided->u.input[i].VBO) {
2964 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2965 ptr += (long) vb->resource.allocatedMemory;
2967 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2969 switch(strided->u.input[i].dwType) {
2970 case WINED3DDECLTYPE_FLOAT1:
2971 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2973 case WINED3DDECLTYPE_FLOAT2:
2974 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2976 case WINED3DDECLTYPE_FLOAT3:
2977 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2979 case WINED3DDECLTYPE_FLOAT4:
2980 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2983 case WINED3DDECLTYPE_UBYTE4:
2984 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2986 case WINED3DDECLTYPE_UBYTE4N:
2987 case WINED3DDECLTYPE_D3DCOLOR:
2988 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2991 case WINED3DDECLTYPE_SHORT2:
2992 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2994 case WINED3DDECLTYPE_SHORT4:
2995 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2998 case WINED3DDECLTYPE_SHORT2N:
3000 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
3001 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3004 case WINED3DDECLTYPE_USHORT2N:
3006 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
3007 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3010 case WINED3DDECLTYPE_SHORT4N:
3011 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
3013 case WINED3DDECLTYPE_USHORT4N:
3014 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
3017 case WINED3DDECLTYPE_UDEC3:
3018 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3019 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
3021 case WINED3DDECLTYPE_DEC3N:
3022 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3023 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
3026 case WINED3DDECLTYPE_FLOAT16_2:
3027 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3028 * byte float according to the IEEE standard
3030 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3032 case WINED3DDECLTYPE_FLOAT16_4:
3033 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3036 case WINED3DDECLTYPE_UNUSED:
3038 ERR("Unexpected declaration in stride 0 attributes\n");
3044 checkGLcall("Loading numbered arrays");
3047 /* Used from 2 different functions, and too big to justify making it inlined */
3048 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3049 UINT *offset = stateblock->streamOffset;
3050 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3052 TRACE("Using fast vertex array code\n");
3054 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3055 stateblock->wineD3DDevice->instancedDraw = FALSE;
3057 /* Blend Data ---------------------------------------------- */
3058 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3059 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3061 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3062 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3063 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3065 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3066 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3068 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3070 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3071 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3072 sd->u.s.blendWeights.dwStride,
3073 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3075 if(curVBO != sd->u.s.blendWeights.VBO) {
3076 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3077 checkGLcall("glBindBufferARB");
3078 curVBO = sd->u.s.blendWeights.VBO;
3081 GL_EXTCALL(glWeightPointerARB)(
3082 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3083 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3084 sd->u.s.blendWeights.dwStride,
3085 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3087 checkGLcall("glWeightPointerARB");
3089 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3090 static BOOL showfixme = TRUE;
3092 FIXME("blendMatrixIndices support\n");
3096 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3097 /* FIXME("TODO\n");*/
3100 GL_EXTCALL(glVertexWeightPointerEXT)(
3101 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3102 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3103 sd->u.s.blendWeights.dwStride,
3104 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3105 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3106 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3107 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3111 /* TODO: support blends in drawStridedSlow
3112 * No need to write a FIXME here, this is done after the general vertex decl decoding
3114 WARN("unsupported blending in openGl\n");
3117 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3118 static const GLbyte one = 1;
3119 GL_EXTCALL(glWeightbvARB(1, &one));
3120 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3124 #if 0 /* FOG ----------------------------------------------*/
3125 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3127 if (GL_SUPPORT(EXT_FOG_COORD) {
3128 glEnableClientState(GL_FOG_COORDINATE_EXT);
3129 (GL_EXTCALL)(FogCoordPointerEXT)(
3130 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3131 sd->u.s.fog.dwStride,
3132 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3134 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3135 /* FIXME: fixme once */
3136 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3139 if (GL_SUPPRT(EXT_FOR_COORD) {
3140 /* make sure fog is disabled */
3141 glDisableClientState(GL_FOG_COORDINATE_EXT);
3146 #if 0 /* tangents ----------------------------------------------*/
3147 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3148 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3150 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3151 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3152 glEnable(GL_TANGENT_ARRAY_EXT);
3153 (GL_EXTCALL)(TangentPointerEXT)(
3154 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3155 sd->u.s.tangent.dwStride,
3156 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3158 glDisable(GL_TANGENT_ARRAY_EXT);
3160 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3161 glEnable(GL_BINORMAL_ARRAY_EXT);
3162 (GL_EXTCALL)(BinormalPointerEXT)(
3163 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3164 sd->u.s.binormal.dwStride,
3165 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3167 glDisable(GL_BINORMAL_ARRAY_EXT);
3171 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3172 /* FIXME: fixme once */
3173 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3176 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3177 /* make sure fog is disabled */
3178 glDisable(GL_TANGENT_ARRAY_EXT);
3179 glDisable(GL_BINORMAL_ARRAY_EXT);
3184 /* Point Size ----------------------------------------------*/
3185 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3187 /* no such functionality in the fixed function GL pipeline */
3188 TRACE("Cannot change ptSize here in openGl\n");
3189 /* TODO: Implement this function in using shaders if they are available */
3193 /* Vertex Pointers -----------------------------------------*/
3194 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3195 /* Note dwType == float3 or float4 == 2 or 3 */
3196 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3197 sd->u.s.position.dwStride,
3198 sd->u.s.position.dwType + 1,
3199 sd->u.s.position.lpData));
3201 if(curVBO != sd->u.s.position.VBO) {
3202 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3203 checkGLcall("glBindBufferARB");
3204 curVBO = sd->u.s.position.VBO;
3207 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3208 handling for rhw mode should not impact screen position whereas in GL it does.
3209 This may result in very slightly distorted textures in rhw mode.
3210 There's always the other option of fixing the view matrix to
3211 prevent w from having any effect.
3213 This only applies to user pointer sources, in VBOs the vertices are fixed up
3215 if(sd->u.s.position.VBO == 0) {
3216 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3217 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3218 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3221 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3222 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3223 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3225 checkGLcall("glVertexPointer(...)");
3226 glEnableClientState(GL_VERTEX_ARRAY);
3227 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3230 /* Normals -------------------------------------------------*/
3231 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3232 /* Note dwType == float3 or float4 == 2 or 3 */
3233 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3234 sd->u.s.normal.dwStride,
3235 sd->u.s.normal.lpData));
3236 if(curVBO != sd->u.s.normal.VBO) {
3237 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3238 checkGLcall("glBindBufferARB");
3239 curVBO = sd->u.s.normal.VBO;
3242 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3243 sd->u.s.normal.dwStride,
3244 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3245 checkGLcall("glNormalPointer(...)");
3246 glEnableClientState(GL_NORMAL_ARRAY);
3247 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3250 glNormal3f(0, 0, 0);
3251 checkGLcall("glNormal3f(0, 0, 0)");
3254 /* Diffuse Colour --------------------------------------------*/
3255 /* WARNING: Data here MUST be in RGBA format, so cannot */
3256 /* go directly into fast mode from app pgm, because */
3257 /* directx requires data in BGRA format. */
3258 /* currently fixupVertices swizzles the format, but this isn't*/
3259 /* very practical when using VBOs */
3260 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3261 /* , or the user doesn't care and wants the speed advantage */
3263 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3264 /* Note dwType == float3 or float4 == 2 or 3 */
3265 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3266 sd->u.s.diffuse.dwStride,
3267 sd->u.s.diffuse.lpData));
3269 if(curVBO != sd->u.s.diffuse.VBO) {
3270 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3271 checkGLcall("glBindBufferARB");
3272 curVBO = sd->u.s.diffuse.VBO;
3275 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3276 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3277 sd->u.s.diffuse.dwStride,
3278 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3279 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3280 glEnableClientState(GL_COLOR_ARRAY);
3281 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3284 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3285 checkGLcall("glColor4f(1, 1, 1, 1)");
3288 /* Specular Colour ------------------------------------------*/
3289 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3290 TRACE("setting specular colour\n");
3291 /* Note dwType == float3 or float4 == 2 or 3 */
3292 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3293 sd->u.s.specular.dwStride,
3294 sd->u.s.specular.lpData));
3295 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3296 if(curVBO != sd->u.s.specular.VBO) {
3297 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3298 checkGLcall("glBindBufferARB");
3299 curVBO = sd->u.s.specular.VBO;
3301 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3302 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3303 sd->u.s.specular.dwStride,
3304 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3305 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3306 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3307 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3310 /* Missing specular color is not critical, no warnings */
3311 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3315 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3316 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3317 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3320 /* Missing specular color is not critical, no warnings */
3321 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3325 /* Texture coords -------------------------------------------*/
3326 loadTexCoords(stateblock, sd, &curVBO);
3329 static inline void drawPrimitiveTraceDataLocations(
3330 WineDirect3DVertexStridedData *dataLocations) {
3332 /* Dump out what parts we have supplied */
3333 TRACE("Strided Data:\n");
3334 TRACE_STRIDED((dataLocations), position);
3335 TRACE_STRIDED((dataLocations), blendWeights);
3336 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3337 TRACE_STRIDED((dataLocations), normal);
3338 TRACE_STRIDED((dataLocations), pSize);
3339 TRACE_STRIDED((dataLocations), diffuse);
3340 TRACE_STRIDED((dataLocations), specular);
3341 TRACE_STRIDED((dataLocations), texCoords[0]);
3342 TRACE_STRIDED((dataLocations), texCoords[1]);
3343 TRACE_STRIDED((dataLocations), texCoords[2]);
3344 TRACE_STRIDED((dataLocations), texCoords[3]);
3345 TRACE_STRIDED((dataLocations), texCoords[4]);
3346 TRACE_STRIDED((dataLocations), texCoords[5]);
3347 TRACE_STRIDED((dataLocations), texCoords[6]);
3348 TRACE_STRIDED((dataLocations), texCoords[7]);
3349 TRACE_STRIDED((dataLocations), position2);
3350 TRACE_STRIDED((dataLocations), normal2);
3351 TRACE_STRIDED((dataLocations), tangent);
3352 TRACE_STRIDED((dataLocations), binormal);
3353 TRACE_STRIDED((dataLocations), tessFactor);
3354 TRACE_STRIDED((dataLocations), fog);
3355 TRACE_STRIDED((dataLocations), depth);
3356 TRACE_STRIDED((dataLocations), sample);
3361 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3362 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3364 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3365 BOOL useVertexShaderFunction;
3367 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3368 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3369 useVertexShaderFunction = TRUE;
3371 useVertexShaderFunction = FALSE;
3375 if(device->up_strided) {
3376 /* Note: this is a ddraw fixed-function code path */
3377 TRACE("================ Strided Input ===================\n");
3378 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3381 drawPrimitiveTraceDataLocations(dataLocations);
3384 /* Note: This is a fixed function or shader codepath.
3385 * This means it must handle both types of strided data.
3386 * Shaders must go through here to zero the strided data, even if they
3387 * don't set any declaration at all
3389 TRACE("================ Vertex Declaration ===================\n");
3390 memset(dataLocations, 0, sizeof(*dataLocations));
3391 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3392 useVertexShaderFunction, dataLocations, &fixup);
3395 if (dataLocations->u.s.position_transformed) {
3396 useVertexShaderFunction = FALSE;
3399 /* Unload the old arrays before loading the new ones to get old junk out */
3400 if(context->numberedArraysLoaded) {
3401 unloadNumberedArrays(stateblock);
3402 context->numberedArraysLoaded = FALSE;
3404 if(context->namedArraysLoaded) {
3405 unloadVertexData(stateblock);
3406 context->namedArraysLoaded = FALSE;
3409 if(useVertexShaderFunction) {
3410 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3411 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3412 device->useDrawStridedSlow = TRUE;
3413 context->numberedArraysLoaded = FALSE;
3415 TRACE("Loading numbered arrays\n");
3416 loadNumberedArrays(stateblock, dataLocations);
3417 device->useDrawStridedSlow = FALSE;
3418 context->numberedArraysLoaded = TRUE;
3421 (dataLocations->u.s.pSize.lpData == NULL &&
3422 dataLocations->u.s.diffuse.lpData == NULL &&
3423 dataLocations->u.s.specular.lpData == NULL)) {
3424 /* Load the vertex data using named arrays */
3425 TRACE("Loading vertex data\n");
3426 loadVertexData(stateblock, dataLocations);
3427 device->useDrawStridedSlow = FALSE;
3428 context->namedArraysLoaded = TRUE;
3430 TRACE("Not loading vertex data\n");
3431 device->useDrawStridedSlow = TRUE;
3434 /* Generate some fixme's if unsupported functionality is being used */
3435 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3436 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3437 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3438 FIXME("Tweening is only valid with vertex shaders\n");
3440 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3441 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3443 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3444 FIXME("Extended attributes are only valid with vertex shaders\n");
3446 #undef BUFFER_OR_DATA
3449 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3450 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3451 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3452 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3454 /* Some stuff is in the device until we have per context tracking */
3455 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3456 BOOL wasrhw = context->last_was_rhw;
3458 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3459 * here simply check whether a shader was set, or the user disabled shaders
3461 if (use_vs(device)) {
3462 useVertexShaderFunction = TRUE;
3464 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3467 } else if(context->last_was_foggy_shader) {
3471 transformed = device->strided_streams.u.s.position_transformed;
3472 if (transformed) useVertexShaderFunction = FALSE;
3474 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3478 /* Reapply lighting if it is not scheduled for reapplication already */
3479 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3480 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3484 context->last_was_rhw = TRUE;
3487 /* Untransformed, so relies on the view and projection matrices */
3488 context->last_was_rhw = FALSE;
3489 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3490 device->untransformed = TRUE;
3492 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3493 * Not needed as long as only hw shaders are supported
3496 /* This sets the shader output position correction constants.
3497 * TODO: Move to the viewport state
3499 if (useVertexShaderFunction) {
3500 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3501 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3505 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3506 * off this function will be called again anyway to make sure they're properly set
3508 if(!useVertexShaderFunction) {
3509 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3510 * or transformed / untransformed was switched
3512 if(wasrhw != context->last_was_rhw &&
3513 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3514 !isStateDirty(context, STATE_VIEWPORT)) {
3515 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3517 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3520 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3521 * this check will fail and the matrix not applied again. This is OK because a simple
3522 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3523 * needs of the vertex declaration.
3525 * World and view matrix go into the same gl matrix, so only apply them when neither is
3528 if(transformed != wasrhw &&
3529 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3530 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3531 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3534 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3535 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3538 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3539 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3541 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3542 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3545 /* We compile the shader here because we need the vertex declaration
3546 * in order to determine if we need to do any swizzling for D3DCOLOR
3547 * registers. If the shader is already compiled this call will do nothing. */
3548 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3550 if(!context->last_was_vshader) {
3552 static BOOL warned = FALSE;
3553 /* Disable all clip planes to get defined results on all drivers. See comment in the
3554 * state_clipping state handler
3556 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3557 glDisable(GL_CLIP_PLANE0 + i);
3558 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3561 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3562 FIXME("Clipping not supported with vertex shaders\n");
3566 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3567 * shaders themselves do not need it, but the matrices are not reapplied automatically when
3568 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3569 * fixed function vertex processing states back in a sane state before switching to shaders
3571 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3572 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3574 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3575 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3581 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3584 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3585 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3587 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3588 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3592 context->last_was_vshader = useVertexShaderFunction;
3595 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3597 if(!useVertexShaderFunction) {
3599 for(i = 0; i < MAX_TEXTURES; i++) {
3600 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3601 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3607 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3609 IWineD3DSurfaceImpl *target;
3611 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3612 checkGLcall("glDepthRange");
3613 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3615 if(stateblock->wineD3DDevice->render_offscreen) {
3616 glViewport(stateblock->viewport.X,
3617 stateblock->viewport.Y,
3618 stateblock->viewport.Width, stateblock->viewport.Height);
3620 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3621 target->get_drawable_size(target, &width, &height);
3623 glViewport(stateblock->viewport.X,
3624 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3625 stateblock->viewport.Width, stateblock->viewport.Height);
3628 checkGLcall("glViewport");
3631 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3632 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3633 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3634 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3635 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3637 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3638 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3642 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3643 UINT Index = state - STATE_ACTIVELIGHT(0);
3644 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3647 glDisable(GL_LIGHT0 + Index);
3648 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3651 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3653 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3654 glMatrixMode(GL_MODELVIEW);
3656 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3659 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3660 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3661 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3662 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3663 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3664 checkGLcall("glLightfv");
3667 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3668 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3669 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3670 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3671 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3672 checkGLcall("glLightfv");
3675 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3676 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3677 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3678 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3679 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3680 checkGLcall("glLightfv");
3682 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3683 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3685 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3688 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3689 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3690 * Attenuation0 to NaN and crashes in the gl lib
3693 switch (lightInfo->OriginalParms.Type) {
3694 case WINED3DLIGHT_POINT:
3696 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3697 checkGLcall("glLightfv");
3698 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3699 checkGLcall("glLightf");
3700 /* Attenuation - Are these right? guessing... */
3701 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3702 checkGLcall("glLightf");
3703 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3704 checkGLcall("glLightf");
3705 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3706 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3707 checkGLcall("glLightf");
3711 case WINED3DLIGHT_SPOT:
3713 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3714 checkGLcall("glLightfv");
3716 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3717 checkGLcall("glLightfv");
3718 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3719 checkGLcall("glLightf");
3720 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3721 checkGLcall("glLightf");
3722 /* Attenuation - Are these right? guessing... */
3723 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3724 checkGLcall("glLightf");
3725 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3726 checkGLcall("glLightf");
3727 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3728 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3729 checkGLcall("glLightf");
3733 case WINED3DLIGHT_DIRECTIONAL:
3735 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3736 checkGLcall("glLightfv");
3737 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3738 checkGLcall("glLightf");
3739 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3740 checkGLcall("glLightf");
3744 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3747 /* Restore the modelview matrix */
3750 glEnable(GL_LIGHT0 + Index);
3751 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3757 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3758 RECT *pRect = &stateblock->scissorRect;
3761 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3763 target->get_drawable_size(target, &width, &height);
3764 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3765 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3767 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3768 pRect->right - pRect->left, pRect->bottom - pRect->top);
3770 if (stateblock->wineD3DDevice->render_offscreen) {
3771 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3773 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3775 checkGLcall("glScissor");
3778 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3779 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3780 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3781 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3783 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3784 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3789 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3790 if(stateblock->wineD3DDevice->render_offscreen) {
3791 glFrontFace(GL_CCW);
3792 checkGLcall("glFrontFace(GL_CCW)");
3795 checkGLcall("glFrontFace(GL_CW)");
3799 const struct StateEntryTemplate misc_state_template[] = {
3800 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3801 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3802 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3803 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3804 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3805 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3806 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3807 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3808 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3809 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3810 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
3811 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
3812 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
3813 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
3814 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
3815 * vshader loadings are untied from each other
3817 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
3818 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
3819 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3820 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3821 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3822 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3823 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3824 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3825 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3826 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3827 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3828 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3829 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3830 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3831 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3832 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3833 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3834 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3835 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3836 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3837 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3838 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3839 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3840 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3841 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3842 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3843 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3844 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3845 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3846 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3847 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3848 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3849 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3850 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3851 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3852 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3853 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3854 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3855 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3856 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3857 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3858 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3859 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3860 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3861 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3862 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3863 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3864 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3865 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3866 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3868 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
3869 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, 0 },
3870 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
3871 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
3872 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
3873 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
3874 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
3875 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
3876 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
3877 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
3878 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
3879 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
3880 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
3881 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
3882 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3883 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3884 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3885 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3886 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
3887 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
3888 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
3889 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
3890 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
3891 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
3892 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
3893 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
3894 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
3895 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
3896 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
3897 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
3898 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
3899 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3900 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3901 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3902 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3903 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3904 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3905 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3906 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
3907 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
3908 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3909 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3910 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3911 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3912 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3913 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3914 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3915 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3916 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3917 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3918 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3919 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3920 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3921 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3922 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3923 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3924 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3925 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3926 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3927 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3928 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3929 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
3930 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
3931 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
3932 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
3933 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
3934 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
3935 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3936 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3937 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3938 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3939 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3940 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3941 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3942 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
3943 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 },
3944 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
3945 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3946 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
3947 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 },
3948 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
3949 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
3950 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3951 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3952 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3953 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
3954 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 },
3955 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
3957 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
3958 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
3959 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
3960 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
3961 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
3962 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
3963 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
3964 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
3965 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
3966 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
3967 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
3968 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
3969 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
3970 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
3971 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
3972 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
3973 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
3974 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
3975 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
3976 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
3977 {0 /* Terminate */, { 0, 0 }, 0 },
3980 const struct StateEntryTemplate ffp_vertexstate_template[] = {
3981 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
3982 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
3983 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
3984 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
3986 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
3987 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
3988 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
3989 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
3990 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
3991 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
3992 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
3993 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
3994 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
3995 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
3996 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
3997 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
3998 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
3999 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
4000 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
4001 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
4002 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
4003 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
4004 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
4005 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
4006 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
4007 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
4008 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
4009 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
4010 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
4011 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
4012 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
4013 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
4014 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
4015 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
4016 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
4017 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
4019 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
4020 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
4021 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
4022 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
4023 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
4024 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
4025 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
4026 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
4028 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
4029 /* Transform states follow */
4030 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
4031 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
4032 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, 0 },
4033 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, 0 },
4034 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, 0 },
4035 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, 0 },
4036 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, 0 },
4037 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, 0 },
4038 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, 0 },
4039 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, 0 },
4040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_world }, 0 },
4042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_world }, 0 },
4043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_world }, 0 },
4044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_world }, 0 },
4045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_world }, 0 },
4046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_world }, 0 },
4047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_world }, 0 },
4048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_world }, 0 },
4049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_world }, 0 },
4050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_world }, 0 },
4051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_world }, 0 },
4052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_world }, 0 },
4053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_world }, 0 },
4054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_world }, 0 },
4055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_world }, 0 },
4056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_world }, 0 },
4057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_world }, 0 },
4058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_world }, 0 },
4059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_world }, 0 },
4060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_world }, 0 },
4061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_world }, 0 },
4062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_world }, 0 },
4063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_world }, 0 },
4064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_world }, 0 },
4065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_world }, 0 },
4066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_world }, 0 },
4067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_world }, 0 },
4068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_world }, 0 },
4069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_world }, 0 },
4070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_world }, 0 },
4071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_world }, 0 },
4072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_world }, 0 },
4073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_world }, 0 },
4074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_world }, 0 },
4075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_world }, 0 },
4076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_world }, 0 },
4077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_world }, 0 },
4078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_world }, 0 },
4079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_world }, 0 },
4080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_world }, 0 },
4081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_world }, 0 },
4082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_world }, 0 },
4083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_world }, 0 },
4084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_world }, 0 },
4085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_world }, 0 },
4086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_world }, 0 },
4087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_world }, 0 },
4088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_world }, 0 },
4089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_world }, 0 },
4090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_world }, 0 },
4091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_world }, 0 },
4092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_world }, 0 },
4093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_world }, 0 },
4094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_world }, 0 },
4095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_world }, 0 },
4096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_world }, 0 },
4097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_world }, 0 },
4098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_world }, 0 },
4099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_world }, 0 },
4100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_world }, 0 },
4101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_world }, 0 },
4102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_world }, 0 },
4103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_world }, 0 },
4104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_world }, 0 },
4105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_world }, 0 },
4106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_world }, 0 },
4107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_world }, 0 },
4108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_world }, 0 },
4109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_world }, 0 },
4110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_world }, 0 },
4111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_world }, 0 },
4112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_world }, 0 },
4113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_world }, 0 },
4114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_world }, 0 },
4115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_world }, 0 },
4116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_world }, 0 },
4117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_world }, 0 },
4118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_world }, 0 },
4119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_world }, 0 },
4120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_world }, 0 },
4121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_world }, 0 },
4122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_world }, 0 },
4123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_world }, 0 },
4124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_world }, 0 },
4125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_world }, 0 },
4126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_world }, 0 },
4127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_world }, 0 },
4128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_world }, 0 },
4129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_world }, 0 },
4130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_world }, 0 },
4131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_world }, 0 },
4132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_world }, 0 },
4133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_world }, 0 },
4134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_world }, 0 },
4135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_world }, 0 },
4136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_world }, 0 },
4137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_world }, 0 },
4138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_world }, 0 },
4139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_world }, 0 },
4140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_world }, 0 },
4141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_world }, 0 },
4142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_world }, 0 },
4143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_world }, 0 },
4144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_world }, 0 },
4145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_world }, 0 },
4146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_world }, 0 },
4147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_world }, 0 },
4148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_world }, 0 },
4149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_world }, 0 },
4150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_world }, 0 },
4151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_world }, 0 },
4152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_world }, 0 },
4153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_world }, 0 },
4154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_world }, 0 },
4155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_world }, 0 },
4156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_world }, 0 },
4157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_world }, 0 },
4158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_world }, 0 },
4159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_world }, 0 },
4160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_world }, 0 },
4161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_world }, 0 },
4162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_world }, 0 },
4163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_world }, 0 },
4164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_world }, 0 },
4165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_world }, 0 },
4166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_world }, 0 },
4167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_world }, 0 },
4168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_world }, 0 },
4169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_world }, 0 },
4170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_world }, 0 },
4171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_world }, 0 },
4172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_world }, 0 },
4173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_world }, 0 },
4174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_world }, 0 },
4175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_world }, 0 },
4176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_world }, 0 },
4177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_world }, 0 },
4178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_world }, 0 },
4179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_world }, 0 },
4180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_world }, 0 },
4181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_world }, 0 },
4182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_world }, 0 },
4183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_world }, 0 },
4184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_world }, 0 },
4185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_world }, 0 },
4186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_world }, 0 },
4187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_world }, 0 },
4188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_world }, 0 },
4189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_world }, 0 },
4190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_world }, 0 },
4191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_world }, 0 },
4192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_world }, 0 },
4193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_world }, 0 },
4194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_world }, 0 },
4195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_world }, 0 },
4196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_world }, 0 },
4197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_world }, 0 },
4198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_world }, 0 },
4199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_world }, 0 },
4200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_world }, 0 },
4201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_world }, 0 },
4202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_world }, 0 },
4203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_world }, 0 },
4204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_world }, 0 },
4205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_world }, 0 },
4206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_world }, 0 },
4207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_world }, 0 },
4208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_world }, 0 },
4209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_world }, 0 },
4210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_world }, 0 },
4211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_world }, 0 },
4212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_world }, 0 },
4213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_world }, 0 },
4214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_world }, 0 },
4215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_world }, 0 },
4216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_world }, 0 },
4217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_world }, 0 },
4218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_world }, 0 },
4219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_world }, 0 },
4220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_world }, 0 },
4221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_world }, 0 },
4222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_world }, 0 },
4223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_world }, 0 },
4224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_world }, 0 },
4225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_world }, 0 },
4226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_world }, 0 },
4227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_world }, 0 },
4228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_world }, 0 },
4229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_world }, 0 },
4230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_world }, 0 },
4231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_world }, 0 },
4232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_world }, 0 },
4233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_world }, 0 },
4234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_world }, 0 },
4235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_world }, 0 },
4236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_world }, 0 },
4237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_world }, 0 },
4238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_world }, 0 },
4239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_world }, 0 },
4240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_world }, 0 },
4241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_world }, 0 },
4242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_world }, 0 },
4243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_world }, 0 },
4244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_world }, 0 },
4245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_world }, 0 },
4246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_world }, 0 },
4247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_world }, 0 },
4248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_world }, 0 },
4249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_world }, 0 },
4250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_world }, 0 },
4251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_world }, 0 },
4252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_world }, 0 },
4253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_world }, 0 },
4254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_world }, 0 },
4255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_world }, 0 },
4256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_world }, 0 },
4257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_world }, 0 },
4258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_world }, 0 },
4259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_world }, 0 },
4260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_world }, 0 },
4261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_world }, 0 },
4262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_world }, 0 },
4263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_world }, 0 },
4264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_world }, 0 },
4265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_world }, 0 },
4266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_world }, 0 },
4267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_world }, 0 },
4268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_world }, 0 },
4269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_world }, 0 },
4270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_world }, 0 },
4271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_world }, 0 },
4272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_world }, 0 },
4273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_world }, 0 },
4274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_world }, 0 },
4275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_world }, 0 },
4276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_world }, 0 },
4277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_world }, 0 },
4278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_world }, 0 },
4279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_world }, 0 },
4280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_world }, 0 },
4281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_world }, 0 },
4282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_world }, 0 },
4283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_world }, 0 },
4284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_world }, 0 },
4285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_world }, 0 },
4286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_world }, 0 },
4287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_world }, 0 },
4288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_world }, 0 },
4289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_world }, 0 },
4290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_world }, 0 },
4291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_world }, 0 },
4292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_world }, 0 },
4293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_world }, 0 },
4294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_world }, 0 },
4295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_world }, 0 },
4296 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, 0 },
4297 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, 0 },
4298 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, 0 },
4299 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, 0 },
4300 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, 0 },
4301 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, 0 },
4302 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, 0 },
4303 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, 0 },
4304 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4305 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4306 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4307 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4308 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4309 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4310 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4311 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4313 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4314 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4315 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4316 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4317 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4318 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
4319 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
4320 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
4321 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 },
4322 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
4323 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
4324 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
4325 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
4326 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4327 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
4328 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
4329 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4330 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4331 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4332 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4333 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, 0 },
4334 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4335 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
4336 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
4337 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
4338 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
4339 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 },
4340 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4341 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4342 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4343 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4344 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_arb }, ARB_POINT_PARAMETERS },
4345 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_ext }, EXT_POINT_PARAMETERS },
4346 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax_w }, 0 },
4347 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
4348 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
4349 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
4351 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4352 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
4353 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4354 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
4355 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4356 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
4357 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4358 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
4359 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4360 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
4361 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4362 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
4363 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4364 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
4365 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
4366 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
4367 {0 /* Terminate */, { 0, 0 }, 0 },
4370 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
4371 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4372 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4373 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4374 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4375 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4376 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4377 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4378 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4379 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4380 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4381 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4382 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4383 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4384 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4385 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4386 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4387 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4388 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4389 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4390 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4391 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4392 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4393 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4394 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4395 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4396 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4397 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4398 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4399 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4400 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4401 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4402 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4403 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4404 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4405 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4406 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4407 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4408 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4409 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4410 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4411 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4412 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4413 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4414 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4415 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4416 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4417 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4418 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4419 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4420 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4421 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4422 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4423 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4424 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4425 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4426 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4427 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4428 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4429 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4430 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4431 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4432 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4433 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4434 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4435 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4436 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4437 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4438 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4439 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4440 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4441 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4442 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4443 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4444 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4445 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4446 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4447 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4448 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4449 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4450 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4451 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4452 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4453 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4454 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4455 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4456 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4457 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4458 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4459 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4460 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4461 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4462 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4463 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4464 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4465 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4466 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4467 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4468 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4469 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4470 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4471 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4472 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4473 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4474 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4475 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4476 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4477 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4478 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, ATI_ENVMAP_BUMPMAP },
4479 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4480 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4481 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4482 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4483 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
4484 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
4485 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
4486 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
4487 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
4488 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
4489 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
4490 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
4491 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
4492 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
4493 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
4494 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
4495 {0 /* Terminate */, { 0, 0 }, 0 },
4497 #undef GLINFO_LOCATION
4499 #define GLINFO_LOCATION (*gl_info)
4500 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
4502 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) {
4503 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
4504 WINED3DTEXOPCAPS_ADDSIGNED |
4505 WINED3DTEXOPCAPS_ADDSIGNED2X |
4506 WINED3DTEXOPCAPS_MODULATE |
4507 WINED3DTEXOPCAPS_MODULATE2X |
4508 WINED3DTEXOPCAPS_MODULATE4X |
4509 WINED3DTEXOPCAPS_SELECTARG1 |
4510 WINED3DTEXOPCAPS_SELECTARG2 |
4511 WINED3DTEXOPCAPS_DISABLE;
4513 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
4514 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
4515 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4516 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
4517 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
4518 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
4519 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
4520 WINED3DTEXOPCAPS_LERP |
4521 WINED3DTEXOPCAPS_SUBTRACT;
4523 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
4524 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4525 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
4526 WINED3DTEXOPCAPS_MULTIPLYADD |
4527 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
4528 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4529 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
4531 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
4532 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
4534 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
4535 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
4538 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
4539 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
4542 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4543 static void ffp_fragment_free(IWineD3DDevice *iface) {}
4545 const struct fragment_pipeline ffp_fragment_pipeline = {
4547 ffp_fragment_get_caps,
4550 ffp_fragmentstate_template
4553 static int num_handlers(APPLYSTATEFUNC *funcs) {
4555 for(i = 0; funcs[i]; i++);
4559 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4560 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4561 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4564 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4565 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4566 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4567 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
4570 void compile_state_table(struct StateEntry *StateTable,
4571 APPLYSTATEFUNC **dev_multistate_funcs,
4572 WineD3D_GL_Info *gl_info,
4573 const struct StateEntryTemplate *vertex,
4574 const struct fragment_pipeline *fragment,
4575 const struct StateEntryTemplate *misc) {
4576 unsigned int i, type, handlers;
4577 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
4578 const struct StateEntryTemplate *cur;
4579 BOOL set[STATE_HIGHEST + 1];
4581 memset(multistate_funcs, 0, sizeof(multistate_funcs));
4583 for(i = 0; i < STATE_HIGHEST + 1; i++) {
4584 StateTable[i].representative = 0;
4585 StateTable[i].apply = state_undefined;
4588 for(type = 0; type < 3; type++) {
4589 /* This switch decides the order in which the states are applied */
4591 case 0: cur = misc; break;
4592 case 1: cur = fragment->states; break;
4593 case 2: cur = vertex; break;
4594 default: cur = NULL; /* Stupid compiler */
4598 /* GL extension filtering should not prevent multiple handlers being applied from different
4601 memset(set, 0, sizeof(set));
4603 for(i = 0; cur[i].state; i++) {
4605 /* Only use the first matching state with the available extension from one template.
4607 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
4608 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
4610 * if GL_XYZ_fancy is supported, ignore the 2nd line
4612 if(set[cur[i].state]) continue;
4613 /* Skip state lines depending on unsupported extensions */
4614 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
4615 set[cur[i].state] = TRUE;
4616 /* In some cases having an extension means that nothing has to be
4617 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
4618 * supported, the texture coordinate fixup can be ignored. If the
4619 * apply function is used, mark the state set(done above) to prevent
4620 * applying later lines, but do not record anything in the state
4623 if(!cur[i].content.apply) continue;
4625 handlers = num_handlers(multistate_funcs[cur[i].state]);
4626 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
4629 StateTable[cur[i].state].apply = cur[i].content.apply;
4632 StateTable[cur[i].state].apply = multistate_apply_2;
4633 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4635 sizeof(**dev_multistate_funcs) * 2);
4636 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4637 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4640 StateTable[cur[i].state].apply = multistate_apply_3;
4641 HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
4642 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4644 sizeof(**dev_multistate_funcs) * 3);
4645 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4646 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4647 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
4650 ERR("Unexpected amount of state handlers for state %u: %u\n",
4651 cur[i].state, handlers + 1);
4654 if(StateTable[cur[i].state].representative &&
4655 StateTable[cur[i].state].representative != cur[i].content.representative) {
4656 FIXME("State %u has different representatives in different pipeline parts\n",
4659 StateTable[cur[i].state].representative = cur[i].content.representative;
4663 #undef GLINFO_LOCATION