wined3d: Add extension information to the states.
[wine/gsoc_dplay.git] / dlls / wined3d / state.c
blobbbd8a1d3e99082a9d88dfa12a57c9d459353615d
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(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
455 float col[4];
457 if(!GL_SUPPORT(EXT_BLEND_COLOR)) {
458 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
459 return;
462 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
463 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
464 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
465 checkGLcall("glBlendColor");
468 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
469 int glParm = 0;
470 float ref;
471 BOOL enable_ckey = FALSE;
473 IWineD3DSurfaceImpl *surf;
475 /* Find out if the texture on the first stage has a ckey set
476 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
477 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
478 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
479 * in case it finds some texture+colorkeyenable combination which needs extra care.
481 if(stateblock->textures[0] && (
482 stateblock->textureDimensions[0] == GL_TEXTURE_2D ||
483 stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
484 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
486 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT) {
487 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
488 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
489 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
490 * surface has alpha bits
492 if(fmt->alphaMask == 0x00000000) {
493 enable_ckey = TRUE;
498 if(enable_ckey || context->last_was_ckey) {
499 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
500 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
502 context->last_was_ckey = enable_ckey;
504 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
505 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
506 glEnable(GL_ALPHA_TEST);
507 checkGLcall("glEnable GL_ALPHA_TEST");
508 } else {
509 glDisable(GL_ALPHA_TEST);
510 checkGLcall("glDisable GL_ALPHA_TEST");
511 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
512 * enable call
514 return;
517 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
518 glParm = GL_NOTEQUAL;
519 ref = 0.0;
520 } else {
521 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
522 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
524 if(glParm) {
525 glAlphaFunc(glParm, ref);
526 checkGLcall("glAlphaFunc");
530 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
531 DWORD enable = 0xFFFFFFFF;
532 DWORD disable = 0x00000000;
534 if (use_vs(stateblock->wineD3DDevice)) {
535 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
536 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
537 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
538 * of that - don't do anything here and keep them disabled
540 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
541 static BOOL warned = FALSE;
542 if(!warned) {
543 FIXME("Clipping not supported with vertex shaders\n");
544 warned = TRUE;
547 return;
550 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
551 * of already set values
554 /* If enabling / disabling all
555 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
557 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
558 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
559 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
560 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
561 glDisable(GL_DEPTH_CLAMP_NV);
562 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
564 } else {
565 disable = 0xffffffff;
566 enable = 0x00;
567 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
568 glEnable(GL_DEPTH_CLAMP_NV);
569 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
573 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
574 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
575 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
576 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
577 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
578 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
580 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
581 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
582 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
583 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
584 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
585 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
587 /** update clipping status */
588 if (enable) {
589 stateblock->clip_status.ClipUnion = 0;
590 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
591 } else {
592 stateblock->clip_status.ClipUnion = 0;
593 stateblock->clip_status.ClipIntersection = 0;
597 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
598 int blendEquation = GL_FUNC_ADD;
599 int blendEquationAlpha = GL_FUNC_ADD;
601 if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
602 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
603 return;
606 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
607 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
608 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
609 return;
612 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
613 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
614 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
615 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
616 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
617 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
618 default:
619 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
622 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
623 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
624 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
625 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
626 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
627 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
628 default:
629 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
632 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
633 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
634 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
635 checkGLcall("glBlendEquationSeparateEXT");
636 } else {
637 TRACE("glBlendEquation(%x)\n", blendEquation);
638 GL_EXTCALL(glBlendEquationEXT(blendEquation));
639 checkGLcall("glBlendEquation");
643 static void
644 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
645 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
646 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
647 * specular color. This is wrong:
648 * Separate specular color means the specular colour is maintained separately, whereas
649 * single color means it is merged in. However in both cases they are being used to
650 * some extent.
651 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
652 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
653 * running 1.4 yet!
656 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
657 * Instead, we need to setup the FinalCombiner properly.
659 * The default setup for the FinalCombiner is:
661 * <variable> <input> <mapping> <usage>
662 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
663 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
664 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
665 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
667 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
668 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
670 * That's pretty much fine as it is, except for variable B, which needs to take
671 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
672 * whether WINED3DRS_SPECULARENABLE is enabled or not.
675 TRACE("Setting specular enable state and materials\n");
676 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
677 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
678 checkGLcall("glMaterialfv");
680 if(stateblock->material.Power > GL_LIMITS(shininess)) {
681 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
682 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
683 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
684 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
685 * them, it should be safe to do so without major visual distortions.
687 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
688 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
689 } else {
690 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
692 checkGLcall("glMaterialf(GL_SHININESS)");
694 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
695 glEnable(GL_COLOR_SUM_EXT);
696 } else {
697 TRACE("Specular colors cannot be enabled in this version of opengl\n");
699 checkGLcall("glEnable(GL_COLOR_SUM)");
701 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
702 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
703 checkGLcall("glFinalCombinerInputNV()");
705 } else {
706 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
708 /* for the case of enabled lighting: */
709 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
710 checkGLcall("glMaterialfv");
712 /* for the case of disabled lighting: */
713 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
714 glDisable(GL_COLOR_SUM_EXT);
715 } else {
716 TRACE("Specular colors cannot be disabled in this version of opengl\n");
718 checkGLcall("glDisable(GL_COLOR_SUM)");
720 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
721 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
722 checkGLcall("glFinalCombinerInputNV()");
726 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
727 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
728 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
729 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
730 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
731 stateblock->material.Specular.b, stateblock->material.Specular.a);
732 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
733 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
735 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
736 checkGLcall("glMaterialfv(GL_AMBIENT)");
737 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
738 checkGLcall("glMaterialfv(GL_DIFFUSE)");
739 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
740 checkGLcall("glMaterialfv(GL_EMISSION)");
743 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
744 unsigned int i;
746 /* Note the texture color applies to all textures whereas
747 * GL_TEXTURE_ENV_COLOR applies to active only
749 float col[4];
750 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
752 /* And now the default texture color as well */
753 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
754 /* Note the WINED3DRS value applies to all textures, but GL has one
755 * per texture, so apply it now ready to be used!
757 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
758 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
759 checkGLcall("glActiveTextureARB");
760 } else if (i>0) {
761 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
764 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
765 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
769 static void
770 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
771 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
772 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
773 GL_EXTCALL(glActiveStencilFaceEXT(face));
774 checkGLcall("glActiveStencilFaceEXT(...)");
775 glStencilFunc(func, ref, mask);
776 checkGLcall("glStencilFunc(...)");
777 glStencilOp(stencilFail, depthFail, stencilPass);
778 checkGLcall("glStencilOp(...)");
781 static void
782 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
783 DWORD onesided_enable = FALSE;
784 DWORD twosided_enable = FALSE;
785 GLint func = GL_ALWAYS;
786 GLint func_ccw = GL_ALWAYS;
787 GLint ref = 0;
788 GLuint mask = 0;
789 GLint stencilFail = GL_KEEP;
790 GLint depthFail = GL_KEEP;
791 GLint stencilPass = GL_KEEP;
792 GLint stencilFail_ccw = GL_KEEP;
793 GLint depthFail_ccw = GL_KEEP;
794 GLint stencilPass_ccw = GL_KEEP;
796 /* No stencil test without a stencil buffer */
797 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
798 glDisable(GL_STENCIL_TEST);
799 checkGLcall("glDisable GL_STENCIL_TEST");
800 return;
803 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
804 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
805 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
806 func = GL_ALWAYS;
807 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
808 func_ccw = GL_ALWAYS;
809 ref = stateblock->renderState[WINED3DRS_STENCILREF];
810 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
811 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
812 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
813 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
814 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
815 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
816 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
818 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
819 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
820 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
821 onesided_enable, twosided_enable, ref, mask,
822 func, stencilFail, depthFail, stencilPass,
823 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
825 if (twosided_enable && onesided_enable) {
826 glEnable(GL_STENCIL_TEST);
827 checkGLcall("glEnable GL_STENCIL_TEST");
829 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
830 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
831 * which has an effect on the code below too. If we apply the front face
832 * afterwards, we are sure that the active stencil face is set to front,
833 * and other stencil functions which do not use two sided stencil do not have
834 * to set it back
836 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
837 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
838 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
839 stencilFail, depthFail, stencilPass);
840 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
841 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
842 checkGLcall("glStencilFuncSeparateATI(...)");
843 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
844 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
845 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
846 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
847 } else {
848 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
850 } else if(onesided_enable) {
851 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
852 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
853 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
856 /* This code disables the ATI extension as well, since the standard stencil functions are equal
857 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
859 glEnable(GL_STENCIL_TEST);
860 checkGLcall("glEnable GL_STENCIL_TEST");
861 glStencilFunc(func, ref, mask);
862 checkGLcall("glStencilFunc(...)");
863 glStencilOp(stencilFail, depthFail, stencilPass);
864 checkGLcall("glStencilOp(...)");
865 } else {
866 glDisable(GL_STENCIL_TEST);
867 checkGLcall("glDisable GL_STENCIL_TEST");
871 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
872 DWORD mask;
874 if(stateblock->wineD3DDevice->stencilBufferTarget) {
875 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
876 } else {
877 mask = 0;
880 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
881 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
882 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
883 glStencilMask(mask);
884 checkGLcall("glStencilMask");
885 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
886 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
887 glStencilMask(mask);
888 } else {
889 glStencilMask(mask);
891 checkGLcall("glStencilMask");
894 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
895 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
896 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
897 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version >= WINED3DPS_VERSION(3,0);
898 float fogstart, fogend;
900 union {
901 DWORD d;
902 float f;
903 } tmpvalue;
905 if (!fogenable) {
906 /* No fog? Disable it, and we're done :-) */
907 glDisable(GL_FOG);
908 checkGLcall("glDisable GL_FOG");
909 if( use_ps(stateblock->wineD3DDevice)
910 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.hex_version < WINED3DPS_VERSION(3,0) ) {
911 /* disable fog in the pixel shader
912 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
913 * -1/(e-s) and e/(e-s) respectively.
915 glFogf(GL_FOG_START, 0.0f);
916 checkGLcall("glFogf(GL_FOG_START, fogstart)");
917 glFogf(GL_FOG_END, 1.0f);
918 checkGLcall("glFogf(GL_FOG_END, fogend)");
920 return;
923 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
924 fogstart = tmpvalue.f;
925 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
926 fogend = tmpvalue.f;
928 /* Fog Rules:
930 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
931 * It can use the Z value of the vertex, or the alpha component of the specular color.
932 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
933 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
934 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
936 * FOGTABLEMODE != NONE:
937 * The Z value is used, with the equation specified, no matter what vertex type.
939 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
940 * Per vertex fog is calculated using the specified fog equation and the parameters
942 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
943 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
944 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
947 * Rules for vertex fog with shaders:
949 * When mixing fixed function functionality with the programmable pipeline, D3D expects
950 * the fog computation to happen during transformation while openGL expects it to happen
951 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
952 * the pixel shader while openGL always expects the pixel shader to handle the blending.
953 * To solve this problem, WineD3D does:
954 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
955 * shader,
956 * and 2) disables the fog computation (in either the fixed function or programmable
957 * rasterizer) if using a vertex program.
960 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
961 * without shaders).
964 if( is_ps3 ) {
965 if( !use_vs(stateblock->wineD3DDevice)
966 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
967 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
971 if (use_vs(stateblock->wineD3DDevice)
972 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
973 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
974 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
975 /* Disable fog */
976 fogenable = FALSE;
977 } else {
978 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
979 glFogi(GL_FOG_MODE, GL_LINEAR);
980 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
981 fogstart = 1.0;
982 fogend = 0.0;
985 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
986 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
987 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
988 context->fog_coord = FALSE;
990 context->last_was_foggy_shader = TRUE;
992 else if( use_ps(stateblock->wineD3DDevice) ) {
993 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
994 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
996 WINED3DFOGMODE mode;
997 context->last_was_foggy_shader = FALSE;
999 /* If both fogmodes are set use the table fog mode */
1000 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
1001 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
1002 else
1003 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
1005 switch (mode) {
1006 case WINED3DFOG_EXP:
1007 case WINED3DFOG_EXP2:
1008 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1009 /* Disable fog */
1010 fogenable = FALSE;
1011 break;
1013 case WINED3DFOG_LINEAR:
1014 fogstart = -1.0f/(fogend-fogstart);
1015 fogend *= -fogstart;
1016 break;
1018 case WINED3DFOG_NONE:
1019 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1020 /* Disable fog */
1021 fogenable = FALSE;
1022 break;
1023 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1026 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1027 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1028 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1029 context->fog_coord = FALSE;
1032 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1033 * the system will apply only pixel(=table) fog effects."
1035 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1036 glHint(GL_FOG_HINT, GL_FASTEST);
1037 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1038 context->last_was_foggy_shader = FALSE;
1040 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1041 /* If processed vertices are used, fall through to the NONE case */
1042 case WINED3DFOG_EXP: {
1043 if(!context->last_was_rhw) {
1044 glFogi(GL_FOG_MODE, GL_EXP);
1045 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1046 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1047 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1048 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1049 context->fog_coord = FALSE;
1051 break;
1054 case WINED3DFOG_EXP2: {
1055 if(!context->last_was_rhw) {
1056 glFogi(GL_FOG_MODE, GL_EXP2);
1057 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1058 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1059 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1060 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1061 context->fog_coord = FALSE;
1063 break;
1066 case WINED3DFOG_LINEAR: {
1067 if(!context->last_was_rhw) {
1068 glFogi(GL_FOG_MODE, GL_LINEAR);
1069 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1070 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1071 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1072 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1073 context->fog_coord = FALSE;
1075 break;
1078 case WINED3DFOG_NONE: {
1079 /* Both are none? According to msdn the alpha channel of the specular
1080 * color contains a fog factor. Set it in drawStridedSlow.
1081 * Same happens with Vertexfog on transformed vertices
1083 if(GL_SUPPORT(EXT_FOG_COORD)) {
1084 if(context->fog_coord == FALSE) {
1085 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1086 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1087 context->fog_coord = TRUE;
1089 glFogi(GL_FOG_MODE, GL_LINEAR);
1090 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1091 fogstart = 0xff;
1092 fogend = 0x0;
1093 } else {
1094 /* Disable GL fog, handle this in software in drawStridedSlow */
1095 fogenable = FALSE;
1097 break;
1099 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1101 } else {
1102 glHint(GL_FOG_HINT, GL_NICEST);
1103 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1104 context->last_was_foggy_shader = FALSE;
1106 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1107 case WINED3DFOG_EXP:
1108 glFogi(GL_FOG_MODE, GL_EXP);
1109 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1110 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1111 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1112 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1113 context->fog_coord = FALSE;
1115 break;
1117 case WINED3DFOG_EXP2:
1118 glFogi(GL_FOG_MODE, GL_EXP2);
1119 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1120 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1121 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1122 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1123 context->fog_coord = FALSE;
1125 break;
1127 case WINED3DFOG_LINEAR:
1128 glFogi(GL_FOG_MODE, GL_LINEAR);
1129 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1130 if(GL_SUPPORT(EXT_FOG_COORD) && context->fog_coord) {
1131 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1132 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1133 context->fog_coord = FALSE;
1135 break;
1137 case WINED3DFOG_NONE: /* Won't happen */
1138 default:
1139 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1143 if(fogenable) {
1144 glEnable(GL_FOG);
1145 checkGLcall("glEnable GL_FOG");
1147 if(fogstart != fogend)
1149 glFogfv(GL_FOG_START, &fogstart);
1150 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1151 TRACE("Fog Start == %f\n", fogstart);
1153 glFogfv(GL_FOG_END, &fogend);
1154 checkGLcall("glFogf(GL_FOG_END, fogend)");
1155 TRACE("Fog End == %f\n", fogend);
1157 else
1159 glFogf(GL_FOG_START, -1.0 / 0.0);
1160 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1161 TRACE("Fog Start == %f\n", fogstart);
1163 glFogf(GL_FOG_END, 0.0);
1164 checkGLcall("glFogf(GL_FOG_END, fogend)");
1165 TRACE("Fog End == %f\n", fogend);
1167 } else {
1168 glDisable(GL_FOG);
1169 checkGLcall("glDisable GL_FOG");
1170 if( use_ps(stateblock->wineD3DDevice) ) {
1171 /* disable fog in the pixel shader
1172 * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
1173 * -1/(e-s) and e/(e-s) respectively.
1175 glFogf(GL_FOG_START, 0.0f);
1176 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1177 glFogf(GL_FOG_END, 1.0f);
1178 checkGLcall("glFogf(GL_FOG_END, fogend)");
1183 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1184 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1185 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1186 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1187 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1188 } else {
1189 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1191 } else {
1192 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
1193 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1194 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1199 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1200 float col[4];
1201 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1202 glFogfv(GL_FOG_COLOR, &col[0]);
1203 checkGLcall("glFog GL_FOG_COLOR");
1206 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1207 union {
1208 DWORD d;
1209 float f;
1210 } tmpvalue;
1211 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1212 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1213 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1216 /* TODO: Merge with primitive type + init_materials()!! */
1217 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1218 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1219 GLenum Parm = 0;
1220 WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1221 BOOL isDiffuseSupplied;
1223 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1224 * The vertex declaration will call this function if the fixed function pipeline is used.
1227 if(isStateDirty(context, STATE_VDECL)) {
1228 return;
1231 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1233 context->num_untracked_materials = 0;
1234 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1235 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1236 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1237 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1238 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1239 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1241 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1242 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1243 Parm = GL_AMBIENT_AND_DIFFUSE;
1244 } else {
1245 Parm = GL_DIFFUSE;
1247 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1248 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1249 context->num_untracked_materials++;
1251 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1252 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1253 context->num_untracked_materials++;
1255 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1256 Parm = GL_AMBIENT;
1257 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1258 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1259 context->num_untracked_materials++;
1261 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1262 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1263 context->num_untracked_materials++;
1265 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1266 Parm = GL_EMISSION;
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_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1272 Parm = GL_SPECULAR;
1276 /* Nothing changed, return. */
1277 if (Parm == context->tracking_parm) return;
1279 if(!Parm) {
1280 glDisable(GL_COLOR_MATERIAL);
1281 checkGLcall("glDisable GL_COLOR_MATERIAL");
1282 } else {
1283 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1284 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1285 glEnable(GL_COLOR_MATERIAL);
1286 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1289 /* Apparently calls to glMaterialfv are ignored for properties we're
1290 * tracking with glColorMaterial, so apply those here. */
1291 switch (context->tracking_parm) {
1292 case GL_AMBIENT_AND_DIFFUSE:
1293 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1294 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1295 checkGLcall("glMaterialfv");
1296 break;
1298 case GL_DIFFUSE:
1299 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1300 checkGLcall("glMaterialfv");
1301 break;
1303 case GL_AMBIENT:
1304 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1305 checkGLcall("glMaterialfv");
1306 break;
1308 case GL_EMISSION:
1309 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1310 checkGLcall("glMaterialfv");
1311 break;
1313 case GL_SPECULAR:
1314 /* Only change material color if specular is enabled, otherwise it is set to black */
1315 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1316 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1317 checkGLcall("glMaterialfv");
1318 } else {
1319 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1320 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1321 checkGLcall("glMaterialfv");
1323 break;
1326 context->tracking_parm = Parm;
1329 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1330 union {
1331 DWORD d;
1332 WINED3DLINEPATTERN lp;
1333 } tmppattern;
1334 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1336 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1338 if (tmppattern.lp.wRepeatFactor) {
1339 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1340 checkGLcall("glLineStipple(repeat, linepattern)");
1341 glEnable(GL_LINE_STIPPLE);
1342 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1343 } else {
1344 glDisable(GL_LINE_STIPPLE);
1345 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1349 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1350 union {
1351 DWORD d;
1352 float f;
1353 } tmpvalue;
1355 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1356 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1357 TRACE("ZBias value %f\n", tmpvalue.f);
1358 glPolygonOffset(0, -tmpvalue.f);
1359 checkGLcall("glPolygonOffset(0, -Value)");
1360 glEnable(GL_POLYGON_OFFSET_FILL);
1361 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1362 glEnable(GL_POLYGON_OFFSET_LINE);
1363 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1364 glEnable(GL_POLYGON_OFFSET_POINT);
1365 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1366 } else {
1367 glDisable(GL_POLYGON_OFFSET_FILL);
1368 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1369 glDisable(GL_POLYGON_OFFSET_LINE);
1370 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1371 glDisable(GL_POLYGON_OFFSET_POINT);
1372 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1377 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1378 if(isStateDirty(context, STATE_VDECL)) {
1379 return;
1381 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1382 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1383 * by zero and is not properly defined in opengl, so avoid it
1385 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1386 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1387 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1388 glEnable(GL_NORMALIZE);
1389 checkGLcall("glEnable(GL_NORMALIZE);");
1390 } else {
1391 glDisable(GL_NORMALIZE);
1392 checkGLcall("glDisable(GL_NORMALIZE);");
1396 static void state_psizemin(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1397 union {
1398 DWORD d;
1399 float f;
1400 } tmpvalue;
1402 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1403 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1404 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, tmpvalue.f);
1405 checkGLcall("glPointParameterfARB(...)");
1407 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1408 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
1409 checkGLcall("glPointParameterfEXT(...)");
1410 } else if(tmpvalue.f != 1.0) {
1411 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1415 static void state_psizemax(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1416 union {
1417 DWORD d;
1418 float f;
1419 } tmpvalue;
1421 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1422 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1423 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, tmpvalue.f);
1424 checkGLcall("glPointParameterfARB(...)");
1426 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1427 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
1428 checkGLcall("glPointParameterfEXT(...)");
1429 } else if(tmpvalue.f != 64.0) {
1430 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1434 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1435 /* TODO: Group this with the viewport */
1437 * POINTSCALEENABLE controls how point size value is treated. If set to
1438 * true, the point size is scaled with respect to height of viewport.
1439 * When set to false point size is in pixels.
1442 /* Default values */
1443 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1444 union {
1445 DWORD d;
1446 float f;
1447 } pointSize, A, B, C;
1449 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1450 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1451 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1452 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1454 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1455 GLfloat scaleFactor;
1456 float h = stateblock->viewport.Height;
1458 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1460 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1461 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1462 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1463 * are less than 1.0f. scale_factor = 1.0f / point_size.
1465 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1466 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1467 * is 1.0, but then accepts points below that and draws too small points
1469 pointSize.f = GL_LIMITS(pointsizemin);
1470 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1471 /* gl already scales the input to glPointSize,
1472 * d3d scales the result after the point size scale.
1473 * If the point size is bigger than the max size, use the
1474 * scaling to scale it bigger, and set the gl point size to max
1476 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1477 TRACE("scale: %f\n", scaleFactor);
1478 pointSize.f = GL_LIMITS(pointsize);
1479 } else {
1480 scaleFactor = 1.0f;
1482 scaleFactor = pow(h * scaleFactor, 2);
1484 att[0] = A.f / scaleFactor;
1485 att[1] = B.f / scaleFactor;
1486 att[2] = C.f / scaleFactor;
1489 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1490 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1491 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1493 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1494 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1495 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1496 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1497 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1500 glPointSize(pointSize.f);
1501 checkGLcall("glPointSize(...);");
1504 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1505 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1507 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1508 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1509 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1510 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1511 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1512 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1513 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1514 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1515 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1516 checkGLcall("glColorMask(...)");
1518 /* depends on WINED3DRS_COLORWRITEENABLE. */
1519 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1520 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1521 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1522 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1523 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1524 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1525 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1529 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1530 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1531 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1532 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1533 } else {
1534 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1535 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1539 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1540 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1541 TRACE("Last Pixel Drawing Enabled\n");
1542 } else {
1543 static BOOL first = TRUE;
1544 if(first) {
1545 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1546 first = FALSE;
1547 } else {
1548 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1553 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1554 /* TODO: NV_POINT_SPRITE */
1555 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
1556 TRACE("Point sprites not supported\n");
1557 return;
1560 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1561 glEnable(GL_POINT_SPRITE_ARB);
1562 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1563 } else {
1564 glDisable(GL_POINT_SPRITE_ARB);
1565 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1569 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1571 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1572 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1573 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1574 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1576 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1578 TRACE("Stub\n");
1579 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1580 stateblock->renderState[WINED3DRS_WRAP1] ||
1581 stateblock->renderState[WINED3DRS_WRAP2] ||
1582 stateblock->renderState[WINED3DRS_WRAP3] ||
1583 stateblock->renderState[WINED3DRS_WRAP4] ||
1584 stateblock->renderState[WINED3DRS_WRAP5] ||
1585 stateblock->renderState[WINED3DRS_WRAP6] ||
1586 stateblock->renderState[WINED3DRS_WRAP7] ||
1587 stateblock->renderState[WINED3DRS_WRAP8] ||
1588 stateblock->renderState[WINED3DRS_WRAP9] ||
1589 stateblock->renderState[WINED3DRS_WRAP10] ||
1590 stateblock->renderState[WINED3DRS_WRAP11] ||
1591 stateblock->renderState[WINED3DRS_WRAP12] ||
1592 stateblock->renderState[WINED3DRS_WRAP13] ||
1593 stateblock->renderState[WINED3DRS_WRAP14] ||
1594 stateblock->renderState[WINED3DRS_WRAP15] ) {
1595 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1599 static void state_multisampleaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1600 if( GL_SUPPORT(ARB_MULTISAMPLE) ) {
1601 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1602 glEnable(GL_MULTISAMPLE_ARB);
1603 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1604 } else {
1605 glDisable(GL_MULTISAMPLE_ARB);
1606 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1608 } else {
1609 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1610 WARN("Multisample antialiasing not supported by gl\n");
1615 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1616 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1617 glEnable(GL_SCISSOR_TEST);
1618 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1619 } else {
1620 glDisable(GL_SCISSOR_TEST);
1621 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1625 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1626 union {
1627 DWORD d;
1628 float f;
1629 } tmpvalue;
1631 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1632 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1633 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1634 glEnable(GL_POLYGON_OFFSET_FILL);
1635 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1636 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1637 checkGLcall("glPolygonOffset(...)");
1638 } else {
1639 glDisable(GL_POLYGON_OFFSET_FILL);
1640 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1644 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1645 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1646 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1647 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1648 } else {
1649 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1650 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1654 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1655 TRACE("Stub\n");
1656 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1657 FIXME(" Stippled Alpha not supported yet.\n");
1660 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1661 TRACE("Stub\n");
1662 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1663 FIXME(" Antialias not supported yet.\n");
1666 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1667 TRACE("Stub\n");
1668 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1669 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1672 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1673 TRACE("Stub\n");
1674 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1675 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1678 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1679 union {
1680 DWORD d;
1681 float f;
1682 } tmpvalue;
1683 tmpvalue.f = 1.0f;
1685 TRACE("Stub\n");
1686 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1688 static BOOL displayed = FALSE;
1690 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1691 if(!displayed)
1692 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1694 displayed = TRUE;
1698 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1699 TRACE("Stub\n");
1700 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1701 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1704 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1705 TRACE("Stub\n");
1706 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1707 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1710 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1711 TRACE("Stub\n");
1712 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1713 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1716 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1717 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1718 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1722 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1723 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1724 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1728 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1729 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1730 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1734 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1735 if(stateblock->renderState[WINED3DRS_ROP2]) {
1736 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1740 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1741 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1742 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1746 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1747 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1748 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1752 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1753 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1754 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1758 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1759 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1760 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1764 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1765 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1766 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1770 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1771 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1772 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1776 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1777 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1778 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1782 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1783 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1784 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1788 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1789 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1790 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1794 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1795 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1796 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1800 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1801 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1802 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1806 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1807 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1808 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1809 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1811 TRACE("Setting color op for stage %d\n", stage);
1813 if (stateblock->pixelShader && stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE &&
1814 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
1815 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
1816 return;
1819 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
1821 if (mapped_stage != -1) {
1822 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1823 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1824 FIXME("Attempt to enable unsupported stage!\n");
1825 return;
1827 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1828 checkGLcall("glActiveTextureARB");
1829 } else if (stage > 0) {
1830 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1831 return;
1835 if(stage >= stateblock->lowest_disabled_stage) {
1836 TRACE("Stage disabled\n");
1837 if (mapped_stage != -1) {
1838 /* Disable everything here */
1839 glDisable(GL_TEXTURE_2D);
1840 checkGLcall("glDisable(GL_TEXTURE_2D)");
1841 glDisable(GL_TEXTURE_3D);
1842 checkGLcall("glDisable(GL_TEXTURE_3D)");
1843 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1844 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
1845 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
1847 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
1848 glDisable(GL_TEXTURE_RECTANGLE_ARB);
1849 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
1852 /* All done */
1853 return;
1856 /* The sampler will also activate the correct texture dimensions, so no need to do it here
1857 * if the sampler for this stage is dirty
1859 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
1860 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
1863 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
1864 stateblock->textureState[stage][WINED3DTSS_COLOROP],
1865 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
1866 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
1867 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
1870 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1871 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
1872 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
1873 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
1874 DWORD op, arg1, arg2, arg0;
1876 TRACE("Setting alpha op for stage %d\n", stage);
1877 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
1878 if (mapped_stage != -1) {
1879 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1880 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
1881 FIXME("Attempt to enable unsupported stage!\n");
1882 return;
1884 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1885 checkGLcall("glActiveTextureARB");
1886 } else if (stage > 0) {
1887 /* We can't do anything here */
1888 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1889 return;
1893 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
1894 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
1895 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
1896 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
1898 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 &&
1899 stateblock->textures[0] &&
1900 (stateblock->textureDimensions[0] == GL_TEXTURE_2D || stateblock->textureDimensions[0] == GL_TEXTURE_RECTANGLE_ARB)) {
1901 IWineD3DSurfaceImpl *surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
1903 if(surf->CKeyFlags & WINEDDSD_CKSRCBLT &&
1904 getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000) {
1906 /* Color keying needs to pass alpha values from the texture through to have the alpha test work properly.
1907 * On the other hand applications can still use texture combiners apparently. This code takes care that apps
1908 * cannot remove the texture's alpha channel entirely.
1910 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires D3DTOP_MODULATE to work
1911 * on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures and alpha component of diffuse color to
1912 * draw things like translucent text and perform other blending effects.
1914 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To provide the
1915 * behavior expected by the game, while emulating the colorkey, diffuse alpha must be modulated with texture alpha.
1916 * OTOH, Moto racer 2 at some points sets alphaop/alphaarg to SELECTARG/CURRENT, yet puts garbage in diffuse alpha
1917 * (zeroes). This works on native, because the game disables alpha test and alpha blending. Alpha test is overwritten by
1918 * wine's for purposes of color-keying though, so this will lead to missing geometry if texture alpha is modulated
1919 * (pixels fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha blending,
1920 * it can be expected to provide meaningful values in diffuse alpha, so it should be modulated with texture alpha;
1921 * otherwise, selecting diffuse alpha is ignored in favour of texture alpha.
1923 * What to do with multitexturing? So far no app has been found that uses color keying with multitexturing
1925 if(op == WINED3DTOP_DISABLE) {
1926 arg1 = WINED3DTA_TEXTURE;
1927 op = WINED3DTOP_SELECTARG1;
1929 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) {
1930 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1931 arg2 = WINED3DTA_TEXTURE;
1932 op = WINED3DTOP_MODULATE;
1934 else arg1 = WINED3DTA_TEXTURE;
1936 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) {
1937 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]) {
1938 arg1 = WINED3DTA_TEXTURE;
1939 op = WINED3DTOP_MODULATE;
1941 else arg2 = WINED3DTA_TEXTURE;
1946 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
1947 * this if block here, and the other code(color keying, texture unit selection) are the same
1949 TRACE("Setting alpha op for stage %d\n", stage);
1950 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
1951 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1952 op, arg1, arg2, arg0,
1953 mapped_stage,
1954 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
1955 } else {
1956 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
1957 op, arg1, arg2, arg0);
1961 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1962 DWORD texUnit = state - STATE_TRANSFORM(WINED3DTS_TEXTURE0);
1963 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
1964 BOOL generated;
1966 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
1967 if(use_vs(stateblock->wineD3DDevice) ||
1968 isStateDirty(context, STATE_VDECL)) {
1969 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
1970 return;
1973 if (mapped_stage == -1) return;
1975 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1976 if(mapped_stage >= GL_LIMITS(textures)) {
1977 return;
1979 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
1980 checkGLcall("glActiveTextureARB");
1981 } else if (mapped_stage > 0) {
1982 /* We can't do anything here */
1983 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1984 return;
1986 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
1988 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
1989 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
1990 generated,
1991 context->last_was_rhw,
1992 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwStride ?
1993 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[texUnit].dwType:
1994 WINED3DDECLTYPE_UNUSED);
1996 /* The sampler applying function calls us if this changes */
1997 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
1998 if(generated) {
1999 FIXME("Non-power2 texture being used with generated texture coords\n");
2001 TRACE("Non power two matrix multiply fixup\n");
2002 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
2006 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
2007 int texture_idx;
2009 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
2010 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
2011 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2015 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd, GLint *curVBO) {
2016 UINT *offset = stateblock->streamOffset;
2017 unsigned int mapped_stage = 0;
2018 unsigned int textureNo = 0;
2020 /* The code below uses glClientActiveTexture and glMultiTexCoord* which are all part of the GL_ARB_multitexture extension. */
2021 /* Abort if we don't support the extension. */
2022 if (!GL_SUPPORT(ARB_MULTITEXTURE)) {
2023 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2024 return;
2027 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
2028 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
2030 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
2031 if (mapped_stage == -1) continue;
2033 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
2034 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
2035 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
2037 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
2038 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
2039 checkGLcall("glBindBufferARB");
2040 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
2043 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2044 checkGLcall("glClientActiveTextureARB");
2046 /* The coords to supply depend completely on the fvf / vertex shader */
2047 glTexCoordPointer(
2048 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
2049 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
2050 sd->u.s.texCoords[coordIdx].dwStride,
2051 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
2052 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2053 } else {
2054 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
2057 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2058 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
2059 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
2060 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
2065 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2066 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2067 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2069 if (mapped_stage == -1) {
2070 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
2071 return;
2074 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2075 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
2076 return;
2078 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2079 checkGLcall("glActiveTextureARB");
2080 } else if (stage > 0) {
2081 /* We can't do anything here */
2082 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2083 return;
2086 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
2088 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
2089 * one flag, you can still specify an index value, which the system uses to
2090 * determine the texture wrapping mode.
2091 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2092 * means use the vertex position (camera-space) as the input texture coordinates
2093 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
2094 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
2095 * to the TEXCOORDINDEX value
2099 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2101 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
2102 case WINED3DTSS_TCI_PASSTHRU:
2103 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2104 glDisable(GL_TEXTURE_GEN_S);
2105 glDisable(GL_TEXTURE_GEN_T);
2106 glDisable(GL_TEXTURE_GEN_R);
2107 glDisable(GL_TEXTURE_GEN_Q);
2108 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
2109 break;
2111 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
2112 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2113 * as the input texture coordinates for this stage's texture transformation. This
2114 * equates roughly to EYE_LINEAR
2117 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2118 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2119 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2120 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2121 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2123 glMatrixMode(GL_MODELVIEW);
2124 glPushMatrix();
2125 glLoadIdentity();
2126 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2127 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2128 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2129 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2130 glPopMatrix();
2132 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2133 glEnable(GL_TEXTURE_GEN_S);
2134 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2135 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2136 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2137 glEnable(GL_TEXTURE_GEN_T);
2138 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2139 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2140 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2141 glEnable(GL_TEXTURE_GEN_R);
2142 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2143 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2144 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2146 break;
2148 case WINED3DTSS_TCI_CAMERASPACENORMAL:
2150 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2151 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2152 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2153 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2154 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2155 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
2157 glMatrixMode(GL_MODELVIEW);
2158 glPushMatrix();
2159 glLoadIdentity();
2160 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2161 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2162 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2163 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2164 glPopMatrix();
2166 glEnable(GL_TEXTURE_GEN_S);
2167 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2168 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2169 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2170 glEnable(GL_TEXTURE_GEN_T);
2171 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2172 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2173 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2174 glEnable(GL_TEXTURE_GEN_R);
2175 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2176 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2177 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2180 break;
2182 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2184 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2185 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2186 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2187 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2188 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2189 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
2191 glMatrixMode(GL_MODELVIEW);
2192 glPushMatrix();
2193 glLoadIdentity();
2194 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2195 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2196 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2197 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2198 glPopMatrix();
2200 glEnable(GL_TEXTURE_GEN_S);
2201 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
2202 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2203 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2204 glEnable(GL_TEXTURE_GEN_T);
2205 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
2206 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2207 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2208 glEnable(GL_TEXTURE_GEN_R);
2209 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
2210 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2211 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2214 break;
2216 /* Unhandled types: */
2217 default:
2218 /* Todo: */
2219 /* ? disable GL_TEXTURE_GEN_n ? */
2220 glDisable(GL_TEXTURE_GEN_S);
2221 glDisable(GL_TEXTURE_GEN_T);
2222 glDisable(GL_TEXTURE_GEN_R);
2223 glDisable(GL_TEXTURE_GEN_Q);
2224 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
2225 break;
2228 /* Update the texture matrix */
2229 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
2230 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage), stateblock, context);
2233 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
2234 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
2235 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
2236 * and do all the things linked to it
2237 * TODO: Tidy that up to reload only the arrays of the changed unit
2239 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2241 unloadTexCoords(stateblock);
2242 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
2246 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2247 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2249 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
2250 * has an update pending
2252 if(isStateDirty(context, STATE_VDECL) ||
2253 isStateDirty(context, STATE_PIXELSHADER)) {
2254 return;
2257 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
2260 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2261 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2262 union {
2263 DWORD d;
2264 float f;
2265 } tmpvalue;
2267 if(stateblock->pixelShader && stage != 0 &&
2268 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2269 /* The pixel shader has to know the luminance scale. Do a constants update if it
2270 * isn't scheduled anyway
2272 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2273 !isStateDirty(context, STATE_PIXELSHADER)) {
2274 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2278 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE];
2279 if(tmpvalue.f != 0.0) {
2280 FIXME("WINED3DTSS_BUMPENVLSCALE not supported yet\n");
2284 static void tex_bumpenvloffset(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2285 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2286 union {
2287 DWORD d;
2288 float f;
2289 } tmpvalue;
2291 if(stateblock->pixelShader && stage != 0 &&
2292 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
2293 /* The pixel shader has to know the luminance offset. Do a constants update if it
2294 * isn't scheduled anyway
2296 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2297 !isStateDirty(context, STATE_PIXELSHADER)) {
2298 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2302 tmpvalue.d = stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET];
2303 if(tmpvalue.f != 0.0) {
2304 FIXME("WINED3DTSS_BUMPENVLOFFSET not supported yet\n");
2308 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2309 BOOL texIsPow2 = FALSE;
2310 DWORD sampler = state - STATE_SAMPLER(0);
2311 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
2313 if(!texture) return;
2314 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
2315 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
2316 * scaling is reapplied or removed, the texture matrix has to be reapplied
2318 * The mapped stage is alrady active because the sampler() function below, which is part of the
2319 * misc pipeline
2321 if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
2322 if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D ||
2323 stateblock->textureDimensions[sampler] == GL_TEXTURE_RECTANGLE_ARB) {
2324 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
2325 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
2326 texIsPow2 = TRUE;
2328 } else if(stateblock->textureDimensions[sampler] == GL_TEXTURE_CUBE_MAP_ARB) {
2329 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
2330 texIsPow2 = TRUE;
2334 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
2335 context->lastWasPow2Texture[sampler] = texIsPow2;
2336 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stateblock->wineD3DDevice->texUnitMap[sampler]), stateblock, context);
2341 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2342 DWORD sampler = state - STATE_SAMPLER(0);
2343 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
2344 union {
2345 float f;
2346 DWORD d;
2347 } tmpvalue;
2349 TRACE("Sampler: %d\n", sampler);
2350 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
2351 * only has to bind textures and set the per texture states
2354 if (mapped_stage == -1) {
2355 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
2356 return;
2359 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2360 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
2361 return;
2363 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2364 checkGLcall("glActiveTextureARB");
2365 } else if (sampler > 0) {
2366 /* We can't do anything here */
2367 WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2368 return;
2371 if(stateblock->textures[sampler]) {
2372 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
2373 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
2375 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2376 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
2377 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2378 GL_TEXTURE_LOD_BIAS_EXT,
2379 tmpvalue.f);
2380 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
2383 if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
2384 ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
2385 /* Using a pixel shader? Verify the sampler types */
2387 /* Make sure that the texture dimensions are enabled. I don't have to disable the other
2388 * dimensions because the shader knows from which texture type to sample from. For the sake of
2389 * debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
2390 * dimensions. This should make wrong sampling sources visible :-)
2392 glEnable(stateblock->textureDimensions[sampler]);
2393 checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
2394 } else if(sampler < stateblock->lowest_disabled_stage) {
2395 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2396 /* If color keying is enabled update the alpha test, it depends on the existence
2397 * of a color key in stage 0
2399 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2402 } else if(mapped_stage < GL_LIMITS(textures)) {
2403 if(sampler < stateblock->lowest_disabled_stage) {
2404 /* TODO: What should I do with pixel shaders here ??? */
2405 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
2406 /* If color keying is enabled update the alpha test, it depends on the existence
2407 * of a color key in stage 0
2409 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
2411 } /* Otherwise tex_colorop disables the stage */
2412 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
2413 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
2417 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2418 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
2419 BOOL use_pshader = use_ps(device);
2420 BOOL use_vshader = use_vs(device);
2421 BOOL update_fog = FALSE;
2422 int i;
2424 if (use_pshader) {
2425 if(!context->last_was_pshader) {
2426 /* Former draw without a pixel shader, some samplers
2427 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
2428 * make sure to enable them
2430 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
2431 if(!isStateDirty(context, STATE_SAMPLER(i))) {
2432 sampler(STATE_SAMPLER(i), stateblock, context);
2435 update_fog = TRUE;
2436 } else {
2437 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
2438 * if a different texture was bound. I don't have to do anything.
2442 /* Compile and bind the shader */
2443 IWineD3DPixelShader_CompileShader(stateblock->pixelShader);
2444 } else {
2445 /* Disabled the pixel shader - color ops weren't applied
2446 * while it was enabled, so re-apply them.
2448 for(i=0; i < MAX_TEXTURES; i++) {
2449 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
2450 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
2451 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
2454 if(context->last_was_pshader)
2455 update_fog = TRUE;
2458 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
2459 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
2461 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
2462 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
2466 if(update_fog)
2467 state_fog(state, stateblock, context);
2469 context->last_was_pshader = use_pshader;
2472 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2473 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2474 if(stateblock->pixelShader && stage != 0 &&
2475 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
2476 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
2477 * anyway
2479 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
2480 !isStateDirty(context, STATE_PIXELSHADER)) {
2481 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
2486 static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2487 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2488 float mat[2][2];
2489 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2490 if(stage >= GL_LIMITS(texture_stages)) {
2491 WARN("Bump env matrix of unsupported stage set\n");
2492 } else if(GL_SUPPORT(ARB_MULTITEXTURE)) {
2493 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage));
2494 checkGLcall("GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + stage))");
2496 mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
2497 mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
2498 mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
2499 mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
2500 GL_EXTCALL(glTexBumpParameterfvATI(GL_BUMP_ROT_MATRIX_ATI, (float *) mat));
2501 checkGLcall("glTexBumpParameterfvATI");
2505 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2506 /* This function is called by transform_view below if the view matrix was changed too
2508 * Deliberately no check if the vertex declaration is dirty because the vdecl state
2509 * does not always update the world matrix, only on a switch between transformed
2510 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
2511 * draw, but that should be rather rare and cheaper in total.
2513 glMatrixMode(GL_MODELVIEW);
2514 checkGLcall("glMatrixMode");
2516 if(context->last_was_rhw) {
2517 glLoadIdentity();
2518 checkGLcall("glLoadIdentity()");
2519 } else {
2520 /* In the general case, the view matrix is the identity matrix */
2521 if (stateblock->wineD3DDevice->view_ident) {
2522 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2523 checkGLcall("glLoadMatrixf");
2524 } else {
2525 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2526 checkGLcall("glLoadMatrixf");
2527 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
2528 checkGLcall("glMultMatrixf");
2533 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2534 UINT index = state - STATE_CLIPPLANE(0);
2536 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
2537 return;
2540 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2541 glMatrixMode(GL_MODELVIEW);
2542 glPushMatrix();
2543 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2545 TRACE("Clipplane [%f,%f,%f,%f]\n",
2546 stateblock->clipplane[index][0],
2547 stateblock->clipplane[index][1],
2548 stateblock->clipplane[index][2],
2549 stateblock->clipplane[index][3]);
2550 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
2551 checkGLcall("glClipPlane");
2553 glPopMatrix();
2556 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2557 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
2558 GLenum glMat;
2559 TRACE("Setting world matrix %d\n", matrix);
2561 if(matrix >= GL_LIMITS(blends)) {
2562 WARN("Unsupported blend matrix set\n");
2563 return;
2564 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
2565 return;
2568 /* GL_MODELVIEW0_ARB: 0x1700
2569 * GL_MODELVIEW1_ARB: 0x0x850a
2570 * GL_MODELVIEW2_ARB: 0x8722
2571 * GL_MODELVIEW3_ARB: 0x8723
2572 * etc
2573 * GL_MODELVIEW31_ARB: 0x873F
2575 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
2576 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
2578 glMatrixMode(glMat);
2579 checkGLcall("glMatrixMode(glMat)");
2581 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
2582 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
2584 if(stateblock->wineD3DDevice->view_ident) {
2585 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2586 checkGLcall("glLoadMatrixf")
2587 } else {
2588 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2589 checkGLcall("glLoadMatrixf")
2590 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
2591 checkGLcall("glMultMatrixf")
2595 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2596 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2598 switch(val) {
2599 case WINED3DVBF_1WEIGHTS:
2600 case WINED3DVBF_2WEIGHTS:
2601 case WINED3DVBF_3WEIGHTS:
2602 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2603 glEnable(GL_VERTEX_BLEND_ARB);
2604 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2606 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2607 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2609 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2611 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2612 int i;
2613 for(i = 1; i < GL_LIMITS(blends); i++) {
2614 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2615 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2618 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2620 } else {
2621 static BOOL once = FALSE;
2622 if(!once) {
2623 once = TRUE;
2624 /* TODO: Implement vertex blending in drawStridedSlow */
2625 FIXME("Vertex blending enabled, but not supported by hardware\n");
2628 break;
2630 case WINED3DVBF_DISABLE:
2631 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2632 if(GL_SUPPORT(ARB_VERTEX_BLEND)) {
2633 glDisable(GL_VERTEX_BLEND_ARB);
2634 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2635 } else {
2636 TRACE("Vertex blending disabled\n");
2638 break;
2640 case WINED3DVBF_TWEENING:
2641 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2642 * vertex weights in the vertices?
2643 * For now we don't report that as supported, so a warn should suffice
2645 WARN("Tweening not supported yet\n");
2646 break;
2650 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2651 unsigned int k;
2653 /* If we are changing the View matrix, reset the light and clipping planes to the new view
2654 * NOTE: We have to reset the positions even if the light/plane is not currently
2655 * enabled, since the call to enable it will not reset the position.
2656 * NOTE2: Apparently texture transforms do NOT need reapplying
2659 PLIGHTINFOEL *light = NULL;
2661 glMatrixMode(GL_MODELVIEW);
2662 checkGLcall("glMatrixMode(GL_MODELVIEW)");
2663 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2664 checkGLcall("glLoadMatrixf(...)");
2666 /* Reset lights. TODO: Call light apply func */
2667 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2668 light = stateblock->activeLights[k];
2669 if(!light) continue;
2670 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2671 checkGLcall("glLightfv posn");
2672 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2673 checkGLcall("glLightfv dirn");
2676 /* Reset Clipping Planes */
2677 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2678 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2679 clipplane(STATE_CLIPPLANE(k), stateblock, context);
2683 if(context->last_was_rhw) {
2684 glLoadIdentity();
2685 checkGLcall("glLoadIdentity()");
2686 /* No need to update the world matrix, the identity is fine */
2687 return;
2690 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2691 * No need to do it here if the state is scheduled for update.
2693 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2694 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2697 /* Avoid looping over a number of matrices if the app never used the functionality */
2698 if(stateblock->wineD3DDevice->vertexBlendUsed) {
2699 for(k = 1; k < GL_LIMITS(blends); k++) {
2700 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2701 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2707 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2708 glMatrixMode(GL_PROJECTION);
2709 checkGLcall("glMatrixMode(GL_PROJECTION)");
2710 glLoadIdentity();
2711 checkGLcall("glLoadIdentity");
2713 if(context->last_was_rhw) {
2714 double X, Y, height, width, minZ, maxZ;
2716 X = stateblock->viewport.X;
2717 Y = stateblock->viewport.Y;
2718 height = stateblock->viewport.Height;
2719 width = stateblock->viewport.Width;
2720 minZ = stateblock->viewport.MinZ;
2721 maxZ = stateblock->viewport.MaxZ;
2723 if(!stateblock->wineD3DDevice->untransformed) {
2724 /* Transformed vertices are supposed to bypass the whole transform pipeline including
2725 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2726 * suppress depth clipping. This can be done because it is an orthogonal projection and
2727 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2728 * Persia 3D need this.
2730 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2731 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2732 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2733 * to the viewer.
2735 * Also note that this breaks z comparison against z values filled in with clear,
2736 * but no app depending on that and disabled clipping has been found yet. Comparing
2737 * primitives against themselves works, so the Z buffer is still intact for normal hidden
2738 * surface removal.
2740 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2741 * but this would break Z buffer operation. Raising the range to something less than
2742 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2743 * problem either.
2745 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2746 if(stateblock->wineD3DDevice->render_offscreen) {
2747 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2748 } else {
2749 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2751 } else {
2752 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2753 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2754 * unmodified to opengl.
2756 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2757 * replacement shader.
2759 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2760 if(stateblock->wineD3DDevice->render_offscreen) {
2761 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2762 } else {
2763 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2766 checkGLcall("glOrtho");
2768 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2769 glTranslatef(0.5, 0.5, 0);
2770 checkGLcall("glTranslatef(0.5, 0.5, 0)");
2771 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2772 * render everything upside down when rendering offscreen. */
2773 if (stateblock->wineD3DDevice->render_offscreen) {
2774 glScalef(1.0, -1.0, 1.0);
2775 checkGLcall("glScalef");
2777 } else {
2778 /* The rule is that the window coordinate 0 does not correspond to the
2779 beginning of the first pixel, but the center of the first pixel.
2780 As a consequence if you want to correctly draw one line exactly from
2781 the left to the right end of the viewport (with all matrices set to
2782 be identity), the x coords of both ends of the line would be not
2783 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2784 instead.
2786 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2787 divide by the Width/Height, so we need the half range(1.0) to translate by
2788 half a pixel.
2790 The other fun is that d3d's output z range after the transformation is [0;1],
2791 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2792 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2793 of Z buffer precision and the clear values do not match in the z test. Thus scale
2794 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2796 glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2797 checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2798 if (stateblock->wineD3DDevice->render_offscreen) {
2799 /* D3D texture coordinates are flipped compared to OpenGL ones, so
2800 * render everything upside down when rendering offscreen. */
2801 glScalef(1.0, -1.0, 2.0);
2802 } else {
2803 glScalef(1.0, 1.0, 2.0);
2805 checkGLcall("glScalef");
2807 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2808 checkGLcall("glLoadMatrixf");
2812 /* This should match any arrays loaded in loadVertexData.
2813 * stateblock impl is required for GL_SUPPORT
2814 * TODO: Only load / unload arrays if we have to.
2816 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2817 glDisableClientState(GL_VERTEX_ARRAY);
2818 glDisableClientState(GL_NORMAL_ARRAY);
2819 glDisableClientState(GL_COLOR_ARRAY);
2820 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2821 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2823 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2824 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2825 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
2826 glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
2828 unloadTexCoords(stateblock);
2831 /* This should match any arrays loaded in loadNumberedArrays
2832 * TODO: Only load / unload arrays if we have to.
2834 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2835 /* disable any attribs (this is the same for both GLSL and ARB modes) */
2836 GLint maxAttribs = 16;
2837 int i;
2839 /* Leave all the attribs disabled */
2840 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2841 /* MESA does not support it right not */
2842 if (glGetError() != GL_NO_ERROR)
2843 maxAttribs = 16;
2844 for (i = 0; i < maxAttribs; ++i) {
2845 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2846 checkGLcall("glDisableVertexAttribArrayARB(reg)");
2847 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
2848 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
2849 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
2850 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
2851 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
2853 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
2854 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
2858 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2859 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2860 int i;
2861 UINT *offset = stateblock->streamOffset;
2862 IWineD3DVertexBufferImpl *vb;
2863 DWORD_PTR shift_index;
2865 /* Default to no instancing */
2866 stateblock->wineD3DDevice->instancedDraw = FALSE;
2868 for (i = 0; i < MAX_ATTRIBS; i++) {
2870 if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2871 continue;
2873 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2874 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2875 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2876 stateblock->wineD3DDevice->instancedDraw = TRUE;
2877 continue;
2880 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2882 if(strided->u.input[i].dwStride) {
2883 if(curVBO != strided->u.input[i].VBO) {
2884 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2885 checkGLcall("glBindBufferARB");
2886 curVBO = strided->u.input[i].VBO;
2888 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2889 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
2890 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
2891 * vbo we won't be load converted attributes anyway
2893 if(curVBO && vb->conv_shift) {
2894 TRACE("Loading attribute from shifted buffer\n");
2895 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
2896 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
2897 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
2898 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
2899 shift_index = shift_index % strided->u.input[i].dwStride;
2900 GL_EXTCALL(glVertexAttribPointerARB(i,
2901 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2902 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2903 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2904 vb->conv_stride,
2906 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
2907 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2908 offset[strided->u.input[i].streamNo]));
2910 } else {
2911 GL_EXTCALL(glVertexAttribPointerARB(i,
2912 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2913 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2914 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2915 strided->u.input[i].dwStride,
2917 strided->u.input[i].lpData +
2918 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2919 offset[strided->u.input[i].streamNo]) );
2921 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2922 } else {
2923 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2924 * set up the attribute statically. But we have to figure out the system memory address.
2926 BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2927 if(strided->u.input[i].VBO) {
2928 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2929 ptr += (long) vb->resource.allocatedMemory;
2931 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2933 switch(strided->u.input[i].dwType) {
2934 case WINED3DDECLTYPE_FLOAT1:
2935 GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2936 break;
2937 case WINED3DDECLTYPE_FLOAT2:
2938 GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2939 break;
2940 case WINED3DDECLTYPE_FLOAT3:
2941 GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2942 break;
2943 case WINED3DDECLTYPE_FLOAT4:
2944 GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2945 break;
2947 case WINED3DDECLTYPE_UBYTE4:
2948 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2949 break;
2950 case WINED3DDECLTYPE_UBYTE4N:
2951 case WINED3DDECLTYPE_D3DCOLOR:
2952 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2953 break;
2955 case WINED3DDECLTYPE_SHORT2:
2956 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2957 break;
2958 case WINED3DDECLTYPE_SHORT4:
2959 GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2960 break;
2962 case WINED3DDECLTYPE_SHORT2N:
2964 GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
2965 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
2966 break;
2968 case WINED3DDECLTYPE_USHORT2N:
2970 GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
2971 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
2972 break;
2974 case WINED3DDECLTYPE_SHORT4N:
2975 GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
2976 break;
2977 case WINED3DDECLTYPE_USHORT4N:
2978 GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
2979 break;
2981 case WINED3DDECLTYPE_UDEC3:
2982 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
2983 /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
2984 break;
2985 case WINED3DDECLTYPE_DEC3N:
2986 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
2987 /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
2988 break;
2990 case WINED3DDECLTYPE_FLOAT16_2:
2991 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
2992 * byte float according to the IEEE standard
2994 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
2995 break;
2996 case WINED3DDECLTYPE_FLOAT16_4:
2997 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
2998 break;
3000 case WINED3DDECLTYPE_UNUSED:
3001 default:
3002 ERR("Unexpected declaration in stride 0 attributes\n");
3003 break;
3008 checkGLcall("Loading numbered arrays");
3011 /* Used from 2 different functions, and too big to justify making it inlined */
3012 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3013 UINT *offset = stateblock->streamOffset;
3014 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3016 TRACE("Using fast vertex array code\n");
3018 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3019 stateblock->wineD3DDevice->instancedDraw = FALSE;
3021 /* Blend Data ---------------------------------------------- */
3022 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3023 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3025 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3026 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3027 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3029 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3030 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3032 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3034 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3035 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3036 sd->u.s.blendWeights.dwStride,
3037 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3039 if(curVBO != sd->u.s.blendWeights.VBO) {
3040 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3041 checkGLcall("glBindBufferARB");
3042 curVBO = sd->u.s.blendWeights.VBO;
3045 GL_EXTCALL(glWeightPointerARB)(
3046 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3047 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3048 sd->u.s.blendWeights.dwStride,
3049 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3051 checkGLcall("glWeightPointerARB");
3053 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3054 static BOOL showfixme = TRUE;
3055 if(showfixme){
3056 FIXME("blendMatrixIndices support\n");
3057 showfixme = FALSE;
3060 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
3061 /* FIXME("TODO\n");*/
3062 #if 0
3064 GL_EXTCALL(glVertexWeightPointerEXT)(
3065 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3066 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3067 sd->u.s.blendWeights.dwStride,
3068 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
3069 checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
3070 glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
3071 checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
3072 #endif
3074 } else {
3075 /* TODO: support blends in drawStridedSlow
3076 * No need to write a FIXME here, this is done after the general vertex decl decoding
3078 WARN("unsupported blending in openGl\n");
3080 } else {
3081 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3082 static const GLbyte one = 1;
3083 GL_EXTCALL(glWeightbvARB(1, &one));
3084 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3088 #if 0 /* FOG ----------------------------------------------*/
3089 if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3090 /* TODO: fog*/
3091 if (GL_SUPPORT(EXT_FOG_COORD) {
3092 glEnableClientState(GL_FOG_COORDINATE_EXT);
3093 (GL_EXTCALL)(FogCoordPointerEXT)(
3094 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3095 sd->u.s.fog.dwStride,
3096 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3097 } else {
3098 /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3099 /* FIXME: fixme once */
3100 TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3102 } else {
3103 if (GL_SUPPRT(EXT_FOR_COORD) {
3104 /* make sure fog is disabled */
3105 glDisableClientState(GL_FOG_COORDINATE_EXT);
3108 #endif
3110 #if 0 /* tangents ----------------------------------------------*/
3111 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3112 sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3113 /* TODO: tangents*/
3114 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3115 if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3116 glEnable(GL_TANGENT_ARRAY_EXT);
3117 (GL_EXTCALL)(TangentPointerEXT)(
3118 WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3119 sd->u.s.tangent.dwStride,
3120 sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3121 } else {
3122 glDisable(GL_TANGENT_ARRAY_EXT);
3124 if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3125 glEnable(GL_BINORMAL_ARRAY_EXT);
3126 (GL_EXTCALL)(BinormalPointerEXT)(
3127 WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3128 sd->u.s.binormal.dwStride,
3129 sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3130 } else{
3131 glDisable(GL_BINORMAL_ARRAY_EXT);
3134 } else {
3135 /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3136 /* FIXME: fixme once */
3137 TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3139 } else {
3140 if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3141 /* make sure fog is disabled */
3142 glDisable(GL_TANGENT_ARRAY_EXT);
3143 glDisable(GL_BINORMAL_ARRAY_EXT);
3146 #endif
3148 /* Point Size ----------------------------------------------*/
3149 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3151 /* no such functionality in the fixed function GL pipeline */
3152 TRACE("Cannot change ptSize here in openGl\n");
3153 /* TODO: Implement this function in using shaders if they are available */
3157 /* Vertex Pointers -----------------------------------------*/
3158 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3159 /* Note dwType == float3 or float4 == 2 or 3 */
3160 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3161 sd->u.s.position.dwStride,
3162 sd->u.s.position.dwType + 1,
3163 sd->u.s.position.lpData));
3165 if(curVBO != sd->u.s.position.VBO) {
3166 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3167 checkGLcall("glBindBufferARB");
3168 curVBO = sd->u.s.position.VBO;
3171 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3172 handling for rhw mode should not impact screen position whereas in GL it does.
3173 This may result in very slightly distorted textures in rhw mode.
3174 There's always the other option of fixing the view matrix to
3175 prevent w from having any effect.
3177 This only applies to user pointer sources, in VBOs the vertices are fixed up
3179 if(sd->u.s.position.VBO == 0) {
3180 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3181 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3182 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3183 } else {
3184 glVertexPointer(
3185 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3186 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3187 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3189 checkGLcall("glVertexPointer(...)");
3190 glEnableClientState(GL_VERTEX_ARRAY);
3191 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3194 /* Normals -------------------------------------------------*/
3195 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3196 /* Note dwType == float3 or float4 == 2 or 3 */
3197 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3198 sd->u.s.normal.dwStride,
3199 sd->u.s.normal.lpData));
3200 if(curVBO != sd->u.s.normal.VBO) {
3201 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3202 checkGLcall("glBindBufferARB");
3203 curVBO = sd->u.s.normal.VBO;
3205 glNormalPointer(
3206 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3207 sd->u.s.normal.dwStride,
3208 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3209 checkGLcall("glNormalPointer(...)");
3210 glEnableClientState(GL_NORMAL_ARRAY);
3211 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3213 } else {
3214 glNormal3f(0, 0, 0);
3215 checkGLcall("glNormal3f(0, 0, 0)");
3218 /* Diffuse Colour --------------------------------------------*/
3219 /* WARNING: Data here MUST be in RGBA format, so cannot */
3220 /* go directly into fast mode from app pgm, because */
3221 /* directx requires data in BGRA format. */
3222 /* currently fixupVertices swizzles the format, but this isn't*/
3223 /* very practical when using VBOs */
3224 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3225 /* , or the user doesn't care and wants the speed advantage */
3227 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3228 /* Note dwType == float3 or float4 == 2 or 3 */
3229 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3230 sd->u.s.diffuse.dwStride,
3231 sd->u.s.diffuse.lpData));
3233 if(curVBO != sd->u.s.diffuse.VBO) {
3234 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3235 checkGLcall("glBindBufferARB");
3236 curVBO = sd->u.s.diffuse.VBO;
3239 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3240 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3241 sd->u.s.diffuse.dwStride,
3242 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3243 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3244 glEnableClientState(GL_COLOR_ARRAY);
3245 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3247 } else {
3248 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3249 checkGLcall("glColor4f(1, 1, 1, 1)");
3252 /* Specular Colour ------------------------------------------*/
3253 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3254 TRACE("setting specular colour\n");
3255 /* Note dwType == float3 or float4 == 2 or 3 */
3256 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3257 sd->u.s.specular.dwStride,
3258 sd->u.s.specular.lpData));
3259 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3260 if(curVBO != sd->u.s.specular.VBO) {
3261 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3262 checkGLcall("glBindBufferARB");
3263 curVBO = sd->u.s.specular.VBO;
3265 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3266 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3267 sd->u.s.specular.dwStride,
3268 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3269 vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3270 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3271 vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3272 } else {
3274 /* Missing specular color is not critical, no warnings */
3275 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3278 } else {
3279 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3280 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3281 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
3282 } else {
3284 /* Missing specular color is not critical, no warnings */
3285 VTRACE(("Specular colour is not supported in this GL implementation\n"));
3289 /* Texture coords -------------------------------------------*/
3290 loadTexCoords(stateblock, sd, &curVBO);
3293 static inline void drawPrimitiveTraceDataLocations(
3294 WineDirect3DVertexStridedData *dataLocations) {
3296 /* Dump out what parts we have supplied */
3297 TRACE("Strided Data:\n");
3298 TRACE_STRIDED((dataLocations), position);
3299 TRACE_STRIDED((dataLocations), blendWeights);
3300 TRACE_STRIDED((dataLocations), blendMatrixIndices);
3301 TRACE_STRIDED((dataLocations), normal);
3302 TRACE_STRIDED((dataLocations), pSize);
3303 TRACE_STRIDED((dataLocations), diffuse);
3304 TRACE_STRIDED((dataLocations), specular);
3305 TRACE_STRIDED((dataLocations), texCoords[0]);
3306 TRACE_STRIDED((dataLocations), texCoords[1]);
3307 TRACE_STRIDED((dataLocations), texCoords[2]);
3308 TRACE_STRIDED((dataLocations), texCoords[3]);
3309 TRACE_STRIDED((dataLocations), texCoords[4]);
3310 TRACE_STRIDED((dataLocations), texCoords[5]);
3311 TRACE_STRIDED((dataLocations), texCoords[6]);
3312 TRACE_STRIDED((dataLocations), texCoords[7]);
3313 TRACE_STRIDED((dataLocations), position2);
3314 TRACE_STRIDED((dataLocations), normal2);
3315 TRACE_STRIDED((dataLocations), tangent);
3316 TRACE_STRIDED((dataLocations), binormal);
3317 TRACE_STRIDED((dataLocations), tessFactor);
3318 TRACE_STRIDED((dataLocations), fog);
3319 TRACE_STRIDED((dataLocations), depth);
3320 TRACE_STRIDED((dataLocations), sample);
3322 return;
3325 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3326 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3327 BOOL fixup = FALSE;
3328 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3329 BOOL useVertexShaderFunction;
3331 if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3332 ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3333 useVertexShaderFunction = TRUE;
3334 } else {
3335 useVertexShaderFunction = FALSE;
3339 if(device->up_strided) {
3340 /* Note: this is a ddraw fixed-function code path */
3341 TRACE("================ Strided Input ===================\n");
3342 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3344 if(TRACE_ON(d3d)) {
3345 drawPrimitiveTraceDataLocations(dataLocations);
3347 } else {
3348 /* Note: This is a fixed function or shader codepath.
3349 * This means it must handle both types of strided data.
3350 * Shaders must go through here to zero the strided data, even if they
3351 * don't set any declaration at all
3353 TRACE("================ Vertex Declaration ===================\n");
3354 memset(dataLocations, 0, sizeof(*dataLocations));
3355 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3356 useVertexShaderFunction, dataLocations, &fixup);
3359 if (dataLocations->u.s.position_transformed) {
3360 useVertexShaderFunction = FALSE;
3363 /* Unload the old arrays before loading the new ones to get old junk out */
3364 if(context->numberedArraysLoaded) {
3365 unloadNumberedArrays(stateblock);
3366 context->numberedArraysLoaded = FALSE;
3368 if(context->namedArraysLoaded) {
3369 unloadVertexData(stateblock);
3370 context->namedArraysLoaded = FALSE;
3373 if(useVertexShaderFunction) {
3374 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3375 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3376 device->useDrawStridedSlow = TRUE;
3377 context->numberedArraysLoaded = FALSE;
3378 } else {
3379 TRACE("Loading numbered arrays\n");
3380 loadNumberedArrays(stateblock, dataLocations);
3381 device->useDrawStridedSlow = FALSE;
3382 context->numberedArraysLoaded = TRUE;
3384 } else if (fixup ||
3385 (dataLocations->u.s.pSize.lpData == NULL &&
3386 dataLocations->u.s.diffuse.lpData == NULL &&
3387 dataLocations->u.s.specular.lpData == NULL)) {
3388 /* Load the vertex data using named arrays */
3389 TRACE("Loading vertex data\n");
3390 loadVertexData(stateblock, dataLocations);
3391 device->useDrawStridedSlow = FALSE;
3392 context->namedArraysLoaded = TRUE;
3393 } else {
3394 TRACE("Not loading vertex data\n");
3395 device->useDrawStridedSlow = TRUE;
3398 /* Generate some fixme's if unsupported functionality is being used */
3399 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3400 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3401 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3402 FIXME("Tweening is only valid with vertex shaders\n");
3404 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3405 FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3407 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3408 FIXME("Extended attributes are only valid with vertex shaders\n");
3410 #undef BUFFER_OR_DATA
3413 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3414 BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3415 BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3416 && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3417 BOOL transformed;
3418 /* Some stuff is in the device until we have per context tracking */
3419 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3420 BOOL wasrhw = context->last_was_rhw;
3422 /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3423 * here simply check whether a shader was set, or the user disabled shaders
3425 if (use_vs(device)) {
3426 useVertexShaderFunction = TRUE;
3428 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3429 updateFog = TRUE;
3431 } else if(context->last_was_foggy_shader) {
3432 updateFog = TRUE;
3435 transformed = device->strided_streams.u.s.position_transformed;
3436 if (transformed) useVertexShaderFunction = FALSE;
3438 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3439 updateFog = TRUE;
3442 /* Reapply lighting if it is not scheduled for reapplication already */
3443 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3444 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3447 if (transformed) {
3448 context->last_was_rhw = TRUE;
3449 } else {
3451 /* Untransformed, so relies on the view and projection matrices */
3452 context->last_was_rhw = FALSE;
3453 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3454 device->untransformed = TRUE;
3456 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3457 * Not needed as long as only hw shaders are supported
3460 /* This sets the shader output position correction constants.
3461 * TODO: Move to the viewport state
3463 if (useVertexShaderFunction) {
3464 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3465 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3469 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3470 * off this function will be called again anyway to make sure they're properly set
3472 if(!useVertexShaderFunction) {
3473 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3474 * or transformed / untransformed was switched
3476 if(wasrhw != context->last_was_rhw &&
3477 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3478 !isStateDirty(context, STATE_VIEWPORT)) {
3479 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3481 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3482 * mode.
3484 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3485 * this check will fail and the matrix not applied again. This is OK because a simple
3486 * world matrix change reapplies the matrix - These checks here are only to satisfy the
3487 * needs of the vertex declaration.
3489 * World and view matrix go into the same gl matrix, so only apply them when neither is
3490 * dirty
3492 if(transformed != wasrhw &&
3493 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3494 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3495 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3498 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3499 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3502 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3503 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3505 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3506 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3508 } else {
3509 /* We compile the shader here because we need the vertex declaration
3510 * in order to determine if we need to do any swizzling for D3DCOLOR
3511 * registers. If the shader is already compiled this call will do nothing. */
3512 IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3514 if(!context->last_was_vshader) {
3515 int i;
3516 static BOOL warned = FALSE;
3517 /* Disable all clip planes to get defined results on all drivers. See comment in the
3518 * state_clipping state handler
3520 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3521 glDisable(GL_CLIP_PLANE0 + i);
3522 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3525 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3526 FIXME("Clipping not supported with vertex shaders\n");
3527 warned = TRUE;
3529 if(wasrhw) {
3530 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3531 * shaders themselves do not need it, but the matrices are not reapplied automatically when
3532 * switching back from vertex shaders to fixed function processing. So make sure we leave the
3533 * fixed function vertex processing states back in a sane state before switching to shaders
3535 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3536 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3538 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3539 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3545 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3546 * application
3548 if (!isStateDirty(context, STATE_PIXELSHADER)) {
3549 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3551 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3552 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3556 context->last_was_vshader = useVertexShaderFunction;
3558 if(updateFog) {
3559 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3561 if(!useVertexShaderFunction) {
3562 int i;
3563 for(i = 0; i < MAX_TEXTURES; i++) {
3564 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3565 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3571 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3572 UINT width, height;
3573 IWineD3DSurfaceImpl *target;
3575 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3576 checkGLcall("glDepthRange");
3577 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3579 if(stateblock->wineD3DDevice->render_offscreen) {
3580 glViewport(stateblock->viewport.X,
3581 stateblock->viewport.Y,
3582 stateblock->viewport.Width, stateblock->viewport.Height);
3583 } else {
3584 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3585 target->get_drawable_size(target, &width, &height);
3587 glViewport(stateblock->viewport.X,
3588 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3589 stateblock->viewport.Width, stateblock->viewport.Height);
3592 checkGLcall("glViewport");
3595 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3596 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3597 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3598 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3599 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3601 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3602 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3606 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3607 UINT Index = state - STATE_ACTIVELIGHT(0);
3608 PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3610 if(!lightInfo) {
3611 glDisable(GL_LIGHT0 + Index);
3612 checkGLcall("glDisable(GL_LIGHT0 + Index)");
3613 } else {
3614 float quad_att;
3615 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3617 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3618 glMatrixMode(GL_MODELVIEW);
3619 glPushMatrix();
3620 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3622 /* Diffuse: */
3623 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3624 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3625 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3626 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3627 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3628 checkGLcall("glLightfv");
3630 /* Specular */
3631 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3632 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3633 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3634 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3635 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3636 checkGLcall("glLightfv");
3638 /* Ambient */
3639 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3640 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3641 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3642 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3643 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3644 checkGLcall("glLightfv");
3646 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3647 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3648 } else {
3649 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
3652 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3653 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3654 * Attenuation0 to NaN and crashes in the gl lib
3657 switch (lightInfo->OriginalParms.Type) {
3658 case WINED3DLIGHT_POINT:
3659 /* Position */
3660 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3661 checkGLcall("glLightfv");
3662 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3663 checkGLcall("glLightf");
3664 /* Attenuation - Are these right? guessing... */
3665 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3666 checkGLcall("glLightf");
3667 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3668 checkGLcall("glLightf");
3669 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3670 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3671 checkGLcall("glLightf");
3672 /* FIXME: Range */
3673 break;
3675 case WINED3DLIGHT_SPOT:
3676 /* Position */
3677 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3678 checkGLcall("glLightfv");
3679 /* Direction */
3680 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3681 checkGLcall("glLightfv");
3682 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3683 checkGLcall("glLightf");
3684 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3685 checkGLcall("glLightf");
3686 /* Attenuation - Are these right? guessing... */
3687 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
3688 checkGLcall("glLightf");
3689 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
3690 checkGLcall("glLightf");
3691 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3692 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3693 checkGLcall("glLightf");
3694 /* FIXME: Range */
3695 break;
3697 case WINED3DLIGHT_DIRECTIONAL:
3698 /* Direction */
3699 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3700 checkGLcall("glLightfv");
3701 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3702 checkGLcall("glLightf");
3703 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3704 checkGLcall("glLightf");
3705 break;
3707 default:
3708 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3711 /* Restore the modelview matrix */
3712 glPopMatrix();
3714 glEnable(GL_LIGHT0 + Index);
3715 checkGLcall("glEnable(GL_LIGHT0 + Index)");
3718 return;
3721 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3722 RECT *pRect = &stateblock->scissorRect;
3723 UINT height;
3724 UINT width;
3725 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3727 target->get_drawable_size(target, &width, &height);
3728 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3729 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3731 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3732 pRect->right - pRect->left, pRect->bottom - pRect->top);
3734 if (stateblock->wineD3DDevice->render_offscreen) {
3735 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3736 } else {
3737 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3739 checkGLcall("glScissor");
3742 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3743 if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3744 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3745 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3746 } else {
3747 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3748 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3753 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3754 if(stateblock->wineD3DDevice->render_offscreen) {
3755 glFrontFace(GL_CCW);
3756 checkGLcall("glFrontFace(GL_CCW)");
3757 } else {
3758 glFrontFace(GL_CW);
3759 checkGLcall("glFrontFace(GL_CW)");
3763 const struct StateEntryTemplate misc_state_template[] = {
3764 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3765 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3766 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3767 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3768 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3769 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3770 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3771 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3772 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3773 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
3774 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
3775 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
3776 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
3777 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
3778 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
3779 * vshader loadings are untied from each other
3781 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
3782 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
3783 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3784 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3785 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3786 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3787 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3788 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3789 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3790 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3791 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3792 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3793 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3794 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3795 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3796 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3797 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3798 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3799 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3800 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3801 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3802 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3803 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3804 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3805 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3806 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3807 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3808 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3809 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3810 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3811 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3812 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3813 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3814 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
3815 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3816 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3817 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3818 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3819 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3820 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3821 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3822 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3823 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3824 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3825 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3826 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3827 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3828 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3829 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
3830 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), tex_bumpenvloffset }, 0 },
3832 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
3833 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, 0 },
3834 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
3835 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
3836 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
3837 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
3838 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
3839 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
3840 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
3841 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
3842 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
3843 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
3844 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
3845 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
3846 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3847 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3848 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3849 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
3850 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
3851 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
3852 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
3853 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
3854 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
3855 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
3856 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
3857 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
3858 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
3859 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
3860 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
3861 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
3862 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
3863 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3864 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3865 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3866 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3867 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3868 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3869 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3870 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
3871 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3872 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3873 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3874 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3875 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
3876 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3877 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3878 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3879 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3880 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3881 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3882 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3883 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3884 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3885 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3886 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3887 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3888 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3889 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3890 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3891 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
3892 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
3893 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
3894 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
3895 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
3896 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
3897 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
3898 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3899 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3900 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3901 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3902 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3903 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3904 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
3905 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_multisampleaa }, 0 },
3906 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
3907 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3908 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, 0 },
3909 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
3910 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
3911 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3912 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3913 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
3914 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, 0 },
3915 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
3916 /* Samplers */
3917 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
3918 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
3919 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
3920 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
3921 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
3922 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
3923 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
3924 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
3925 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
3926 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
3927 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
3928 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
3929 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
3930 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
3931 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
3932 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
3933 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
3934 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
3935 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
3936 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
3937 {0 /* Terminate */, { 0, 0 }, 0 },
3940 const struct StateEntryTemplate ffp_vertexstate_template[] = {
3941 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
3942 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
3943 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
3944 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
3945 /* Clip planes */
3946 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
3947 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
3948 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
3949 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
3950 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
3951 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
3952 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
3953 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
3954 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
3955 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
3956 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
3957 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
3958 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
3959 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
3960 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
3961 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
3962 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
3963 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
3964 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
3965 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
3966 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
3967 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
3968 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
3969 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
3970 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
3971 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
3972 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
3973 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
3974 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
3975 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
3976 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
3977 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
3978 /* Lights */
3979 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
3980 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
3981 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
3982 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
3983 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
3984 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
3985 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
3986 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
3987 /* Viewport */
3988 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
3989 /* Transform states follow */
3990 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
3991 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
3992 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, 0 },
3993 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, 0 },
3994 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, 0 },
3995 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, 0 },
3996 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, 0 },
3997 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, 0 },
3998 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, 0 },
3999 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, 0 },
4000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_world }, 0 },
4002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_world }, 0 },
4003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_world }, 0 },
4004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_world }, 0 },
4005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_world }, 0 },
4006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_world }, 0 },
4007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_world }, 0 },
4008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_world }, 0 },
4009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_world }, 0 },
4010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_world }, 0 },
4011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_world }, 0 },
4012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_world }, 0 },
4013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_world }, 0 },
4014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_world }, 0 },
4015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_world }, 0 },
4016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_world }, 0 },
4017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_world }, 0 },
4018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_world }, 0 },
4019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_world }, 0 },
4020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_world }, 0 },
4021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_world }, 0 },
4022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_world }, 0 },
4023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_world }, 0 },
4024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_world }, 0 },
4025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_world }, 0 },
4026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_world }, 0 },
4027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_world }, 0 },
4028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_world }, 0 },
4029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_world }, 0 },
4030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_world }, 0 },
4031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_world }, 0 },
4032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_world }, 0 },
4033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_world }, 0 },
4034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_world }, 0 },
4035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_world }, 0 },
4036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_world }, 0 },
4037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_world }, 0 },
4038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_world }, 0 },
4039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_world }, 0 },
4040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_world }, 0 },
4041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_world }, 0 },
4042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_world }, 0 },
4043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_world }, 0 },
4044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_world }, 0 },
4045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_world }, 0 },
4046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_world }, 0 },
4047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_world }, 0 },
4048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_world }, 0 },
4049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_world }, 0 },
4050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_world }, 0 },
4051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_world }, 0 },
4052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_world }, 0 },
4053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_world }, 0 },
4054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_world }, 0 },
4055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_world }, 0 },
4056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_world }, 0 },
4057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_world }, 0 },
4058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_world }, 0 },
4059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_world }, 0 },
4060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_world }, 0 },
4061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_world }, 0 },
4062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_world }, 0 },
4063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_world }, 0 },
4064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_world }, 0 },
4065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_world }, 0 },
4066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_world }, 0 },
4067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_world }, 0 },
4068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_world }, 0 },
4069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_world }, 0 },
4070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_world }, 0 },
4071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_world }, 0 },
4072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_world }, 0 },
4073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_world }, 0 },
4074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_world }, 0 },
4075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_world }, 0 },
4076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_world }, 0 },
4077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_world }, 0 },
4078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_world }, 0 },
4079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_world }, 0 },
4080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_world }, 0 },
4081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_world }, 0 },
4082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_world }, 0 },
4083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_world }, 0 },
4084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_world }, 0 },
4085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_world }, 0 },
4086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_world }, 0 },
4087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_world }, 0 },
4088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_world }, 0 },
4089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_world }, 0 },
4090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_world }, 0 },
4091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_world }, 0 },
4092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_world }, 0 },
4093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_world }, 0 },
4094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_world }, 0 },
4095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_world }, 0 },
4096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_world }, 0 },
4097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_world }, 0 },
4098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_world }, 0 },
4099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_world }, 0 },
4100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_world }, 0 },
4101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_world }, 0 },
4102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_world }, 0 },
4103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_world }, 0 },
4104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_world }, 0 },
4105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_world }, 0 },
4106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_world }, 0 },
4107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_world }, 0 },
4108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_world }, 0 },
4109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_world }, 0 },
4110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_world }, 0 },
4111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_world }, 0 },
4112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_world }, 0 },
4113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_world }, 0 },
4114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_world }, 0 },
4115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_world }, 0 },
4116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_world }, 0 },
4117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_world }, 0 },
4118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_world }, 0 },
4119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_world }, 0 },
4120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_world }, 0 },
4121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_world }, 0 },
4122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_world }, 0 },
4123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_world }, 0 },
4124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_world }, 0 },
4125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_world }, 0 },
4126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_world }, 0 },
4127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_world }, 0 },
4128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_world }, 0 },
4129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_world }, 0 },
4130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_world }, 0 },
4131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_world }, 0 },
4132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_world }, 0 },
4133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_world }, 0 },
4134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_world }, 0 },
4135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_world }, 0 },
4136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_world }, 0 },
4137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_world }, 0 },
4138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_world }, 0 },
4139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_world }, 0 },
4140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_world }, 0 },
4141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_world }, 0 },
4142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_world }, 0 },
4143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_world }, 0 },
4144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_world }, 0 },
4145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_world }, 0 },
4146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_world }, 0 },
4147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_world }, 0 },
4148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_world }, 0 },
4149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_world }, 0 },
4150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_world }, 0 },
4151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_world }, 0 },
4152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_world }, 0 },
4153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_world }, 0 },
4154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_world }, 0 },
4155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_world }, 0 },
4156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_world }, 0 },
4157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_world }, 0 },
4158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_world }, 0 },
4159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_world }, 0 },
4160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_world }, 0 },
4161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_world }, 0 },
4162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_world }, 0 },
4163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_world }, 0 },
4164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_world }, 0 },
4165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_world }, 0 },
4166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_world }, 0 },
4167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_world }, 0 },
4168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_world }, 0 },
4169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_world }, 0 },
4170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_world }, 0 },
4171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_world }, 0 },
4172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_world }, 0 },
4173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_world }, 0 },
4174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_world }, 0 },
4175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_world }, 0 },
4176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_world }, 0 },
4177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_world }, 0 },
4178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_world }, 0 },
4179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_world }, 0 },
4180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_world }, 0 },
4181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_world }, 0 },
4182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_world }, 0 },
4183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_world }, 0 },
4184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_world }, 0 },
4185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_world }, 0 },
4186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_world }, 0 },
4187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_world }, 0 },
4188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_world }, 0 },
4189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_world }, 0 },
4190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_world }, 0 },
4191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_world }, 0 },
4192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_world }, 0 },
4193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_world }, 0 },
4194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_world }, 0 },
4195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_world }, 0 },
4196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_world }, 0 },
4197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_world }, 0 },
4198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_world }, 0 },
4199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_world }, 0 },
4200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_world }, 0 },
4201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_world }, 0 },
4202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_world }, 0 },
4203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_world }, 0 },
4204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_world }, 0 },
4205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_world }, 0 },
4206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_world }, 0 },
4207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_world }, 0 },
4208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_world }, 0 },
4209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_world }, 0 },
4210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_world }, 0 },
4211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_world }, 0 },
4212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_world }, 0 },
4213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_world }, 0 },
4214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_world }, 0 },
4215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_world }, 0 },
4216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_world }, 0 },
4217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_world }, 0 },
4218 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_world }, 0 },
4219 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_world }, 0 },
4220 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_world }, 0 },
4221 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_world }, 0 },
4222 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_world }, 0 },
4223 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_world }, 0 },
4224 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_world }, 0 },
4225 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_world }, 0 },
4226 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_world }, 0 },
4227 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_world }, 0 },
4228 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_world }, 0 },
4229 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_world }, 0 },
4230 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_world }, 0 },
4231 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_world }, 0 },
4232 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_world }, 0 },
4233 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_world }, 0 },
4234 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_world }, 0 },
4235 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_world }, 0 },
4236 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_world }, 0 },
4237 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_world }, 0 },
4238 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_world }, 0 },
4239 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_world }, 0 },
4240 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_world }, 0 },
4241 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_world }, 0 },
4242 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_world }, 0 },
4243 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_world }, 0 },
4244 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_world }, 0 },
4245 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_world }, 0 },
4246 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_world }, 0 },
4247 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_world }, 0 },
4248 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_world }, 0 },
4249 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_world }, 0 },
4250 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_world }, 0 },
4251 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_world }, 0 },
4252 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_world }, 0 },
4253 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_world }, 0 },
4254 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_world }, 0 },
4255 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_world }, 0 },
4256 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE0), transform_texture }, 0 },
4257 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE1), transform_texture }, 0 },
4258 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE2), transform_texture }, 0 },
4259 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE3), transform_texture }, 0 },
4260 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE4), transform_texture }, 0 },
4261 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE5), transform_texture }, 0 },
4262 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE6), transform_texture }, 0 },
4263 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE7), transform_texture }, 0 },
4264 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4265 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4266 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4267 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4268 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4269 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4270 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4271 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
4272 /* Fog */
4273 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4274 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4275 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4276 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4277 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
4278 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
4279 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
4280 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, 0 },
4281 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
4282 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
4283 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
4284 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
4285 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4286 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
4287 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
4288 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4289 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4290 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4291 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
4292 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, 0 },
4293 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4294 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin }, 0 },
4295 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, 0 },
4296 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4297 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4298 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4299 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
4300 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), state_psizemax }, 0 },
4301 /* Samplers for NP2 texture matrix adjustions */
4302 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
4303 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
4304 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
4305 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
4306 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
4307 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
4308 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
4309 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
4310 {0 /* Terminate */, { 0, 0 }, 0 },
4313 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
4314 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4315 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4316 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4317 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4318 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4319 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4320 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4321 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4322 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4323 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4324 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4325 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4326 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4327 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4328 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4329 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4330 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4331 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4332 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4333 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4334 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4335 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4336 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4337 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4338 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4339 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4340 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4341 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4342 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4343 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4344 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4345 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4346 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4347 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4348 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4349 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4350 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4351 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4352 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4353 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4354 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4355 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4356 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4357 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4358 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4359 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4360 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4361 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4362 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4363 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4364 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4365 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4366 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4367 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4368 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4369 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4370 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4371 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4372 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4373 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4374 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4375 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4376 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4377 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4378 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4379 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4380 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4381 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4382 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4383 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4384 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4385 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4386 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4387 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4388 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4389 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4390 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4391 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4392 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4393 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4394 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4395 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4396 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4397 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4398 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4399 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4400 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4401 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4402 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4403 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4404 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4405 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4406 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4407 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4408 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4409 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4410 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4411 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4412 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4413 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4414 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4415 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4416 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4417 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4418 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4419 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4420 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4421 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), tex_bumpenvmat }, 0 },
4422 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4423 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
4424 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
4425 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
4426 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
4427 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
4428 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
4429 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
4430 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
4431 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
4432 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
4433 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
4434 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
4435 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
4436 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
4437 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
4438 {0 /* Terminate */, { 0, 0 }, 0 },
4440 #undef GLINFO_LOCATION
4442 #define GLINFO_LOCATION (*gl_info)
4443 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
4445 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) {
4446 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
4447 WINED3DTEXOPCAPS_ADDSIGNED |
4448 WINED3DTEXOPCAPS_ADDSIGNED2X |
4449 WINED3DTEXOPCAPS_MODULATE |
4450 WINED3DTEXOPCAPS_MODULATE2X |
4451 WINED3DTEXOPCAPS_MODULATE4X |
4452 WINED3DTEXOPCAPS_SELECTARG1 |
4453 WINED3DTEXOPCAPS_SELECTARG2 |
4454 WINED3DTEXOPCAPS_DISABLE;
4456 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
4457 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
4458 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4459 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
4460 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
4461 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
4462 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
4463 WINED3DTEXOPCAPS_LERP |
4464 WINED3DTEXOPCAPS_SUBTRACT;
4466 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
4467 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4468 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
4469 WINED3DTEXOPCAPS_MULTIPLYADD |
4470 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
4471 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4472 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
4474 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
4475 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
4477 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
4478 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
4481 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
4482 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
4485 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4486 static void ffp_fragment_free(IWineD3DDevice *iface) {}
4488 const struct fragment_pipeline ffp_fragment_pipeline = {
4489 ffp_enable,
4490 ffp_fragment_get_caps,
4491 ffp_fragment_alloc,
4492 ffp_fragment_free,
4493 ffp_fragmentstate_template
4496 static int num_handlers(APPLYSTATEFUNC *funcs) {
4497 unsigned int i;
4498 for(i = 0; funcs[i]; i++);
4499 return i;
4502 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4503 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4504 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4507 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4508 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4509 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4510 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
4513 void compile_state_table(struct StateEntry *StateTable,
4514 APPLYSTATEFUNC **dev_multistate_funcs,
4515 WineD3D_GL_Info *gl_info,
4516 const struct StateEntryTemplate *vertex,
4517 const struct fragment_pipeline *fragment,
4518 const struct StateEntryTemplate *misc) {
4519 unsigned int i, type, handlers;
4520 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
4521 const struct StateEntryTemplate *cur;
4522 BOOL set[STATE_HIGHEST + 1];
4524 memset(multistate_funcs, 0, sizeof(multistate_funcs));
4526 for(i = 0; i < STATE_HIGHEST + 1; i++) {
4527 StateTable[i].representative = 0;
4528 StateTable[i].apply = state_undefined;
4531 for(type = 0; type < 3; type++) {
4532 /* This switch decides the order in which the states are applied */
4533 switch(type) {
4534 case 0: cur = misc; break;
4535 case 1: cur = fragment->states; break;
4536 case 2: cur = vertex; break;
4537 default: cur = NULL; /* Stupid compiler */
4539 if(!cur) continue;
4541 /* GL extension filtering should not prevent multiple handlers being applied from different
4542 * pipeline parts
4544 memset(set, 0, sizeof(set));
4546 for(i = 0; cur[i].state; i++) {
4548 /* Only use the first matching state with the available extension from one template.
4549 * e.g.
4550 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
4551 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
4553 * if GL_XYZ_fancy is supported, ignore the 2nd line
4555 if(set[cur[i].state]) continue;
4556 /* Skip state lines depending on unsupported extensions */
4557 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
4558 set[cur[i].state] = TRUE;
4559 /* In some cases having an extension means that nothing has to be
4560 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
4561 * supported, the texture coordinate fixup can be ignored. If the
4562 * apply function is used, mark the state set(done above) to prevent
4563 * applying later lines, but do not record anything in the state
4564 * table
4566 if(!cur[i].content.apply) continue;
4568 handlers = num_handlers(multistate_funcs[cur[i].state]);
4569 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
4570 switch(handlers) {
4571 case 0:
4572 StateTable[cur[i].state].apply = cur[i].content.apply;
4573 break;
4574 case 1:
4575 StateTable[cur[i].state].apply = multistate_apply_2;
4576 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4578 sizeof(**dev_multistate_funcs) * 2);
4579 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4580 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4581 break;
4582 case 2:
4583 StateTable[cur[i].state].apply = multistate_apply_3;
4584 HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
4585 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4587 sizeof(**dev_multistate_funcs) * 3);
4588 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4589 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4590 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
4591 break;
4592 default:
4593 ERR("Unexpected amount of state handlers for state %u: %u\n",
4594 cur[i].state, handlers + 1);
4597 if(StateTable[cur[i].state].representative &&
4598 StateTable[cur[i].state].representative != cur[i].content.representative) {
4599 FIXME("State %u has different representatives in different pipeline parts\n",
4600 cur[i].state);
4602 StateTable[cur[i].state].representative = cur[i].content.representative;
4606 #undef GLINFO_LOCATION