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