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(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
457 if(!GL_SUPPORT(EXT_BLEND_COLOR)) {
458 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
462 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
463 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
464 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
465 checkGLcall("glBlendColor");
468 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
471 BOOL enable_ckey = FALSE;
473 IWineD3DSurfaceImpl *surf;
475 /* Find out if the texture on the first stage has a ckey set
476 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
477 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
478 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
479 * in case it finds some texture+colorkeyenable combination which needs extra care.
481 if(stateblock->textures[0] && (
482 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
483 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
484 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
486 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
487 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
488 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
489 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
490 * surface has alpha bits
492 if(fmt->alphaMask == 0x00000000) {
498 if(enable_ckey || context->last_was_ckey) {
499 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
500 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
502 context->last_was_ckey = enable_ckey;
504 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
505 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
506 glEnable(GL_ALPHA_TEST);
507 checkGLcall("glEnable GL_ALPHA_TEST");
509 glDisable(GL_ALPHA_TEST);
510 checkGLcall("glDisable GL_ALPHA_TEST");
511 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
517 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
518 glParm = GL_NOTEQUAL;
521 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
522 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
525 glAlphaFunc(glParm, ref);
526 checkGLcall("glAlphaFunc");
530 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
531 DWORD enable = 0xFFFFFFFF;
532 DWORD disable = 0x00000000;
534 if (use_vs(stateblock->wineD3DDevice)) {
535 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
536 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
537 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
538 * of that - don't do anything here and keep them disabled
540 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
541 static BOOL warned = FALSE;
543 FIXME("Clipping not supported with vertex shaders\n");
550 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
551 * of already set values
554 /* If enabling / disabling all
555 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
557 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
558 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
559 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
560 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
561 glDisable(GL_DEPTH_CLAMP_NV);
562 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
565 disable = 0xffffffff;
567 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
568 glEnable(GL_DEPTH_CLAMP_NV);
569 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
573 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
574 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
575 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
576 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
577 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
578 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
580 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
581 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
582 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
583 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
584 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
585 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
587 /** update clipping status */
589 stateblock->clip_status.ClipUnion = 0;
590 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
592 stateblock->clip_status.ClipUnion = 0;
593 stateblock->clip_status.ClipIntersection = 0;
597 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
598 int blendEquation = GL_FUNC_ADD;
599 int blendEquationAlpha = GL_FUNC_ADD;
601 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
602 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
606 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
607 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
608 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
612 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
613 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
614 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
615 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
616 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
617 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
619 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
622 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
623 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
624 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
625 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
626 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
627 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
629 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
632 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
633 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
634 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
635 checkGLcall("glBlendEquationSeparateEXT");
637 TRACE("glBlendEquation(%x)\n", blendEquation);
638 GL_EXTCALL(glBlendEquationEXT(blendEquation));
639 checkGLcall("glBlendEquation");
644 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
645 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
646 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
647 * specular color. This is wrong:
648 * Separate specular color means the specular colour is maintained separately, whereas
649 * single color means it is merged in. However in both cases they are being used to
651 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
652 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
656 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
657 * Instead, we need to setup the FinalCombiner properly.
659 * The default setup for the FinalCombiner is:
661 * <variable> <input> <mapping> <usage>
662 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
663 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
664 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
665 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
667 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
668 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
670 * That's pretty much fine as it is, except for variable B, which needs to take
671 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
672 * whether WINED3DRS_SPECULARENABLE is enabled or not.
675 TRACE("Setting specular enable state and materials\n");
676 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
677 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
678 checkGLcall("glMaterialfv");
680 if(stateblock->material.Power > GL_LIMITS(shininess)) {
681 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
682 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
683 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
684 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
685 * them, it should be safe to do so without major visual distortions.
687 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
688 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
690 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
692 checkGLcall("glMaterialf(GL_SHININESS)");
694 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
695 glEnable(GL_COLOR_SUM_EXT);
697 TRACE("Specular colors cannot be enabled in this version of opengl\n");
699 checkGLcall("glEnable(GL_COLOR_SUM)");
701 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
702 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
703 checkGLcall("glFinalCombinerInputNV()");
706 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
708 /* for the case of enabled lighting: */
709 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
710 checkGLcall("glMaterialfv");
712 /* for the case of disabled lighting: */
713 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
714 glDisable(GL_COLOR_SUM_EXT);
716 TRACE("Specular colors cannot be disabled in this version of opengl\n");
718 checkGLcall("glDisable(GL_COLOR_SUM)");
720 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
721 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
722 checkGLcall("glFinalCombinerInputNV()");
726 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
727 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
728 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
729 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
730 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
731 stateblock->material.Specular.b, stateblock->material.Specular.a);
732 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
733 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
735 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
736 checkGLcall("glMaterialfv(GL_AMBIENT)");
737 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
738 checkGLcall("glMaterialfv(GL_DIFFUSE)");
739 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
740 checkGLcall("glMaterialfv(GL_EMISSION)");
743 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
746 /* Note the texture color applies to all textures whereas
747 * GL_TEXTURE_ENV_COLOR applies to active only
750 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
752 if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
753 /* And now the default texture color as well */
754 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
755 /* Note the WINED3DRS value applies to all textures, but GL has one
756 * per texture, so apply it now ready to be used!
758 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
759 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
760 checkGLcall("glActiveTextureARB");
762 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
765 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
766 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
769 GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
774 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
775 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
776 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
777 GL_EXTCALL(glActiveStencilFaceEXT(face));
778 checkGLcall("glActiveStencilFaceEXT(...)");
779 glStencilFunc(func, ref, mask);
780 checkGLcall("glStencilFunc(...)");
781 glStencilOp(stencilFail, depthFail, stencilPass);
782 checkGLcall("glStencilOp(...)");
786 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
787 DWORD onesided_enable = FALSE;
788 DWORD twosided_enable = FALSE;
789 GLint func = GL_ALWAYS;
790 GLint func_ccw = GL_ALWAYS;
793 GLint stencilFail = GL_KEEP;
794 GLint depthFail = GL_KEEP;
795 GLint stencilPass = GL_KEEP;
796 GLint stencilFail_ccw = GL_KEEP;
797 GLint depthFail_ccw = GL_KEEP;
798 GLint stencilPass_ccw = GL_KEEP;
800 /* No stencil test without a stencil buffer */
801 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
802 glDisable(GL_STENCIL_TEST);
803 checkGLcall("glDisable GL_STENCIL_TEST");
807 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
808 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
809 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
811 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
812 func_ccw = GL_ALWAYS;
813 ref = stateblock->renderState[WINED3DRS_STENCILREF];
814 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
815 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
816 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
817 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
818 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
819 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
820 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
822 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
823 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
824 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
825 onesided_enable, twosided_enable, ref, mask,
826 func, stencilFail, depthFail, stencilPass,
827 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
829 if (twosided_enable && onesided_enable) {
830 glEnable(GL_STENCIL_TEST);
831 checkGLcall("glEnable GL_STENCIL_TEST");
833 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
834 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
835 * which has an effect on the code below too. If we apply the front face
836 * afterwards, we are sure that the active stencil face is set to front,
837 * and other stencil functions which do not use two sided stencil do not have
840 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
841 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
842 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
843 stencilFail, depthFail, stencilPass);
844 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
845 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
846 checkGLcall("glStencilFuncSeparateATI(...)");
847 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
848 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
849 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
850 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
852 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
854 } else if(onesided_enable) {
855 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
856 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
857 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
860 /* This code disables the ATI extension as well, since the standard stencil functions are equal
861 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
863 glEnable(GL_STENCIL_TEST);
864 checkGLcall("glEnable GL_STENCIL_TEST");
865 glStencilFunc(func, ref, mask);
866 checkGLcall("glStencilFunc(...)");
867 glStencilOp(stencilFail, depthFail, stencilPass);
868 checkGLcall("glStencilOp(...)");
870 glDisable(GL_STENCIL_TEST);
871 checkGLcall("glDisable GL_STENCIL_TEST");
875 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
878 if(stateblock->wineD3DDevice->stencilBufferTarget) {
879 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
884 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
885 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
886 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
888 checkGLcall("glStencilMask");
889 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
890 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
895 checkGLcall("glStencilMask");
898 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
899 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
900 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
901 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
902 float fogstart, fogend;
910 /* No fog? Disable it, and we're done :-) */
912 checkGLcall("glDisable GL_FOG");
913 if( use_ps(stateblock->wineD3DDevice)
914 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
915 /* disable fog in the pixel shader
916 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
917 * -1/(e-s) and e/(e-s) respectively.
919 glFogf(GL_FOG_START, 0.0f);
920 checkGLcall("glFogf(GL_FOG_START, fogstart)");
921 glFogf(GL_FOG_END, 1.0f);
922 checkGLcall("glFogf(GL_FOG_END, fogend)");
927 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
928 fogstart = tmpvalue.f;
929 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
934 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
935 * It can use the Z value of the vertex, or the alpha component of the specular color.
936 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
937 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
938 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
940 * FOGTABLEMODE != NONE:
941 * The Z value is used, with the equation specified, no matter what vertex type.
943 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
944 * Per vertex fog is calculated using the specified fog equation and the parameters
946 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
947 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
948 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
951 * Rules for vertex fog with shaders:
953 * When mixing fixed function functionality with the programmable pipeline, D3D expects
954 * the fog computation to happen during transformation while openGL expects it to happen
955 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
956 * the pixel shader while openGL always expects the pixel shader to handle the blending.
957 * To solve this problem, WineD3D does:
958 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
960 * and 2) disables the fog computation (in either the fixed function or programmable
961 * rasterizer) if using a vertex program.
964 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
969 if( !use_vs(stateblock->wineD3DDevice)
970 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
971 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
975 if (use_vs(stateblock->wineD3DDevice)
976 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
977 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
978 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
982 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
983 glFogi(GL_FOG_MODE, GL_LINEAR);
984 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
989 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
990 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
991 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
992 context->fog_coord = FALSE;
994 context->last_was_foggy_shader = TRUE;
996 else if( use_ps(stateblock->wineD3DDevice) ) {
997 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
998 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
1000 WINED3DFOGMODE mode;
1001 context->last_was_foggy_shader = FALSE;
1003 /* If both fogmodes are set use the table fog mode */
1004 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1005 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
1007 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1010 case WINED3DFOG_EXP:
1011 case WINED3DFOG_EXP2:
1012 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1017 case WINED3DFOG_LINEAR:
1018 fogstart = -1.0f/(fogend-fogstart);
1019 fogend *= -fogstart;
1022 case WINED3DFOG_NONE:
1023 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1027 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1030 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1031 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1032 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1033 context->fog_coord = FALSE;
1036 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1037 * the system will apply only pixel(=table) fog effects."
1039 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1040 glHint(GL_FOG_HINT, GL_FASTEST);
1041 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1042 context->last_was_foggy_shader = FALSE;
1044 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1045 /* If processed vertices are used, fall through to the NONE case */
1046 case WINED3DFOG_EXP: {
1047 if(!context->last_was_rhw) {
1048 glFogi(GL_FOG_MODE, GL_EXP);
1049 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1050 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1051 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1052 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1053 context->fog_coord = FALSE;
1058 case WINED3DFOG_EXP2: {
1059 if(!context->last_was_rhw) {
1060 glFogi(GL_FOG_MODE, GL_EXP2);
1061 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1062 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1063 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1064 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1065 context->fog_coord = FALSE;
1070 case WINED3DFOG_LINEAR: {
1071 if(!context->last_was_rhw) {
1072 glFogi(GL_FOG_MODE, GL_LINEAR);
1073 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1074 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1075 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1076 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1077 context->fog_coord = FALSE;
1082 case WINED3DFOG_NONE: {
1083 /* Both are none? According to msdn the alpha channel of the specular
1084 * color contains a fog factor. Set it in drawStridedSlow.
1085 * Same happens with Vertexfog on transformed vertices
1087 if(GL_SUPPORT(EXT_FOG_COORD)) {
1088 if(context->fog_coord == FALSE) {
1089 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1090 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1091 context->fog_coord = TRUE;
1093 glFogi(GL_FOG_MODE, GL_LINEAR);
1094 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1098 /* Disable GL fog, handle this in software in drawStridedSlow */
1103 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1106 glHint(GL_FOG_HINT, GL_NICEST);
1107 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1108 context->last_was_foggy_shader = FALSE;
1110 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1111 case WINED3DFOG_EXP:
1112 glFogi(GL_FOG_MODE, GL_EXP);
1113 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1114 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1115 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1116 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1117 context->fog_coord = FALSE;
1121 case WINED3DFOG_EXP2:
1122 glFogi(GL_FOG_MODE, GL_EXP2);
1123 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1124 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1125 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1126 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1127 context->fog_coord = FALSE;
1131 case WINED3DFOG_LINEAR:
1132 glFogi(GL_FOG_MODE, GL_LINEAR);
1133 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1134 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1135 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1136 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1137 context->fog_coord = FALSE;
1141 case WINED3DFOG_NONE: /* Won't happen */
1143 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1149 checkGLcall("glEnable GL_FOG");
1151 if(fogstart != fogend)
1153 glFogfv(GL_FOG_START, &fogstart);
1154 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1155 TRACE("Fog Start == %f\n", fogstart);
1157 glFogfv(GL_FOG_END, &fogend);
1158 checkGLcall("glFogf(GL_FOG_END, fogend)");
1159 TRACE("Fog End == %f\n", fogend);
1163 glFogf(GL_FOG_START, -1.0 / 0.0);
1164 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1165 TRACE("Fog Start == %f\n", fogstart);
1167 glFogf(GL_FOG_END, 0.0);
1168 checkGLcall("glFogf(GL_FOG_END, fogend)");
1169 TRACE("Fog End == %f\n", fogend);
1173 checkGLcall("glDisable GL_FOG");
1174 if( use_ps(stateblock->wineD3DDevice) ) {
1175 /* disable fog in the pixel shader
1176 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1177 * -1/(e-s) and e/(e-s) respectively.
1179 glFogf(GL_FOG_START, 0.0f);
1180 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1181 glFogf(GL_FOG_END, 1.0f);
1182 checkGLcall("glFogf(GL_FOG_END, fogend)");
1187 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1188 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1189 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1190 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1191 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1193 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1196 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1197 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1198 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1203 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1205 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1206 glFogfv(GL_FOG_COLOR, &col[0]);
1207 checkGLcall("glFog GL_FOG_COLOR");
1210 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1215 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1216 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1217 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1220 /* TODO: Merge with primitive type + init_materials()!! */
1221 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1222 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1224 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1225 BOOL isDiffuseSupplied;
1227 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1228 * The vertex declaration will call this function if the fixed function pipeline is used.
1231 if(isStateDirty(context, STATE_VDECL)) {
1235 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1237 context->num_untracked_materials = 0;
1238 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1239 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1240 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1241 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1242 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1243 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1245 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1246 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1247 Parm = GL_AMBIENT_AND_DIFFUSE;
1251 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1252 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1253 context->num_untracked_materials++;
1255 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1256 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1257 context->num_untracked_materials++;
1259 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1261 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1262 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1263 context->num_untracked_materials++;
1265 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1266 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1267 context->num_untracked_materials++;
1269 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1271 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1272 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1273 context->num_untracked_materials++;
1275 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1280 /* Nothing changed, return. */
1281 if (Parm == context->tracking_parm) return;
1284 glDisable(GL_COLOR_MATERIAL);
1285 checkGLcall("glDisable GL_COLOR_MATERIAL");
1287 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1288 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1289 glEnable(GL_COLOR_MATERIAL);
1290 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1293 /* Apparently calls to glMaterialfv are ignored for properties we're
1294 * tracking with glColorMaterial, so apply those here. */
1295 switch (context->tracking_parm) {
1296 case GL_AMBIENT_AND_DIFFUSE:
1297 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1298 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1299 checkGLcall("glMaterialfv");
1303 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1304 checkGLcall("glMaterialfv");
1308 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1309 checkGLcall("glMaterialfv");
1313 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1314 checkGLcall("glMaterialfv");
1318 /* Only change material color if specular is enabled, otherwise it is set to black */
1319 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1320 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1321 checkGLcall("glMaterialfv");
1323 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1324 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1325 checkGLcall("glMaterialfv");
1330 context->tracking_parm = Parm;
1333 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1336 WINED3DLINEPATTERN lp;
1338 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1340 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1342 if (tmppattern.lp.wRepeatFactor) {
1343 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1344 checkGLcall("glLineStipple(repeat, linepattern)");
1345 glEnable(GL_LINE_STIPPLE);
1346 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1348 glDisable(GL_LINE_STIPPLE);
1349 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1353 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1359 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1360 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1361 TRACE("ZBias value %f\n", tmpvalue.f);
1362 glPolygonOffset(0, -tmpvalue.f);
1363 checkGLcall("glPolygonOffset(0, -Value)");
1364 glEnable(GL_POLYGON_OFFSET_FILL);
1365 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1366 glEnable(GL_POLYGON_OFFSET_LINE);
1367 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1368 glEnable(GL_POLYGON_OFFSET_POINT);
1369 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1371 glDisable(GL_POLYGON_OFFSET_FILL);
1372 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1373 glDisable(GL_POLYGON_OFFSET_LINE);
1374 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1375 glDisable(GL_POLYGON_OFFSET_POINT);
1376 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1381 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1382 if(isStateDirty(context, STATE_VDECL)) {
1385 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1386 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1387 * by zero and is not properly defined in opengl, so avoid it
1389 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1390 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1391 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1392 glEnable(GL_NORMALIZE);
1393 checkGLcall("glEnable(GL_NORMALIZE);");
1395 glDisable(GL_NORMALIZE);
1396 checkGLcall("glDisable(GL_NORMALIZE);");
1400 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1406 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1407 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1408 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1409 checkGLcall("glPointParameterfARB(...)");
1411 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1412 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1413 checkGLcall("glPointParameterfEXT(...)");
1414 } else if(tmpvalue.f != 1.0) {
1415 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1419 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1425 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1426 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1427 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1428 checkGLcall("glPointParameterfARB(...)");
1430 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1431 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1432 checkGLcall("glPointParameterfEXT(...)");
1433 } else if(tmpvalue.f != 64.0) {
1434 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1438 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1439 /* TODO: Group this with the viewport */
1441 * POINTSCALEENABLE controls how point size value is treated. If set to
1442 * true, the point size is scaled with respect to height of viewport.
1443 * When set to false point size is in pixels.
1446 /* Default values */
1447 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1451 } pointSize, A, B, C;
1453 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1454 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1455 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1456 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1458 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1459 GLfloat scaleFactor;
1460 float h = stateblock->viewport.Height;
1462 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1464 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1465 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1466 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1467 * are less than 1.0f. scale_factor = 1.0f / point_size.
1469 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1470 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1471 * is 1.0, but then accepts points below that and draws too small points
1473 pointSize.f = GL_LIMITS(pointsizemin);
1474 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1475 /* gl already scales the input to glPointSize,
1476 * d3d scales the result after the point size scale.
1477 * If the point size is bigger than the max size, use the
1478 * scaling to scale it bigger, and set the gl point size to max
1480 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1481 TRACE("scale: %f\n", scaleFactor);
1482 pointSize.f = GL_LIMITS(pointsize);
1486 scaleFactor = pow(h * scaleFactor, 2);
1488 att[0] = A.f / scaleFactor;
1489 att[1] = B.f / scaleFactor;
1490 att[2] = C.f / scaleFactor;
1493 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1494 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1495 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1497 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1498 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1499 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1500 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1501 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1504 glPointSize(pointSize.f);
1505 checkGLcall("glPointSize(...);");
1508 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1509 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1511 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1512 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1513 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1514 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1515 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1516 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1517 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1518 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1519 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1520 checkGLcall("glColorMask(...)");
1522 /* depends on WINED3DRS_COLORWRITEENABLE. */
1523 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1524 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1525 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1526 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1527 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1528 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1529 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1533 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1534 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1535 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1536 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1538 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1539 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1543 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1544 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1545 TRACE("Last Pixel Drawing Enabled\n");
1547 static BOOL first = TRUE;
1549 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1552 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1557 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1558 /* TODO: NV_POINT_SPRITE */
1559 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1560 TRACE("Point sprites not supported\n");
1564 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1565 glEnable(GL_POINT_SPRITE_ARB);
1566 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1568 glDisable(GL_POINT_SPRITE_ARB);
1569 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1573 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1575 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1576 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1577 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1578 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1580 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1583 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1584 stateblock->renderState[WINED3DRS_WRAP1] ||
1585 stateblock->renderState[WINED3DRS_WRAP2] ||
1586 stateblock->renderState[WINED3DRS_WRAP3] ||
1587 stateblock->renderState[WINED3DRS_WRAP4] ||
1588 stateblock->renderState[WINED3DRS_WRAP5] ||
1589 stateblock->renderState[WINED3DRS_WRAP6] ||
1590 stateblock->renderState[WINED3DRS_WRAP7] ||
1591 stateblock->renderState[WINED3DRS_WRAP8] ||
1592 stateblock->renderState[WINED3DRS_WRAP9] ||
1593 stateblock->renderState[WINED3DRS_WRAP10] ||
1594 stateblock->renderState[WINED3DRS_WRAP11] ||
1595 stateblock->renderState[WINED3DRS_WRAP12] ||
1596 stateblock->renderState[WINED3DRS_WRAP13] ||
1597 stateblock->renderState[WINED3DRS_WRAP14] ||
1598 stateblock->renderState[WINED3DRS_WRAP15] ) {
1599 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1603 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1604 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1605 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1606 glEnable(GL_MULTISAMPLE_ARB);
1607 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1609 glDisable(GL_MULTISAMPLE_ARB);
1610 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1613 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1614 WARN("Multisample antialiasing not supported by gl\n");
1619 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1620 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1621 glEnable(GL_SCISSOR_TEST);
1622 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1624 glDisable(GL_SCISSOR_TEST);
1625 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1629 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1635 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1636 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1637 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1638 glEnable(GL_POLYGON_OFFSET_FILL);
1639 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1640 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1641 checkGLcall("glPolygonOffset(...)");
1643 glDisable(GL_POLYGON_OFFSET_FILL);
1644 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1648 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1649 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1650 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1651 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1653 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1654 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1658 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1660 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1661 FIXME(" Stippled Alpha not supported yet.\n");
1664 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1666 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1667 FIXME(" Antialias not supported yet.\n");
1670 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1672 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1673 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1676 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1678 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1679 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1682 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1690 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1692 static BOOL displayed = FALSE;
1694 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1696 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1702 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1704 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1705 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1708 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1710 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1711 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1714 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1716 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1717 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1720 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1721 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1722 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1726 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1727 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1728 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1732 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1733 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1734 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1738 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1739 if(stateblock->renderState[WINED3DRS_ROP2]) {
1740 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1744 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1745 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1746 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1750 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1751 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1752 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1756 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1757 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1758 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1762 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1763 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1764 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1768 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1769 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1770 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1774 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1775 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1776 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1780 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1781 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1782 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1786 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1787 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1788 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1792 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1793 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1794 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1798 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1799 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1800 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1804 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1805 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1806 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1810 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1811 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1812 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1813 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1815 TRACE("Setting color op for stage %d\n", stage);
1817 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1818 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1819 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1823 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1825 if (mapped_stage != -1) {
1826 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1827 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1828 FIXME("Attempt to enable unsupported stage!\n");
1831 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1832 checkGLcall("glActiveTextureARB");
1833 } else if (stage > 0) {
1834 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1839 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1840 if(stateblock->lowest_disabled_stage > 0) {
1841 glEnable(GL_REGISTER_COMBINERS_NV);
1842 GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, stateblock->lowest_disabled_stage));
1844 glDisable(GL_REGISTER_COMBINERS_NV);
1847 if(stage >= stateblock->lowest_disabled_stage) {
1848 TRACE("Stage disabled\n");
1849 if (mapped_stage != -1) {
1850 /* Disable everything here */
1851 glDisable(GL_TEXTURE_2D);
1852 checkGLcall("glDisable(GL_TEXTURE_2D)");
1853 glDisable(GL_TEXTURE_3D);
1854 checkGLcall("glDisable(GL_TEXTURE_3D)");
1855 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1856 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1857 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1859 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1860 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1861 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1863 if(GL_SUPPORT(NV_TEXTURE_SHADER2) && mapped_stage < GL_LIMITS(textures)) {
1864 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
1871 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1872 * if the sampler for this stage is dirty
1874 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1875 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
1878 /* Set the texture combiners */
1879 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1880 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1881 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1882 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1883 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1884 stateblock->textureState[stage][WINED3DTSS_COLORARG0],
1886 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
1888 /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
1889 * thus the texture shader may have to be updated
1891 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1892 BOOL usesBump = (stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAPLUMINANCE ||
1893 stateblock->textureState[stage][WINED3DTSS_COLOROP] == WINED3DTOP_BUMPENVMAP) ? TRUE : FALSE;
1894 BOOL usedBump = (context->texShaderBumpMap & 1 << (stage + 1)) ? TRUE : FALSE;
1895 if(usesBump != usedBump) {
1896 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage + 1));
1897 checkGLcall("glActiveTextureARB");
1898 texture_activate_dimensions(stage + 1, stateblock, context);
1899 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1900 checkGLcall("glActiveTextureARB");
1904 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1905 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1906 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1907 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1908 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1912 static void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1913 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1914 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1915 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1916 DWORD op, arg1, arg2, arg0;
1918 TRACE("Setting alpha op for stage %d\n", stage);
1919 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
1920 if (mapped_stage != -1) {
1921 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1922 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1923 FIXME("Attempt to enable unsupported stage!\n");
1926 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1927 checkGLcall("glActiveTextureARB");
1928 } else if (stage > 0) {
1929 /* We can't do anything here */
1930 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1935 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1936 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1937 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1938 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1940 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1941 stateblock->textures[0] &&
1942 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
1943 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1945 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1946 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1948 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1949 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1950 * cannot remove the texture's alpha channel entirely.
1952 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1953 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
1954 * draw things like translucent text and perform other blending effects.
1956 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
1957 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
1958 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
1959 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
1960 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
1961 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
1962 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
1963 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
1965 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1967 if(op == WINED3DTOP_DISABLE) {
1968 arg1 = WINED3DTA_TEXTURE;
1969 op = WINED3DTOP_SELECTARG1;
1971 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
1972 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1973 arg2 = WINED3DTA_TEXTURE;
1974 op = WINED3DTOP_MODULATE;
1976 else arg1 = WINED3DTA_TEXTURE;
1978 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
1979 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1980 arg1 = WINED3DTA_TEXTURE;
1981 op = WINED3DTOP_MODULATE;
1983 else arg2 = WINED3DTA_TEXTURE;
1988 TRACE("Setting alpha op for stage %d\n", stage);
1989 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1990 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1991 op, arg1, arg2, arg0,
1993 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
1995 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1996 op, arg1, arg2, arg0);
2000 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2001 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
2002 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2005 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2006 if(use_vs(stateblock->wineD3DDevice) ||
2007 isStateDirty(context, STATE_VDECL)) {
2008 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
2012 if (mapped_stage == -1) return;
2014 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2015 if(mapped_stage >= GL_LIMITS(textures)) {
2018 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2019 checkGLcall("glActiveTextureARB");
2020 } else if (mapped_stage > 0) {
2021 /* We can't do anything here */
2022 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2025 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
2027 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
2028 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
2030 context->last_was_rhw,
2031 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
2032 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
2033 WINED3DDECLTYPE_UNUSED);
2035 /* The sampler applying function calls us if this changes */
2036 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
2038 FIXME("Non-power2 texture being used with generated texture coords\n");
2040 TRACE("Non power two matrix multiply fixup\n");
2041 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
2045 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
2048 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
2049 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2050 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2054 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2055 UINT *offset = stateblock->streamOffset;
2056 unsigned int mapped_stage = 0;
2057 unsigned int textureNo = 0;
2059 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2060 /* Abort if we don't support the extension. */
2061 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2062 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2066 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2067 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2069 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2070 if (mapped_stage == -1) continue;
2072 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2073 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2074 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2076 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2077 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2078 checkGLcall("glBindBufferARB");
2079 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2082 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2083 checkGLcall("glClientActiveTextureARB");
2085 /* The coords to supply depend completely on the fvf / vertex shader */
2087 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2088 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2089 sd->u.s.texCoords[coordIdx].dwStride,
2090 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2091 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2093 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2096 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2097 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2098 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2099 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2104 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2105 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2106 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2108 if (mapped_stage == -1) {
2109 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2113 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2114 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2117 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2118 checkGLcall("glActiveTextureARB");
2119 } else if (stage > 0) {
2120 /* We can't do anything here */
2121 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2125 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2127 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2128 * one flag, you can still specify an index value, which the system uses to
2129 * determine the texture wrapping mode.
2130 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2131 * means use the vertex position (camera-space) as the input texture coordinates
2132 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2133 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2134 * to the TEXCOORDINDEX value
2138 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2140 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2141 case WINED3DTSS_TCI_PASSTHRU:
2142 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2143 glDisable(GL_TEXTURE_GEN_S);
2144 glDisable(GL_TEXTURE_GEN_T);
2145 glDisable(GL_TEXTURE_GEN_R);
2146 glDisable(GL_TEXTURE_GEN_Q);
2147 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2150 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2151 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2152 * as the input texture coordinates for this stage's texture transformation. This
2153 * equates roughly to EYE_LINEAR
2156 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2157 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2158 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2159 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2160 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2162 glMatrixMode(GL_MODELVIEW);
2165 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2166 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2167 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2168 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2171 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2172 glEnable(GL_TEXTURE_GEN_S);
2173 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2174 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2175 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2176 glEnable(GL_TEXTURE_GEN_T);
2177 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2178 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2179 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2180 glEnable(GL_TEXTURE_GEN_R);
2181 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2182 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2183 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2187 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2189 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2190 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2191 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2192 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2193 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2194 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2196 glMatrixMode(GL_MODELVIEW);
2199 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2200 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2201 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2202 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2205 glEnable(GL_TEXTURE_GEN_S);
2206 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2207 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2208 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2209 glEnable(GL_TEXTURE_GEN_T);
2210 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2211 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2212 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2213 glEnable(GL_TEXTURE_GEN_R);
2214 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2215 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2216 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2221 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2223 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2224 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2225 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2226 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2227 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2228 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2230 glMatrixMode(GL_MODELVIEW);
2233 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2234 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2235 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2236 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2239 glEnable(GL_TEXTURE_GEN_S);
2240 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2241 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2242 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2243 glEnable(GL_TEXTURE_GEN_T);
2244 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2245 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2246 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2247 glEnable(GL_TEXTURE_GEN_R);
2248 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2249 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2250 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2255 /* Unhandled types: */
2258 /* ? disable GL_TEXTURE_GEN_n ? */
2259 glDisable(GL_TEXTURE_GEN_S);
2260 glDisable(GL_TEXTURE_GEN_T);
2261 glDisable(GL_TEXTURE_GEN_R);
2262 glDisable(GL_TEXTURE_GEN_Q);
2263 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2267 /* Update the texture matrix */
2268 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2269 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2272 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2273 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2274 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2275 * and do all the things linked to it
2276 * TODO: Tidy that up to reload only the arrays of the changed unit
2278 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2280 unloadTexCoords(stateblock);
2281 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2285 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2286 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2288 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2289 * has an update pending
2291 if(isStateDirty(context, STATE_VDECL) ||
2292 isStateDirty(context, STATE_PIXELSHADER)) {
2296 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2299 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2300 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2306 if(stateblock->pixelShader && stage != 0 &&
2307 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2308 /* The pixel shader has to know the luminance scale. Do a constants update if it
2309 * isn't scheduled anyway
2311 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2312 !isStateDirty(context, STATE_PIXELSHADER)) {
2313 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2317 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2318 if(tmpvalue.f != 0.0) {
2319 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2323 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2324 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2330 if(stateblock->pixelShader && stage != 0 &&
2331 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2332 /* The pixel shader has to know the luminance offset. Do a constants update if it
2333 * isn't scheduled anyway
2335 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2336 !isStateDirty(context, STATE_PIXELSHADER)) {
2337 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2341 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2342 if(tmpvalue.f != 0.0) {
2343 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2347 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2348 BOOL texIsPow2 = FALSE;
2349 DWORD sampler = state - STATE_SAMPLER(0);
2351 if(!stateblock->textures[sampler]) return;
2352 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2353 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2354 * scaling is reapplied or removed, the texture matrix has to be reapplied
2356 * The mapped stage is alrady active because the sampler() function below, which is part of the
2359 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2360 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2361 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2362 if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0 ||
2363 ((IWineD3DTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[5] != 1.0 ) {
2366 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2367 if(((IWineD3DCubeTextureImpl *) stateblock->textures[sampler])->baseTexture.pow2Matrix[0] != 1.0) {
2372 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2373 context->lastWasPow2Texture[sampler] = texIsPow2;
2374 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2379 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2380 DWORD sampler = state - STATE_SAMPLER(0);
2381 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2387 TRACE("Sampler: %d\n", sampler);
2388 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2389 * only has to bind textures and set the per texture states
2392 if (mapped_stage == -1) {
2393 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2397 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2398 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2401 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2402 checkGLcall("glActiveTextureARB");
2403 } else if (sampler > 0) {
2404 /* We can't do anything here */
2405 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2409 if(stateblock->textures[sampler]) {
2410 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
2411 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2413 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2414 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2415 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2416 GL_TEXTURE_LOD_BIAS_EXT,
2418 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
2421 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2422 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2423 /* Using a pixel shader? Verify the sampler types */
2425 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2426 * dimensions because the shader knows from which texture type to sample from. For the sake of
2427 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2428 * dimensions. This should make wrong sampling sources visible :-)
2430 glEnable(stateblock->textureDimensions[sampler]);
2431 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2432 } else if(sampler < stateblock->lowest_disabled_stage) {
2433 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2434 /* If color keying is enabled update the alpha test, it depends on the existence
2435 * of a color key in stage 0
2437 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2440 } else if(mapped_stage < GL_LIMITS(textures)) {
2441 if(sampler < stateblock->lowest_disabled_stage) {
2442 /* TODO: What should I do with pixel shaders here ??? */
2443 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2444 /* If color keying is enabled update the alpha test, it depends on the existence
2445 * of a color key in stage 0
2447 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2449 } /* Otherwise tex_colorop disables the stage */
2450 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2451 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2455 static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2456 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2457 BOOL use_pshader = use_ps(device);
2458 BOOL use_vshader = use_vs(device);
2459 BOOL update_fog = FALSE;
2463 if(!context->last_was_pshader) {
2464 /* Former draw without a pixel shader, some samplers
2465 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2466 * make sure to enable them
2468 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2469 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2470 sampler(STATE_SAMPLER(i), stateblock, context);
2475 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2476 * if a different texture was bound. I don't have to do anything.
2480 /* Compile and bind the shader */
2481 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2483 /* Disabled the pixel shader - color ops weren't applied
2484 * while it was enabled, so re-apply them.
2486 for(i=0; i < MAX_TEXTURES; i++) {
2487 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2488 tex_colorop(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;
2526 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
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");
2539 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2540 /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
2541 * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
2542 * map offsetting is done in the stage reading the bump mapped texture, and the perturbation
2543 * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
2544 * for stage + 1. Keep the nvrc tex unit mapping in mind too
2546 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage + 1];
2548 if(mapped_stage < GL_LIMITS(textures)) {
2549 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2550 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage))");
2552 /* We can't just pass a pointer to the stateblock to GL due to the different matrix
2553 * format(column major vs row major)
2555 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2556 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2557 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2558 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2559 glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *) mat);
2560 checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)");
2565 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2566 /* This function is called by transform_view below if the view matrix was changed too
2568 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2569 * does not always update the world matrix, only on a switch between transformed
2570 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
2571 * draw, but that should be rather rare and cheaper in total.
2573 glMatrixMode(GL_MODELVIEW);
2574 checkGLcall("glMatrixMode");
2576 if(context->last_was_rhw) {
2578 checkGLcall("glLoadIdentity()");
2580 /* In the general case, the view matrix is the identity matrix */
2581 if (stateblock->wineD3DDevice->view_ident) {
2582 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2583 checkGLcall("glLoadMatrixf");
2585 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2586 checkGLcall("glLoadMatrixf");
2587 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2588 checkGLcall("glMultMatrixf");
2593 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2594 UINT index = state - STATE_CLIPPLANE(0);
2596 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2600 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2601 glMatrixMode(GL_MODELVIEW);
2603 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2605 TRACE("Clipplane [%f,%f,%f,%f]\n",
2606 stateblock->clipplane[index][0],
2607 stateblock->clipplane[index][1],
2608 stateblock->clipplane[index][2],
2609 stateblock->clipplane[index][3]);
2610 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2611 checkGLcall("glClipPlane");
2616 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2617 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2619 TRACE("Setting world matrix %d\n", matrix);
2621 if(matrix >= GL_LIMITS(blends)) {
2622 WARN("Unsupported blend matrix set\n");
2624 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2628 /* GL_MODELVIEW0_ARB: 0x1700
2629 * GL_MODELVIEW1_ARB: 0x0x850a
2630 * GL_MODELVIEW2_ARB: 0x8722
2631 * GL_MODELVIEW3_ARB: 0x8723
2633 * GL_MODELVIEW31_ARB: 0x873F
2635 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2636 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2638 glMatrixMode(glMat);
2639 checkGLcall("glMatrixMode(glMat)");
2641 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2642 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2644 if(stateblock->wineD3DDevice->view_ident) {
2645 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2646 checkGLcall("glLoadMatrixf")
2648 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2649 checkGLcall("glLoadMatrixf")
2650 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2651 checkGLcall("glMultMatrixf")
2655 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2656 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2659 case WINED3DVBF_1WEIGHTS:
2660 case WINED3DVBF_2WEIGHTS:
2661 case WINED3DVBF_3WEIGHTS:
2662 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2663 glEnable(GL_VERTEX_BLEND_ARB);
2664 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2666 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2667 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2669 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2671 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2673 for(i = 1; i < GL_LIMITS(blends); i++) {
2674 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2675 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2678 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2681 static BOOL once = FALSE;
2684 /* TODO: Implement vertex blending in drawStridedSlow */
2685 FIXME("Vertex blending enabled, but not supported by hardware\n");
2690 case WINED3DVBF_DISABLE:
2691 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2692 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2693 glDisable(GL_VERTEX_BLEND_ARB);
2694 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2696 TRACE("Vertex blending disabled\n");
2700 case WINED3DVBF_TWEENING:
2701 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2702 * vertex weights in the vertices?
2703 * For now we don't report that as supported, so a warn should suffice
2705 WARN("Tweening not supported yet\n");
2710 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2713 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2714 * NOTE: We have to reset the positions even if the light/plane is not currently
2715 * enabled, since the call to enable it will not reset the position.
2716 * NOTE2: Apparently texture transforms do NOT need reapplying
2719 PLIGHTINFOEL *light = NULL;
2721 glMatrixMode(GL_MODELVIEW);
2722 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2723 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2724 checkGLcall("glLoadMatrixf(...)");
2726 /* Reset lights. TODO: Call light apply func */
2727 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2728 light = stateblock->activeLights[k];
2729 if(!light) continue;
2730 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2731 checkGLcall("glLightfv posn");
2732 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2733 checkGLcall("glLightfv dirn");
2736 /* Reset Clipping Planes */
2737 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2738 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2739 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2743 if(context->last_was_rhw) {
2745 checkGLcall("glLoadIdentity()");
2746 /* No need to update the world matrix, the identity is fine */
2750 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2751 * No need to do it here if the state is scheduled for update.
2753 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2754 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2757 /* Avoid looping over a number of matrices if the app never used the functionality */
2758 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2759 for(k = 1; k < GL_LIMITS(blends); k++) {
2760 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2761 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2767 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2768 glMatrixMode(GL_PROJECTION);
2769 checkGLcall("glMatrixMode(GL_PROJECTION)");
2771 checkGLcall("glLoadIdentity");
2773 if(context->last_was_rhw) {
2774 double X, Y, height, width, minZ, maxZ;
2776 X = stateblock->viewport.X;
2777 Y = stateblock->viewport.Y;
2778 height = stateblock->viewport.Height;
2779 width = stateblock->viewport.Width;
2780 minZ = stateblock->viewport.MinZ;
2781 maxZ = stateblock->viewport.MaxZ;
2783 if(!stateblock->wineD3DDevice->untransformed) {
2784 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2785 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2786 * suppress depth clipping. This can be done because it is an orthogonal projection and
2787 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2788 * Persia 3D need this.
2790 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2791 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2792 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2795 * Also note that this breaks z comparison against z values filled in with clear,
2796 * but no app depending on that and disabled clipping has been found yet. Comparing
2797 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2800 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2801 * but this would break Z buffer operation. Raising the range to something less than
2802 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2805 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2806 if(stateblock->wineD3DDevice->render_offscreen) {
2807 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2809 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2812 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2813 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2814 * unmodified to opengl.
2816 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2817 * replacement shader.
2819 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2820 if(stateblock->wineD3DDevice->render_offscreen) {
2821 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2823 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2826 checkGLcall("glOrtho");
2828 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2829 glTranslatef(0.5, 0.5, 0);
2830 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2831 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2832 * render everything upside down when rendering offscreen. */
2833 if (stateblock->wineD3DDevice->render_offscreen) {
2834 glScalef(1.0, -1.0, 1.0);
2835 checkGLcall("glScalef");
2838 /* The rule is that the window coordinate 0 does not correspond to the
2839 beginning of the first pixel, but the center of the first pixel.
2840 As a consequence if you want to correctly draw one line exactly from
2841 the left to the right end of the viewport (with all matrices set to
2842 be identity), the x coords of both ends of the line would be not
2843 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2846 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2847 divide by the Width/Height, so we need the half range(1.0) to translate by
2850 The other fun is that d3d's output z range after the transformation is [0;1],
2851 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2852 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2853 of Z buffer precision and the clear values do not match in the z test. Thus scale
2854 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2856 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2857 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2858 if (stateblock->wineD3DDevice->render_offscreen) {
2859 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2860 * render everything upside down when rendering offscreen. */
2861 glScalef(1.0, -1.0, 2.0);
2863 glScalef(1.0, 1.0, 2.0);
2865 checkGLcall("glScalef");
2867 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2868 checkGLcall("glLoadMatrixf");
2872 /* This should match any arrays loaded in loadVertexData.
2873 * stateblock impl is required for GL_SUPPORT
2874 * TODO: Only load / unload arrays if we have to.
2876 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2877 glDisableClientState(GL_VERTEX_ARRAY);
2878 glDisableClientState(GL_NORMAL_ARRAY);
2879 glDisableClientState(GL_COLOR_ARRAY);
2880 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2881 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2883 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2884 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2885 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2886 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2888 unloadTexCoords(stateblock);
2891 /* This should match any arrays loaded in loadNumberedArrays
2892 * TODO: Only load / unload arrays if we have to.
2894 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2895 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2896 GLint maxAttribs = 16;
2899 /* Leave all the attribs disabled */
2900 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2901 /* MESA does not support it right not */
2902 if (glGetError() != GL_NO_ERROR)
2904 for (i = 0; i < maxAttribs; ++i) {
2905 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2906 checkGLcall("glDisableVertexAttribArrayARB(reg)");
2907 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
2908 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
2909 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
2910 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
2911 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
2913 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
2914 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
2918 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2919 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2921 UINT *offset = stateblock->streamOffset;
2922 IWineD3DVertexBufferImpl *vb;
2923 DWORD_PTR shift_index;
2925 /* Default to no instancing */
2926 stateblock->wineD3DDevice->instancedDraw = FALSE;
2928 for (i = 0; i < MAX_ATTRIBS; i++) {
2930 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2933 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2934 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2935 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2936 stateblock->wineD3DDevice->instancedDraw = TRUE;
2940 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2942 if(strided->u.input[i].dwStride) {
2943 if(curVBO != strided->u.input[i].VBO) {
2944 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2945 checkGLcall("glBindBufferARB");
2946 curVBO = strided->u.input[i].VBO;
2948 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2949 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
2950 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
2951 * vbo we won't be load converted attributes anyway
2953 if(curVBO && vb->conv_shift) {
2954 TRACE("Loading attribute from shifted buffer\n");
2955 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
2956 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
2957 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
2958 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
2959 shift_index = shift_index % strided->u.input[i].dwStride;
2960 GL_EXTCALL(glVertexAttribPointerARB(i,
2961 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2962 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2963 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2966 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
2967 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2968 offset[strided->u.input[i].streamNo]));
2971 GL_EXTCALL(glVertexAttribPointerARB(i,
2972 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2973 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2974 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2975 strided->u.input[i].dwStride,
2977 strided->u.input[i].lpData +
2978 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2979 offset[strided->u.input[i].streamNo]) );
2981 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2983 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2984 * set up the attribute statically. But we have to figure out the system memory address.
2986 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2987 if(strided->u.input[i].VBO) {
2988 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2989 ptr += (long) vb->resource.allocatedMemory;
2991 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2993 switch(strided->u.input[i].dwType) {
2994 case WINED3DDECLTYPE_FLOAT1:
2995 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2997 case WINED3DDECLTYPE_FLOAT2:
2998 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
3000 case WINED3DDECLTYPE_FLOAT3:
3001 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
3003 case WINED3DDECLTYPE_FLOAT4:
3004 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
3007 case WINED3DDECLTYPE_UBYTE4:
3008 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3010 case WINED3DDECLTYPE_UBYTE4N:
3011 case WINED3DDECLTYPE_D3DCOLOR:
3012 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3015 case WINED3DDECLTYPE_SHORT2:
3016 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3018 case WINED3DDECLTYPE_SHORT4:
3019 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3022 case WINED3DDECLTYPE_SHORT2N:
3024 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
3025 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3028 case WINED3DDECLTYPE_USHORT2N:
3030 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
3031 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3034 case WINED3DDECLTYPE_SHORT4N:
3035 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
3037 case WINED3DDECLTYPE_USHORT4N:
3038 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
3041 case WINED3DDECLTYPE_UDEC3:
3042 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3043 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
3045 case WINED3DDECLTYPE_DEC3N:
3046 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3047 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
3050 case WINED3DDECLTYPE_FLOAT16_2:
3051 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3052 * byte float according to the IEEE standard
3054 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3056 case WINED3DDECLTYPE_FLOAT16_4:
3057 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3060 case WINED3DDECLTYPE_UNUSED:
3062 ERR("Unexpected declaration in stride 0 attributes\n");
3068 checkGLcall("Loading numbered arrays");
3071 /* Used from 2 different functions, and too big to justify making it inlined */
3072 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3073 UINT *offset = stateblock->streamOffset;
3074 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3076 TRACE("Using fast vertex array code\n");
3078 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3079 stateblock->wineD3DDevice->instancedDraw = FALSE;
3081 /* Blend Data ---------------------------------------------- */
3082 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3083 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3085 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3086 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3087 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3089 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3090 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3092 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3094 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3095 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3096 sd->u.s.blendWeights.dwStride,
3097 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3099 if(curVBO != sd->u.s.blendWeights.VBO) {
3100 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3101 checkGLcall("glBindBufferARB");
3102 curVBO = sd->u.s.blendWeights.VBO;
3105 GL_EXTCALL(glWeightPointerARB)(
3106 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3107 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3108 sd->u.s.blendWeights.dwStride,
3109 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3111 checkGLcall("glWeightPointerARB");
3113 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3114 static BOOL showfixme = TRUE;
3116 FIXME("blendMatrixIndices support\n");
3120 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3121 /* FIXME("TODO\n");*/
3124 GL_EXTCALL(glVertexWeightPointerEXT)(
3125 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3126 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3127 sd->u.s.blendWeights.dwStride,
3128 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3129 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3130 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3131 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3135 /* TODO: support blends in drawStridedSlow
3136 * No need to write a FIXME here, this is done after the general vertex decl decoding
3138 WARN("unsupported blending in openGl\n");
3141 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3142 static const GLbyte one = 1;
3143 GL_EXTCALL(glWeightbvARB(1, &one));
3144 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3148 #if 0 /* FOG ----------------------------------------------*/
3149 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3151 if (GL_SUPPORT(EXT_FOG_COORD) {
3152 glEnableClientState(GL_FOG_COORDINATE_EXT);
3153 (GL_EXTCALL)(FogCoordPointerEXT)(
3154 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3155 sd->u.s.fog.dwStride,
3156 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3158 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3159 /* FIXME: fixme once */
3160 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3163 if (GL_SUPPRT(EXT_FOR_COORD) {
3164 /* make sure fog is disabled */
3165 glDisableClientState(GL_FOG_COORDINATE_EXT);
3170 #if 0 /* tangents ----------------------------------------------*/
3171 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3172 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3174 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3175 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3176 glEnable(GL_TANGENT_ARRAY_EXT);
3177 (GL_EXTCALL)(TangentPointerEXT)(
3178 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3179 sd->u.s.tangent.dwStride,
3180 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3182 glDisable(GL_TANGENT_ARRAY_EXT);
3184 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3185 glEnable(GL_BINORMAL_ARRAY_EXT);
3186 (GL_EXTCALL)(BinormalPointerEXT)(
3187 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3188 sd->u.s.binormal.dwStride,
3189 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3191 glDisable(GL_BINORMAL_ARRAY_EXT);
3195 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3196 /* FIXME: fixme once */
3197 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3200 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3201 /* make sure fog is disabled */
3202 glDisable(GL_TANGENT_ARRAY_EXT);
3203 glDisable(GL_BINORMAL_ARRAY_EXT);
3208 /* Point Size ----------------------------------------------*/
3209 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3211 /* no such functionality in the fixed function GL pipeline */
3212 TRACE("Cannot change ptSize here in openGl\n");
3213 /* TODO: Implement this function in using shaders if they are available */
3217 /* Vertex Pointers -----------------------------------------*/
3218 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3219 /* Note dwType == float3 or float4 == 2 or 3 */
3220 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3221 sd->u.s.position.dwStride,
3222 sd->u.s.position.dwType + 1,
3223 sd->u.s.position.lpData));
3225 if(curVBO != sd->u.s.position.VBO) {
3226 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3227 checkGLcall("glBindBufferARB");
3228 curVBO = sd->u.s.position.VBO;
3231 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3232 handling for rhw mode should not impact screen position whereas in GL it does.
3233 This may result in very slightly distorted textures in rhw mode.
3234 There's always the other option of fixing the view matrix to
3235 prevent w from having any effect.
3237 This only applies to user pointer sources, in VBOs the vertices are fixed up
3239 if(sd->u.s.position.VBO == 0) {
3240 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3241 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3242 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3245 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3246 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3247 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3249 checkGLcall("glVertexPointer(...)");
3250 glEnableClientState(GL_VERTEX_ARRAY);
3251 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3254 /* Normals -------------------------------------------------*/
3255 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3256 /* Note dwType == float3 or float4 == 2 or 3 */
3257 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3258 sd->u.s.normal.dwStride,
3259 sd->u.s.normal.lpData));
3260 if(curVBO != sd->u.s.normal.VBO) {
3261 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3262 checkGLcall("glBindBufferARB");
3263 curVBO = sd->u.s.normal.VBO;
3266 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3267 sd->u.s.normal.dwStride,
3268 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3269 checkGLcall("glNormalPointer(...)");
3270 glEnableClientState(GL_NORMAL_ARRAY);
3271 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3274 glNormal3f(0, 0, 0);
3275 checkGLcall("glNormal3f(0, 0, 0)");
3278 /* Diffuse Colour --------------------------------------------*/
3279 /* WARNING: Data here MUST be in RGBA format, so cannot */
3280 /* go directly into fast mode from app pgm, because */
3281 /* directx requires data in BGRA format. */
3282 /* currently fixupVertices swizzles the format, but this isn't*/
3283 /* very practical when using VBOs */
3284 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3285 /* , or the user doesn't care and wants the speed advantage */
3287 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3288 /* Note dwType == float3 or float4 == 2 or 3 */
3289 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3290 sd->u.s.diffuse.dwStride,
3291 sd->u.s.diffuse.lpData));
3293 if(curVBO != sd->u.s.diffuse.VBO) {
3294 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3295 checkGLcall("glBindBufferARB");
3296 curVBO = sd->u.s.diffuse.VBO;
3299 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3300 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3301 sd->u.s.diffuse.dwStride,
3302 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3303 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3304 glEnableClientState(GL_COLOR_ARRAY);
3305 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3308 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3309 checkGLcall("glColor4f(1, 1, 1, 1)");
3312 /* Specular Colour ------------------------------------------*/
3313 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3314 TRACE("setting specular colour\n");
3315 /* Note dwType == float3 or float4 == 2 or 3 */
3316 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3317 sd->u.s.specular.dwStride,
3318 sd->u.s.specular.lpData));
3319 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3320 if(curVBO != sd->u.s.specular.VBO) {
3321 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3322 checkGLcall("glBindBufferARB");
3323 curVBO = sd->u.s.specular.VBO;
3325 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3326 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3327 sd->u.s.specular.dwStride,
3328 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3329 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3330 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3331 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3334 /* Missing specular color is not critical, no warnings */
3335 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3339 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3340 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3341 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3344 /* Missing specular color is not critical, no warnings */
3345 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3349 /* Texture coords -------------------------------------------*/
3350 loadTexCoords(stateblock, sd, &curVBO);
3353 static inline void drawPrimitiveTraceDataLocations(
3354 WineDirect3DVertexStridedData *dataLocations) {
3356 /* Dump out what parts we have supplied */
3357 TRACE("Strided Data:\n");
3358 TRACE_STRIDED((dataLocations), position);
3359 TRACE_STRIDED((dataLocations), blendWeights);
3360 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3361 TRACE_STRIDED((dataLocations), normal);
3362 TRACE_STRIDED((dataLocations), pSize);
3363 TRACE_STRIDED((dataLocations), diffuse);
3364 TRACE_STRIDED((dataLocations), specular);
3365 TRACE_STRIDED((dataLocations), texCoords[0]);
3366 TRACE_STRIDED((dataLocations), texCoords[1]);
3367 TRACE_STRIDED((dataLocations), texCoords[2]);
3368 TRACE_STRIDED((dataLocations), texCoords[3]);
3369 TRACE_STRIDED((dataLocations), texCoords[4]);
3370 TRACE_STRIDED((dataLocations), texCoords[5]);
3371 TRACE_STRIDED((dataLocations), texCoords[6]);
3372 TRACE_STRIDED((dataLocations), texCoords[7]);
3373 TRACE_STRIDED((dataLocations), position2);
3374 TRACE_STRIDED((dataLocations), normal2);
3375 TRACE_STRIDED((dataLocations), tangent);
3376 TRACE_STRIDED((dataLocations), binormal);
3377 TRACE_STRIDED((dataLocations), tessFactor);
3378 TRACE_STRIDED((dataLocations), fog);
3379 TRACE_STRIDED((dataLocations), depth);
3380 TRACE_STRIDED((dataLocations), sample);
3385 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3386 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3388 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3389 BOOL useVertexShaderFunction;
3391 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3392 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3393 useVertexShaderFunction = TRUE;
3395 useVertexShaderFunction = FALSE;
3399 if(device->up_strided) {
3400 /* Note: this is a ddraw fixed-function code path */
3401 TRACE("================ Strided Input ===================\n");
3402 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3405 drawPrimitiveTraceDataLocations(dataLocations);
3408 /* Note: This is a fixed function or shader codepath.
3409 * This means it must handle both types of strided data.
3410 * Shaders must go through here to zero the strided data, even if they
3411 * don't set any declaration at all
3413 TRACE("================ Vertex Declaration ===================\n");
3414 memset(dataLocations, 0, sizeof(*dataLocations));
3415 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3416 useVertexShaderFunction, dataLocations, &fixup);
3419 if (dataLocations->u.s.position_transformed) {
3420 useVertexShaderFunction = FALSE;
3423 /* Unload the old arrays before loading the new ones to get old junk out */
3424 if(context->numberedArraysLoaded) {
3425 unloadNumberedArrays(stateblock);
3426 context->numberedArraysLoaded = FALSE;
3428 if(context->namedArraysLoaded) {
3429 unloadVertexData(stateblock);
3430 context->namedArraysLoaded = FALSE;
3433 if(useVertexShaderFunction) {
3434 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3435 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3436 device->useDrawStridedSlow = TRUE;
3437 context->numberedArraysLoaded = FALSE;
3439 TRACE("Loading numbered arrays\n");
3440 loadNumberedArrays(stateblock, dataLocations);
3441 device->useDrawStridedSlow = FALSE;
3442 context->numberedArraysLoaded = TRUE;
3445 (dataLocations->u.s.pSize.lpData == NULL &&
3446 dataLocations->u.s.diffuse.lpData == NULL &&
3447 dataLocations->u.s.specular.lpData == NULL)) {
3448 /* Load the vertex data using named arrays */
3449 TRACE("Loading vertex data\n");
3450 loadVertexData(stateblock, dataLocations);
3451 device->useDrawStridedSlow = FALSE;
3452 context->namedArraysLoaded = TRUE;
3454 TRACE("Not loading vertex data\n");
3455 device->useDrawStridedSlow = TRUE;
3458 /* Generate some fixme's if unsupported functionality is being used */
3459 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3460 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3461 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3462 FIXME("Tweening is only valid with vertex shaders\n");
3464 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3465 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3467 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3468 FIXME("Extended attributes are only valid with vertex shaders\n");
3470 #undef BUFFER_OR_DATA
3473 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3474 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3475 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3476 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3478 /* Some stuff is in the device until we have per context tracking */
3479 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3480 BOOL wasrhw = context->last_was_rhw;
3482 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3483 * here simply check whether a shader was set, or the user disabled shaders
3485 if (use_vs(device)) {
3486 useVertexShaderFunction = TRUE;
3488 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3491 } else if(context->last_was_foggy_shader) {
3495 transformed = device->strided_streams.u.s.position_transformed;
3496 if (transformed) useVertexShaderFunction = FALSE;
3498 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3502 /* Reapply lighting if it is not scheduled for reapplication already */
3503 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3504 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3508 context->last_was_rhw = TRUE;
3511 /* Untransformed, so relies on the view and projection matrices */
3512 context->last_was_rhw = FALSE;
3513 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3514 device->untransformed = TRUE;
3516 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3517 * Not needed as long as only hw shaders are supported
3520 /* This sets the shader output position correction constants.
3521 * TODO: Move to the viewport state
3523 if (useVertexShaderFunction) {
3524 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3525 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3529 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3530 * off this function will be called again anyway to make sure they're properly set
3532 if(!useVertexShaderFunction) {
3533 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3534 * or transformed / untransformed was switched
3536 if(wasrhw != context->last_was_rhw &&
3537 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3538 !isStateDirty(context, STATE_VIEWPORT)) {
3539 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3541 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3544 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3545 * this check will fail and the matrix not applied again. This is OK because a simple
3546 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3547 * needs of the vertex declaration.
3549 * World and view matrix go into the same gl matrix, so only apply them when neither is
3552 if(transformed != wasrhw &&
3553 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3554 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3555 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3558 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3559 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3562 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3563 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3565 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3566 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3569 /* We compile the shader here because we need the vertex declaration
3570 * in order to determine if we need to do any swizzling for D3DCOLOR
3571 * registers. If the shader is already compiled this call will do nothing. */
3572 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3574 if(!context->last_was_vshader) {
3576 static BOOL warned = FALSE;
3577 /* Disable all clip planes to get defined results on all drivers. See comment in the
3578 * state_clipping state handler
3580 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3581 glDisable(GL_CLIP_PLANE0 + i);
3582 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3585 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3586 FIXME("Clipping not supported with vertex shaders\n");
3590 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3591 * shaders themselves do not need it, but the matrices are not reapplied automatically when
3592 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3593 * fixed function vertex processing states back in a sane state before switching to shaders
3595 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3596 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3598 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3599 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3605 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3608 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3609 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3611 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3612 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3616 context->last_was_vshader = useVertexShaderFunction;
3619 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3621 if(!useVertexShaderFunction) {
3623 for(i = 0; i < MAX_TEXTURES; i++) {
3624 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3625 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3631 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3633 IWineD3DSurfaceImpl *target;
3635 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3636 checkGLcall("glDepthRange");
3637 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3639 if(stateblock->wineD3DDevice->render_offscreen) {
3640 glViewport(stateblock->viewport.X,
3641 stateblock->viewport.Y,
3642 stateblock->viewport.Width, stateblock->viewport.Height);
3644 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3645 target->get_drawable_size(target, &width, &height);
3647 glViewport(stateblock->viewport.X,
3648 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3649 stateblock->viewport.Width, stateblock->viewport.Height);
3652 checkGLcall("glViewport");
3655 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3656 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3657 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3658 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3659 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3661 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3662 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3666 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3667 UINT Index = state - STATE_ACTIVELIGHT(0);
3668 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3671 glDisable(GL_LIGHT0 + Index);
3672 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3675 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3677 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3678 glMatrixMode(GL_MODELVIEW);
3680 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3683 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3684 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3685 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3686 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3687 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3688 checkGLcall("glLightfv");
3691 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3692 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3693 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3694 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3695 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3696 checkGLcall("glLightfv");
3699 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3700 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3701 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3702 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3703 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3704 checkGLcall("glLightfv");
3706 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3707 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3709 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3712 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3713 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3714 * Attenuation0 to NaN and crashes in the gl lib
3717 switch (lightInfo->OriginalParms.Type) {
3718 case WINED3DLIGHT_POINT:
3720 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3721 checkGLcall("glLightfv");
3722 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3723 checkGLcall("glLightf");
3724 /* Attenuation - Are these right? guessing... */
3725 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3726 checkGLcall("glLightf");
3727 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3728 checkGLcall("glLightf");
3729 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3730 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3731 checkGLcall("glLightf");
3735 case WINED3DLIGHT_SPOT:
3737 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3738 checkGLcall("glLightfv");
3740 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3741 checkGLcall("glLightfv");
3742 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3743 checkGLcall("glLightf");
3744 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3745 checkGLcall("glLightf");
3746 /* Attenuation - Are these right? guessing... */
3747 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3748 checkGLcall("glLightf");
3749 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3750 checkGLcall("glLightf");
3751 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3752 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3753 checkGLcall("glLightf");
3757 case WINED3DLIGHT_DIRECTIONAL:
3759 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3760 checkGLcall("glLightfv");
3761 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3762 checkGLcall("glLightf");
3763 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3764 checkGLcall("glLightf");
3768 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3771 /* Restore the modelview matrix */
3774 glEnable(GL_LIGHT0 + Index);
3775 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3781 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3782 RECT *pRect = &stateblock->scissorRect;
3785 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3787 target->get_drawable_size(target, &width, &height);
3788 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3789 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3791 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3792 pRect->right - pRect->left, pRect->bottom - pRect->top);
3794 if (stateblock->wineD3DDevice->render_offscreen) {
3795 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3797 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3799 checkGLcall("glScissor");
3802 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3803 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3804 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3805 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3807 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3808 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3813 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3814 if(stateblock->wineD3DDevice->render_offscreen) {
3815 glFrontFace(GL_CCW);
3816 checkGLcall("glFrontFace(GL_CCW)");
3819 checkGLcall("glFrontFace(GL_CW)");
3823 const struct StateEntryTemplate misc_state_template[] = {
3824 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3825 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3826 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3827 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3828 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3829 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3830 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3831 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3832 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3833 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }},
3834 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }},
3835 { STATE_VDECL, { STATE_VDECL, streamsrc }},
3836 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }},
3837 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }},
3838 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
3839 * vshader loadings are untied from each other
3841 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }},
3842 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }},
3843 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3844 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3845 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3846 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3847 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3848 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3849 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3850 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3851 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3852 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3853 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3854 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3855 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3856 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3857 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3858 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3859 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3860 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3861 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3862 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3863 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3864 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3865 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3866 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3867 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3868 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3869 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3870 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3871 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3872 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3873 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3874 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }},
3875 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3876 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3877 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3878 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3879 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3880 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3881 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3882 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3883 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3884 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3885 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3886 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3887 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3888 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3889 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }},
3890 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }},
3892 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }},
3893 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }},
3894 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }},
3895 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }},
3896 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }},
3897 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }},
3898 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }},
3899 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }},
3900 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }},
3901 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }},
3902 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }},
3903 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }},
3904 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }},
3905 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }},
3906 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }},
3907 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }},
3908 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }},
3909 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }},
3910 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }},
3911 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }},
3912 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }},
3913 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }},
3914 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }},
3915 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }},
3916 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }},
3917 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }},
3918 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }},
3919 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }},
3920 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }},
3921 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }},
3922 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }},
3923 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3924 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3925 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3926 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3927 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3928 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3929 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3930 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }},
3931 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3932 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3933 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3934 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3935 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }},
3936 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3937 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3938 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3939 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3940 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3941 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3942 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3943 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3944 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3945 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3946 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3947 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3948 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3949 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3950 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3951 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }},
3952 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }},
3953 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }},
3954 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}},
3955 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }},
3956 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}},
3957 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }},
3958 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3959 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3960 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3961 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3962 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3963 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3964 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }},
3965 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa }},
3966 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }},
3967 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }},
3968 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }},
3969 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }},
3970 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }},
3971 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }},
3972 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }},
3973 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }},
3974 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }},
3975 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }},
3977 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }},
3978 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }},
3979 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }},
3980 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }},
3981 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }},
3982 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }},
3983 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }},
3984 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }},
3985 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }},
3986 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }},
3987 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }},
3988 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }},
3989 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }},
3990 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }},
3991 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }},
3992 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }},
3993 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }},
3994 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }},
3995 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }},
3996 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }},
3997 {0 /* Terminate */, { 0, 0 }},
4000 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4001 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }},
4002 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }},
4003 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}},
4004 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}},
4006 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }},
4007 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }},
4008 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }},
4009 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }},
4010 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }},
4011 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }},
4012 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }},
4013 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }},
4014 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }},
4015 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }},
4016 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }},
4017 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }},
4018 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }},
4019 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }},
4020 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }},
4021 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }},
4022 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }},
4023 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }},
4024 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }},
4025 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }},
4026 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }},
4027 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }},
4028 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }},
4029 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }},
4030 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }},
4031 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }},
4032 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }},
4033 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }},
4034 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }},
4035 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }},
4036 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }},
4037 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }},
4039 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }},
4040 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }},
4041 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }},
4042 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }},
4043 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }},
4044 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }},
4045 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }},
4046 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }},
4048 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }},
4049 /* Transform states follow */
4050 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }},
4051 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}},
4052 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }},
4053 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }},
4054 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }},
4055 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }},
4056 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }},
4057 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }},
4058 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }},
4059 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }},
4060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }},
4061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_world }},
4062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_world }},
4063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_world }},
4064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_world }},
4065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_world }},
4066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_world }},
4067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_world }},
4068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_world }},
4069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_world }},
4070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_world }},
4071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_world }},
4072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_world }},
4073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_world }},
4074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_world }},
4075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_world }},
4076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_world }},
4077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_world }},
4078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_world }},
4079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_world }},
4080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_world }},
4081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_world }},
4082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_world }},
4083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_world }},
4084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_world }},
4085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_world }},
4086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_world }},
4087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_world }},
4088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_world }},
4089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_world }},
4090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_world }},
4091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_world }},
4092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_world }},
4093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_world }},
4094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_world }},
4095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_world }},
4096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_world }},
4097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_world }},
4098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_world }},
4099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_world }},
4100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_world }},
4101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_world }},
4102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_world }},
4103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_world }},
4104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_world }},
4105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_world }},
4106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_world }},
4107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_world }},
4108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_world }},
4109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_world }},
4110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_world }},
4111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_world }},
4112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_world }},
4113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_world }},
4114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_world }},
4115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_world }},
4116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_world }},
4117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_world }},
4118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_world }},
4119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_world }},
4120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_world }},
4121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_world }},
4122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_world }},
4123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_world }},
4124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_world }},
4125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_world }},
4126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_world }},
4127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_world }},
4128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_world }},
4129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_world }},
4130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_world }},
4131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_world }},
4132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_world }},
4133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_world }},
4134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_world }},
4135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_world }},
4136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_world }},
4137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_world }},
4138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_world }},
4139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_world }},
4140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_world }},
4141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_world }},
4142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_world }},
4143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_world }},
4144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_world }},
4145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_world }},
4146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_world }},
4147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_world }},
4148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_world }},
4149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_world }},
4150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_world }},
4151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_world }},
4152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_world }},
4153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_world }},
4154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_world }},
4155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_world }},
4156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_world }},
4157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_world }},
4158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_world }},
4159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_world }},
4160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_world }},
4161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_world }},
4162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_world }},
4163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_world }},
4164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_world }},
4165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_world }},
4166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_world }},
4167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_world }},
4168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_world }},
4169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_world }},
4170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_world }},
4171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_world }},
4172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_world }},
4173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_world }},
4174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_world }},
4175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_world }},
4176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_world }},
4177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_world }},
4178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_world }},
4179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_world }},
4180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_world }},
4181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_world }},
4182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_world }},
4183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_world }},
4184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_world }},
4185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_world }},
4186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_world }},
4187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_world }},
4188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_world }},
4189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_world }},
4190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_world }},
4191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_world }},
4192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_world }},
4193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_world }},
4194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_world }},
4195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_world }},
4196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_world }},
4197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_world }},
4198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_world }},
4199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_world }},
4200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_world }},
4201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_world }},
4202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_world }},
4203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_world }},
4204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_world }},
4205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_world }},
4206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_world }},
4207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_world }},
4208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_world }},
4209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_world }},
4210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_world }},
4211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_world }},
4212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_world }},
4213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_world }},
4214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_world }},
4215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_world }},
4216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_world }},
4217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_world }},
4218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_world }},
4219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_world }},
4220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_world }},
4221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_world }},
4222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_world }},
4223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_world }},
4224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_world }},
4225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_world }},
4226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_world }},
4227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_world }},
4228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_world }},
4229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_world }},
4230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_world }},
4231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_world }},
4232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_world }},
4233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_world }},
4234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_world }},
4235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_world }},
4236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_world }},
4237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_world }},
4238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_world }},
4239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_world }},
4240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_world }},
4241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_world }},
4242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_world }},
4243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_world }},
4244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_world }},
4245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_world }},
4246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_world }},
4247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_world }},
4248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_world }},
4249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_world }},
4250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_world }},
4251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_world }},
4252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_world }},
4253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_world }},
4254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_world }},
4255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_world }},
4256 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_world }},
4257 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_world }},
4258 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_world }},
4259 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_world }},
4260 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_world }},
4261 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_world }},
4262 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_world }},
4263 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_world }},
4264 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_world }},
4265 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_world }},
4266 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_world }},
4267 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_world }},
4268 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_world }},
4269 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_world }},
4270 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_world }},
4271 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_world }},
4272 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_world }},
4273 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_world }},
4274 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_world }},
4275 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_world }},
4276 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_world }},
4277 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_world }},
4278 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_world }},
4279 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_world }},
4280 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_world }},
4281 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_world }},
4282 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_world }},
4283 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_world }},
4284 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_world }},
4285 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_world }},
4286 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_world }},
4287 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_world }},
4288 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_world }},
4289 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_world }},
4290 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_world }},
4291 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_world }},
4292 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_world }},
4293 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_world }},
4294 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_world }},
4295 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_world }},
4296 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_world }},
4297 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_world }},
4298 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_world }},
4299 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_world }},
4300 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_world }},
4301 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_world }},
4302 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_world }},
4303 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_world }},
4304 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_world }},
4305 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_world }},
4306 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_world }},
4307 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_world }},
4308 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_world }},
4309 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_world }},
4310 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_world }},
4311 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_world }},
4312 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_world }},
4313 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_world }},
4314 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_world }},
4315 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_world }},
4316 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }},
4317 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }},
4318 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }},
4319 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }},
4320 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }},
4321 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }},
4322 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }},
4323 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }},
4324 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4325 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4326 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4327 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4328 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4329 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4330 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4331 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }},
4333 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }},
4334 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }},
4335 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }},
4336 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }},
4337 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }},
4338 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }},
4339 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }},
4340 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }},
4341 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }},
4342 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }},
4343 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }},
4344 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }},
4345 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }},
4346 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }},
4347 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }},
4348 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }},
4349 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }},
4350 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }},
4351 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }},
4352 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }},
4353 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }},
4354 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin }},
4355 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }},
4356 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }},
4357 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }},
4358 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }},
4359 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }},
4360 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax }},
4361 /* Samplers for NP2 texture matrix adjustions */
4362 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }},
4363 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }},
4364 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }},
4365 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }},
4366 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }},
4367 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }},
4368 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }},
4369 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }},
4370 {0 /* Terminate */, { 0, 0 }},
4373 const struct StateEntryTemplate ffp_fragmentstate_template[] = {
4374 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }},
4375 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }},
4376 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }},
4377 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }},
4378 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }},
4379 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }},
4380 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4381 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4382 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4383 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4384 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }},
4385 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }},
4386 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }},
4387 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4388 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }},
4389 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }},
4390 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }},
4391 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }},
4392 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }},
4393 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }},
4394 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4395 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4396 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4397 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4398 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }},
4399 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }},
4400 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }},
4401 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4402 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }},
4403 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }},
4404 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }},
4405 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }},
4406 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }},
4407 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }},
4408 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4409 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4410 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4411 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4412 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }},
4413 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }},
4414 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }},
4415 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4416 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }},
4417 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }},
4418 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }},
4419 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }},
4420 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }},
4421 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }},
4422 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4423 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4424 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4425 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4426 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }},
4427 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }},
4428 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }},
4429 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4430 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }},
4431 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }},
4432 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }},
4433 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }},
4434 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }},
4435 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }},
4436 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4437 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4438 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4439 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4440 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }},
4441 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }},
4442 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }},
4443 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4444 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }},
4445 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }},
4446 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }},
4447 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }},
4448 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }},
4449 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }},
4450 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4451 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4452 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4453 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4454 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }},
4455 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }},
4456 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }},
4457 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4458 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }},
4459 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }},
4460 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }},
4461 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }},
4462 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }},
4463 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }},
4464 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4465 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4466 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4467 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4468 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }},
4469 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }},
4470 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }},
4471 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4472 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }},
4473 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }},
4474 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }},
4475 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }},
4476 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }},
4477 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }},
4478 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4479 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4480 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4481 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }},
4482 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }},
4483 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }},
4484 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }},
4485 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }},
4486 { STATE_PIXELSHADER, { STATE_PIXELSHADER, pixelshader }},
4487 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, pixelshader }},
4488 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }},
4489 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }},
4490 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }},
4491 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }},
4492 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }},
4493 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }},
4494 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }},
4495 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }},
4496 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }},
4497 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }},
4498 {0 /* Terminate */, { 0, 0 }},
4500 #undef GLINFO_LOCATION
4502 #define GLINFO_LOCATION (*gl_info)
4503 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
4505 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) {
4506 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
4507 WINED3DTEXOPCAPS_ADDSIGNED |
4508 WINED3DTEXOPCAPS_ADDSIGNED2X |
4509 WINED3DTEXOPCAPS_MODULATE |
4510 WINED3DTEXOPCAPS_MODULATE2X |
4511 WINED3DTEXOPCAPS_MODULATE4X |
4512 WINED3DTEXOPCAPS_SELECTARG1 |
4513 WINED3DTEXOPCAPS_SELECTARG2 |
4514 WINED3DTEXOPCAPS_DISABLE;
4516 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
4517 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
4518 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4519 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
4520 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
4521 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
4522 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
4523 WINED3DTEXOPCAPS_LERP |
4524 WINED3DTEXOPCAPS_SUBTRACT;
4526 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
4527 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4528 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
4529 WINED3DTEXOPCAPS_MULTIPLYADD |
4530 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
4531 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4532 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
4534 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
4535 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
4537 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
4538 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
4539 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
4542 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
4543 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
4544 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
4545 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
4546 * not support 3D textures. This asks for trouble if an app uses both bump mapping
4547 * and 3D textures. It also allows us to keep the code simpler by having texture
4548 * shaders constantly enabled.
4550 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
4551 /* TODO: Luminance bump map? */
4556 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
4557 WINED3DTEXOPCAPS_PREMODULATE */
4560 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
4561 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
4563 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
4564 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
4567 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
4569 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
4570 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
4575 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4576 static void ffp_fragment_free(IWineD3DDevice *iface) {}
4578 #undef GLINFO_LOCATION
4580 const struct fragment_pipeline ffp_fragment_pipeline = {
4582 ffp_fragment_get_caps,
4585 ffp_fragmentstate_template
4588 static int num_handlers(APPLYSTATEFUNC *funcs) {
4590 for(i = 0; funcs[i]; i++);
4594 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4595 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4596 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4599 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4600 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4601 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4602 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
4605 void compile_state_table(struct StateEntry *StateTable,
4606 APPLYSTATEFUNC **dev_multistate_funcs,
4607 const struct StateEntryTemplate *vertex,
4608 const struct fragment_pipeline *fragment,
4609 const struct StateEntryTemplate *misc) {
4610 unsigned int i, type, handlers;
4611 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
4612 const struct StateEntryTemplate *cur;
4614 memset(multistate_funcs, 0, sizeof(multistate_funcs));
4616 for(i = 0; i < STATE_HIGHEST + 1; i++) {
4617 StateTable[i].representative = 0;
4618 StateTable[i].apply = state_undefined;
4621 for(type = 0; type < 3; type++) {
4622 /* This switch decides the order in which the states are applied */
4624 case 0: cur = misc; break;
4625 case 1: cur = fragment->states; break;
4626 case 2: cur = vertex; break;
4627 default: cur = NULL; /* Stupid compiler */
4631 for(i = 0; cur[i].state; i++) {
4632 handlers = num_handlers(multistate_funcs[cur[i].state]);
4633 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
4636 StateTable[cur[i].state].apply = cur[i].content.apply;
4639 StateTable[cur[i].state].apply = multistate_apply_2;
4640 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4642 sizeof(**dev_multistate_funcs) * 2);
4643 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4644 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4647 StateTable[cur[i].state].apply = multistate_apply_3;
4648 HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
4649 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4651 sizeof(**dev_multistate_funcs) * 3);
4652 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4653 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4654 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
4657 ERR("Unexpected amount of state handlers for state %u: %u\n",
4658 cur[i].state, handlers + 1);
4661 if(StateTable[cur[i].state].representative &&
4662 StateTable[cur[i].state].representative != cur[i].content.representative) {
4663 FIXME("State %u has different representatives in different pipeline parts\n",
4666 StateTable[cur[i].state].representative = cur[i].content.representative;