push 818f085f73990f577927aeb76c81fa65ee9c5568
[wine/hacks.git] / dlls / wined3d / state.c
blobe4c819d25903b8e8f7b557d30ba5fd148948077f
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 struct GlPixelFormatDesc *glDesc;
247 getFormatDescEntry(target->resource.format, &GLINFO_LOCATION, &glDesc);
249 /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
250 * The d3d9 visual test confirms the behavior. */
251 if(!(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) {
252 glDisable(GL_BLEND);
253 checkGLcall("glDisable GL_BLEND");
254 return;
255 } else {
256 glEnable(GL_BLEND);
257 checkGLcall("glEnable GL_BLEND");
259 } else {
260 glDisable(GL_BLEND);
261 checkGLcall("glDisable GL_BLEND");
262 /* Nothing more to do - get out */
263 return;
266 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
267 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
268 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
269 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
270 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
271 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
272 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
273 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
274 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
276 /* To compensate the lack of format switching with backbuffer offscreen rendering,
277 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
278 * if the render target doesn't support alpha blending. A nonexistent alpha channel
279 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
281 case WINED3DBLEND_DESTALPHA :
282 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
283 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
284 break;
285 case WINED3DBLEND_INVDESTALPHA :
286 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
287 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
288 break;
290 case WINED3DBLEND_SRCALPHASAT :
291 dstBlend = GL_SRC_ALPHA_SATURATE;
292 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
293 break;
295 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
296 * values which are still valid up to d3d9. They should not occur as dest blend values
298 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
299 srcBlend = GL_SRC_ALPHA;
300 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
301 break;
303 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
304 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
305 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
306 break;
308 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
309 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
310 default:
311 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
314 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
315 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
316 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
317 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
318 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
319 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
320 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
321 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
322 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
323 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
325 case WINED3DBLEND_DESTALPHA :
326 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
327 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
328 break;
329 case WINED3DBLEND_INVDESTALPHA :
330 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
331 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
332 break;
334 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
335 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
336 break;
338 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
339 dstBlend = GL_SRC_ALPHA;
340 break;
342 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
343 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
344 default:
345 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
348 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
349 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
350 glEnable(GL_LINE_SMOOTH);
351 checkGLcall("glEnable(GL_LINE_SMOOTH)");
352 if(srcBlend != GL_SRC_ALPHA) {
353 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
355 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
356 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
358 } else {
359 glDisable(GL_LINE_SMOOTH);
360 checkGLcall("glDisable(GL_LINE_SMOOTH)");
363 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
364 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
365 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
368 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
369 int srcBlendAlpha = GL_ZERO;
370 int dstBlendAlpha = GL_ZERO;
372 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
373 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
374 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
375 return;
378 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
379 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
380 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
381 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
382 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
383 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
384 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
385 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
386 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
387 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
388 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
389 case WINED3DBLEND_SRCALPHASAT :
390 dstBlend = GL_SRC_ALPHA_SATURATE;
391 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
392 break;
393 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
394 * values which are still valid up to d3d9. They should not occur as dest blend values
396 case WINED3DBLEND_BOTHSRCALPHA :
397 dstBlendAlpha = GL_SRC_ALPHA;
398 srcBlendAlpha = GL_SRC_ALPHA;
399 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
400 break;
401 case WINED3DBLEND_BOTHINVSRCALPHA :
402 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
403 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
404 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
405 break;
406 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
407 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
408 default:
409 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
412 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
413 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
414 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
415 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
416 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
417 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
418 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
419 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
420 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
421 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
422 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
423 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
424 case WINED3DBLEND_BOTHSRCALPHA :
425 srcBlendAlpha = GL_SRC_ALPHA;
426 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
427 break;
428 case WINED3DBLEND_BOTHINVSRCALPHA :
429 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
430 dstBlendAlpha = GL_SRC_ALPHA;
431 break;
432 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
433 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
434 default:
435 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
438 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
439 checkGLcall("glBlendFuncSeparateEXT");
440 } else {
441 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
442 glBlendFunc(srcBlend, dstBlend);
443 checkGLcall("glBlendFunc");
446 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
447 so it may need updating */
448 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
449 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
450 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
454 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
455 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
458 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
459 float col[4];
461 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
462 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
463 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
464 checkGLcall("glBlendColor");
467 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
468 int glParm = 0;
469 float ref;
470 BOOL enable_ckey = FALSE;
472 /* Find out if the texture on the first stage has a ckey set
473 * The alpha state func reads the texture settings, even though alpha and texture are not grouped
474 * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
475 * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
476 * in case it finds some texture+colorkeyenable combination which needs extra care.
478 if (stateblock->textures[0])
480 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
482 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
484 IWineD3DSurfaceImpl *surf;
486 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
488 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
490 const StaticPixelFormatDesc *fmt = getFormatDescEntry(surf->resource.format, NULL, NULL);
491 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
492 * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
493 * surface has alpha bits */
494 if (fmt->alphaMask == 0x00000000) enable_ckey = TRUE;
499 if(enable_ckey || context->last_was_ckey) {
500 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
501 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
503 context->last_was_ckey = enable_ckey;
505 if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
506 (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
507 glEnable(GL_ALPHA_TEST);
508 checkGLcall("glEnable GL_ALPHA_TEST");
509 } else {
510 glDisable(GL_ALPHA_TEST);
511 checkGLcall("glDisable GL_ALPHA_TEST");
512 /* Alpha test is disabled, don't bother setting the params - it will happen on the next
513 * enable call
515 return;
518 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
519 glParm = GL_NOTEQUAL;
520 ref = 0.0;
521 } else {
522 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
523 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
525 if(glParm) {
526 glAlphaFunc(glParm, ref);
527 checkGLcall("glAlphaFunc");
531 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
532 DWORD enable = 0xFFFFFFFF;
533 DWORD disable = 0x00000000;
535 if (use_vs(stateblock->wineD3DDevice)) {
536 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
537 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
538 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
539 * of that - don't do anything here and keep them disabled
541 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
542 static BOOL warned = FALSE;
543 if(!warned) {
544 FIXME("Clipping not supported with vertex shaders\n");
545 warned = TRUE;
548 return;
551 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
552 * of already set values
555 /* If enabling / disabling all
556 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
558 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
559 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
560 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
561 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
562 glDisable(GL_DEPTH_CLAMP_NV);
563 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
565 } else {
566 disable = 0xffffffff;
567 enable = 0x00;
568 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
569 glEnable(GL_DEPTH_CLAMP_NV);
570 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
574 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
575 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
576 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
577 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
578 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
579 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
581 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
582 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
583 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
584 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
585 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
586 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
588 /** update clipping status */
589 if (enable) {
590 stateblock->clip_status.ClipUnion = 0;
591 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
592 } else {
593 stateblock->clip_status.ClipUnion = 0;
594 stateblock->clip_status.ClipIntersection = 0;
598 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
599 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
602 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
603 int blendEquation = GL_FUNC_ADD;
604 int blendEquationAlpha = GL_FUNC_ADD;
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 static const GLfloat black[] = {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 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
758 checkGLcall("glActiveTextureARB");
760 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
761 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
765 static void
766 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
767 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
768 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
769 GL_EXTCALL(glActiveStencilFaceEXT(face));
770 checkGLcall("glActiveStencilFaceEXT(...)");
771 glStencilFunc(func, ref, mask);
772 checkGLcall("glStencilFunc(...)");
773 glStencilOp(stencilFail, depthFail, stencilPass);
774 checkGLcall("glStencilOp(...)");
777 static void
778 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
779 DWORD onesided_enable = FALSE;
780 DWORD twosided_enable = FALSE;
781 GLint func = GL_ALWAYS;
782 GLint func_ccw = GL_ALWAYS;
783 GLint ref = 0;
784 GLuint mask = 0;
785 GLint stencilFail = GL_KEEP;
786 GLint depthFail = GL_KEEP;
787 GLint stencilPass = GL_KEEP;
788 GLint stencilFail_ccw = GL_KEEP;
789 GLint depthFail_ccw = GL_KEEP;
790 GLint stencilPass_ccw = GL_KEEP;
792 /* No stencil test without a stencil buffer */
793 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
794 glDisable(GL_STENCIL_TEST);
795 checkGLcall("glDisable GL_STENCIL_TEST");
796 return;
799 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
800 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
801 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
802 func = GL_ALWAYS;
803 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
804 func_ccw = GL_ALWAYS;
805 ref = stateblock->renderState[WINED3DRS_STENCILREF];
806 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
807 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
808 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
809 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
810 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
811 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
812 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
814 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
815 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
816 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
817 onesided_enable, twosided_enable, ref, mask,
818 func, stencilFail, depthFail, stencilPass,
819 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
821 if (twosided_enable && onesided_enable) {
822 glEnable(GL_STENCIL_TEST);
823 checkGLcall("glEnable GL_STENCIL_TEST");
825 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
826 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
827 * which has an effect on the code below too. If we apply the front face
828 * afterwards, we are sure that the active stencil face is set to front,
829 * and other stencil functions which do not use two sided stencil do not have
830 * to set it back
832 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
833 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
834 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
835 stencilFail, depthFail, stencilPass);
836 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
837 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
838 checkGLcall("glStencilFuncSeparateATI(...)");
839 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
840 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
841 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
842 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
843 } else {
844 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
846 } else if(onesided_enable) {
847 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
848 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
849 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
852 /* This code disables the ATI extension as well, since the standard stencil functions are equal
853 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
855 glEnable(GL_STENCIL_TEST);
856 checkGLcall("glEnable GL_STENCIL_TEST");
857 glStencilFunc(func, ref, mask);
858 checkGLcall("glStencilFunc(...)");
859 glStencilOp(stencilFail, depthFail, stencilPass);
860 checkGLcall("glStencilOp(...)");
861 } else {
862 glDisable(GL_STENCIL_TEST);
863 checkGLcall("glDisable GL_STENCIL_TEST");
867 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
868 DWORD mask;
870 if(stateblock->wineD3DDevice->stencilBufferTarget) {
871 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
872 } else {
873 mask = 0;
876 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
877 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
878 glStencilMask(mask);
879 checkGLcall("glStencilMask");
880 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
881 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
882 glStencilMask(mask);
885 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
886 DWORD mask;
888 if(stateblock->wineD3DDevice->stencilBufferTarget) {
889 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
890 } else {
891 mask = 0;
894 glStencilMask(mask);
895 checkGLcall("glStencilMask");
898 static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
899 BOOL fogenable = stateblock->renderState[WINED3DRS_FOGENABLE];
900 IWineD3DPixelShaderImpl *ps_impl = (IWineD3DPixelShaderImpl *)stateblock->pixelShader;
901 BOOL is_ps3 = use_ps(stateblock->wineD3DDevice)
902 && ps_impl->baseShader.reg_maps.shader_version >= WINED3DPS_VERSION(3,0);
903 float fogstart, fogend;
905 union {
906 DWORD d;
907 float f;
908 } tmpvalue;
910 if (!fogenable) {
911 /* No fog? Disable it, and we're done :-) */
912 glDisable(GL_FOG);
913 checkGLcall("glDisable GL_FOG");
914 return;
917 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
918 fogstart = tmpvalue.f;
919 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
920 fogend = tmpvalue.f;
922 /* Fog Rules:
924 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
925 * It can use the Z value of the vertex, or the alpha component of the specular color.
926 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
927 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
928 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
930 * FOGTABLEMODE != NONE:
931 * The Z value is used, with the equation specified, no matter what vertex type.
933 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
934 * Per vertex fog is calculated using the specified fog equation and the parameters
936 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
937 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
938 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
941 * Rules for vertex fog with shaders:
943 * When mixing fixed function functionality with the programmable pipeline, D3D expects
944 * the fog computation to happen during transformation while openGL expects it to happen
945 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
946 * the pixel shader while openGL always expects the pixel shader to handle the blending.
947 * To solve this problem, WineD3D does:
948 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
949 * shader,
950 * and 2) disables the fog computation (in either the fixed function or programmable
951 * rasterizer) if using a vertex program.
954 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
955 * without shaders).
958 if( is_ps3 ) {
959 if( !use_vs(stateblock->wineD3DDevice)
960 && stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ) {
961 FIXME("Implement vertex fog for pixel shader >= 3.0 and fixed function pipeline\n");
965 if (use_vs(stateblock->wineD3DDevice)
966 && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
967 if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
968 if(!is_ps3) FIXME("Implement table fog for foggy vertex shader\n");
969 /* Disable fog */
970 fogenable = FALSE;
971 } else {
972 /* Set fog computation in the rasterizer to pass through the value (just blend it) */
973 glFogi(GL_FOG_MODE, GL_LINEAR);
974 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
975 fogstart = 1.0;
976 fogend = 0.0;
979 if(context->fog_coord) {
980 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
981 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
982 context->fog_coord = FALSE;
984 context->last_was_foggy_shader = TRUE;
986 else if( use_ps(stateblock->wineD3DDevice) ) {
987 /* NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
988 * -1/(e-s) and e/(e-s) respectively to simplify fog computation in the shader.
990 WINED3DFOGMODE mode;
991 context->last_was_foggy_shader = FALSE;
993 /* If both fogmodes are set use the table fog mode */
994 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE)
995 mode = stateblock->renderState[WINED3DRS_FOGVERTEXMODE];
996 else
997 mode = stateblock->renderState[WINED3DRS_FOGTABLEMODE];
999 switch (mode) {
1000 case WINED3DFOG_EXP:
1001 case WINED3DFOG_EXP2:
1002 if(!is_ps3) FIXME("Implement non linear fog for pixel shader < 3.0\n");
1003 /* Disable fog */
1004 fogenable = FALSE;
1005 break;
1007 case WINED3DFOG_LINEAR:
1008 fogstart = -1.0f/(fogend-fogstart);
1009 fogend *= -fogstart;
1010 break;
1012 case WINED3DFOG_NONE:
1013 if(!is_ps3) FIXME("Implement software vertex fog for pixel shader < 3.0\n");
1014 /* Disable fog */
1015 fogenable = FALSE;
1016 break;
1017 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1020 if(context->fog_coord) {
1021 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1022 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1023 context->fog_coord = FALSE;
1026 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1027 * the system will apply only pixel(=table) fog effects."
1029 else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1030 glHint(GL_FOG_HINT, GL_FASTEST);
1031 checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
1032 context->last_was_foggy_shader = FALSE;
1034 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1035 /* If processed vertices are used, fall through to the NONE case */
1036 case WINED3DFOG_EXP: {
1037 if(!context->last_was_rhw) {
1038 glFogi(GL_FOG_MODE, GL_EXP);
1039 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1040 if(context->fog_coord) {
1041 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1042 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1043 context->fog_coord = FALSE;
1045 break;
1048 case WINED3DFOG_EXP2: {
1049 if(!context->last_was_rhw) {
1050 glFogi(GL_FOG_MODE, GL_EXP2);
1051 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1052 if(context->fog_coord) {
1053 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1054 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1055 context->fog_coord = FALSE;
1057 break;
1060 case WINED3DFOG_LINEAR: {
1061 if(!context->last_was_rhw) {
1062 glFogi(GL_FOG_MODE, GL_LINEAR);
1063 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1064 if(context->fog_coord) {
1065 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1066 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1067 context->fog_coord = FALSE;
1069 break;
1072 case WINED3DFOG_NONE: {
1073 /* Both are none? According to msdn the alpha channel of the specular
1074 * color contains a fog factor. Set it in drawStridedSlow.
1075 * Same happens with Vertexfog on transformed vertices
1077 if(context->fog_coord == FALSE) {
1078 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1079 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
1080 context->fog_coord = TRUE;
1082 glFogi(GL_FOG_MODE, GL_LINEAR);
1083 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1084 fogstart = 0xff;
1085 fogend = 0x0;
1086 break;
1088 default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1090 } else {
1091 glHint(GL_FOG_HINT, GL_NICEST);
1092 checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
1093 context->last_was_foggy_shader = FALSE;
1095 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1096 case WINED3DFOG_EXP:
1097 glFogi(GL_FOG_MODE, GL_EXP);
1098 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1099 if(context->fog_coord) {
1100 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1101 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1102 context->fog_coord = FALSE;
1104 break;
1106 case WINED3DFOG_EXP2:
1107 glFogi(GL_FOG_MODE, GL_EXP2);
1108 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1109 if(context->fog_coord) {
1110 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1111 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1112 context->fog_coord = FALSE;
1114 break;
1116 case WINED3DFOG_LINEAR:
1117 glFogi(GL_FOG_MODE, GL_LINEAR);
1118 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1119 if(context->fog_coord) {
1120 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1121 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
1122 context->fog_coord = FALSE;
1124 break;
1126 case WINED3DFOG_NONE: /* Won't happen */
1127 default:
1128 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1132 if(fogenable) {
1133 glEnable(GL_FOG);
1134 checkGLcall("glEnable GL_FOG");
1136 if(fogstart != fogend)
1138 glFogfv(GL_FOG_START, &fogstart);
1139 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1140 TRACE("Fog Start == %f\n", fogstart);
1142 glFogfv(GL_FOG_END, &fogend);
1143 checkGLcall("glFogf(GL_FOG_END, fogend)");
1144 TRACE("Fog End == %f\n", fogend);
1146 else
1148 glFogf(GL_FOG_START, -1.0 / 0.0);
1149 checkGLcall("glFogf(GL_FOG_START, fogstart)");
1150 TRACE("Fog Start == %f\n", fogstart);
1152 glFogf(GL_FOG_END, 0.0);
1153 checkGLcall("glFogf(GL_FOG_END, fogend)");
1154 TRACE("Fog End == %f\n", fogend);
1156 } else {
1157 glDisable(GL_FOG);
1158 checkGLcall("glDisable GL_FOG");
1162 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1163 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1164 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1168 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1169 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1170 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1171 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1172 } else {
1173 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1174 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1178 static void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1179 float col[4];
1180 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1181 glFogfv(GL_FOG_COLOR, &col[0]);
1182 checkGLcall("glFog GL_FOG_COLOR");
1185 static void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1186 union {
1187 DWORD d;
1188 float f;
1189 } tmpvalue;
1190 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1191 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1192 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1195 /* TODO: Merge with primitive type + init_materials()!! */
1196 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1197 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1198 GLenum Parm = 0;
1199 const WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1200 BOOL isDiffuseSupplied;
1202 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1203 * The vertex declaration will call this function if the fixed function pipeline is used.
1206 if(isStateDirty(context, STATE_VDECL)) {
1207 return;
1210 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1212 context->num_untracked_materials = 0;
1213 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1214 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1215 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1216 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1217 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1218 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1220 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1221 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1222 Parm = GL_AMBIENT_AND_DIFFUSE;
1223 } else {
1224 Parm = GL_DIFFUSE;
1226 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1227 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1228 context->num_untracked_materials++;
1230 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1231 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1232 context->num_untracked_materials++;
1234 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1235 Parm = GL_AMBIENT;
1236 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1237 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1238 context->num_untracked_materials++;
1240 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1241 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1242 context->num_untracked_materials++;
1244 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1245 Parm = GL_EMISSION;
1246 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1247 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1248 context->num_untracked_materials++;
1250 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1251 Parm = GL_SPECULAR;
1255 /* Nothing changed, return. */
1256 if (Parm == context->tracking_parm) return;
1258 if(!Parm) {
1259 glDisable(GL_COLOR_MATERIAL);
1260 checkGLcall("glDisable GL_COLOR_MATERIAL");
1261 } else {
1262 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1263 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1264 glEnable(GL_COLOR_MATERIAL);
1265 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1268 /* Apparently calls to glMaterialfv are ignored for properties we're
1269 * tracking with glColorMaterial, so apply those here. */
1270 switch (context->tracking_parm) {
1271 case GL_AMBIENT_AND_DIFFUSE:
1272 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1273 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1274 checkGLcall("glMaterialfv");
1275 break;
1277 case GL_DIFFUSE:
1278 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1279 checkGLcall("glMaterialfv");
1280 break;
1282 case GL_AMBIENT:
1283 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1284 checkGLcall("glMaterialfv");
1285 break;
1287 case GL_EMISSION:
1288 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1289 checkGLcall("glMaterialfv");
1290 break;
1292 case GL_SPECULAR:
1293 /* Only change material color if specular is enabled, otherwise it is set to black */
1294 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1295 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1296 checkGLcall("glMaterialfv");
1297 } else {
1298 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1299 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1300 checkGLcall("glMaterialfv");
1302 break;
1305 context->tracking_parm = Parm;
1308 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1309 union {
1310 DWORD d;
1311 WINED3DLINEPATTERN lp;
1312 } tmppattern;
1313 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1315 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1317 if (tmppattern.lp.wRepeatFactor) {
1318 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1319 checkGLcall("glLineStipple(repeat, linepattern)");
1320 glEnable(GL_LINE_STIPPLE);
1321 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1322 } else {
1323 glDisable(GL_LINE_STIPPLE);
1324 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1328 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1329 union {
1330 DWORD d;
1331 float f;
1332 } tmpvalue;
1334 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1335 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1336 TRACE("ZBias value %f\n", tmpvalue.f);
1337 glPolygonOffset(0, -tmpvalue.f);
1338 checkGLcall("glPolygonOffset(0, -Value)");
1339 glEnable(GL_POLYGON_OFFSET_FILL);
1340 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1341 glEnable(GL_POLYGON_OFFSET_LINE);
1342 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1343 glEnable(GL_POLYGON_OFFSET_POINT);
1344 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1345 } else {
1346 glDisable(GL_POLYGON_OFFSET_FILL);
1347 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1348 glDisable(GL_POLYGON_OFFSET_LINE);
1349 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1350 glDisable(GL_POLYGON_OFFSET_POINT);
1351 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1356 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1357 if(isStateDirty(context, STATE_VDECL)) {
1358 return;
1360 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1361 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1362 * by zero and is not properly defined in opengl, so avoid it
1364 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1365 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1366 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1367 glEnable(GL_NORMALIZE);
1368 checkGLcall("glEnable(GL_NORMALIZE);");
1369 } else {
1370 glDisable(GL_NORMALIZE);
1371 checkGLcall("glDisable(GL_NORMALIZE);");
1375 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1376 union {
1377 DWORD d;
1378 float f;
1379 } tmpvalue;
1381 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1382 if(tmpvalue.f != 1.0) {
1383 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1385 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1386 if(tmpvalue.f != 64.0) {
1387 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1392 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1393 union {
1394 DWORD d;
1395 float f;
1396 } min, max;
1398 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1399 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1401 /* Max point size trumps min point size */
1402 if(min.f > max.f) {
1403 min.f = max.f;
1406 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1407 checkGLcall("glPointParameterfEXT(...)");
1408 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1409 checkGLcall("glPointParameterfEXT(...)");
1412 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1413 union {
1414 DWORD d;
1415 float f;
1416 } min, max;
1418 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1419 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1421 /* Max point size trumps min point size */
1422 if(min.f > max.f) {
1423 min.f = max.f;
1426 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1427 checkGLcall("glPointParameterfARB(...)");
1428 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1429 checkGLcall("glPointParameterfARB(...)");
1432 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1433 /* TODO: Group this with the viewport */
1435 * POINTSCALEENABLE controls how point size value is treated. If set to
1436 * true, the point size is scaled with respect to height of viewport.
1437 * When set to false point size is in pixels.
1440 /* Default values */
1441 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1442 union {
1443 DWORD d;
1444 float f;
1445 } pointSize, A, B, C;
1447 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1448 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1449 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1450 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1452 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1453 GLfloat scaleFactor;
1454 float h = stateblock->viewport.Height;
1456 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1458 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1459 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1460 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1461 * are less than 1.0f. scale_factor = 1.0f / point_size.
1463 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1464 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1465 * is 1.0, but then accepts points below that and draws too small points
1467 pointSize.f = GL_LIMITS(pointsizemin);
1468 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1469 /* gl already scales the input to glPointSize,
1470 * d3d scales the result after the point size scale.
1471 * If the point size is bigger than the max size, use the
1472 * scaling to scale it bigger, and set the gl point size to max
1474 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1475 TRACE("scale: %f\n", scaleFactor);
1476 pointSize.f = GL_LIMITS(pointsize);
1477 } else {
1478 scaleFactor = 1.0f;
1480 scaleFactor = pow(h * scaleFactor, 2);
1482 att[0] = A.f / scaleFactor;
1483 att[1] = B.f / scaleFactor;
1484 att[2] = C.f / scaleFactor;
1487 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1488 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1489 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1491 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1492 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1493 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1494 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1495 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1498 glPointSize(pointSize.f);
1499 checkGLcall("glPointSize(...);");
1502 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1503 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1505 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1506 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1507 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1508 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1509 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1510 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1511 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1512 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1513 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1514 checkGLcall("glColorMask(...)");
1516 /* depends on WINED3DRS_COLORWRITEENABLE. */
1517 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1518 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1519 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1520 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1521 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1522 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1523 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1527 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1528 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1529 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1530 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1531 } else {
1532 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1533 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1537 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1538 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1539 TRACE("Last Pixel Drawing Enabled\n");
1540 } else {
1541 static BOOL warned;
1542 if (!warned) {
1543 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1544 warned = TRUE;
1545 } else {
1546 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1551 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1552 /* TODO: NV_POINT_SPRITE */
1553 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1554 TRACE("Point sprites not supported\n");
1558 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1559 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1560 glEnable(GL_POINT_SPRITE_ARB);
1561 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1562 } else {
1563 glDisable(GL_POINT_SPRITE_ARB);
1564 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1568 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1570 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1571 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1572 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1573 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1575 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1577 TRACE("Stub\n");
1578 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1579 stateblock->renderState[WINED3DRS_WRAP1] ||
1580 stateblock->renderState[WINED3DRS_WRAP2] ||
1581 stateblock->renderState[WINED3DRS_WRAP3] ||
1582 stateblock->renderState[WINED3DRS_WRAP4] ||
1583 stateblock->renderState[WINED3DRS_WRAP5] ||
1584 stateblock->renderState[WINED3DRS_WRAP6] ||
1585 stateblock->renderState[WINED3DRS_WRAP7] ||
1586 stateblock->renderState[WINED3DRS_WRAP8] ||
1587 stateblock->renderState[WINED3DRS_WRAP9] ||
1588 stateblock->renderState[WINED3DRS_WRAP10] ||
1589 stateblock->renderState[WINED3DRS_WRAP11] ||
1590 stateblock->renderState[WINED3DRS_WRAP12] ||
1591 stateblock->renderState[WINED3DRS_WRAP13] ||
1592 stateblock->renderState[WINED3DRS_WRAP14] ||
1593 stateblock->renderState[WINED3DRS_WRAP15] ) {
1594 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1598 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1599 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1600 WARN("Multisample antialiasing not supported by gl\n");
1604 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1605 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1606 glEnable(GL_MULTISAMPLE_ARB);
1607 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1608 } else {
1609 glDisable(GL_MULTISAMPLE_ARB);
1610 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1614 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1615 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1616 glEnable(GL_SCISSOR_TEST);
1617 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1618 } else {
1619 glDisable(GL_SCISSOR_TEST);
1620 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1624 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1625 union {
1626 DWORD d;
1627 float f;
1628 } tmpvalue;
1630 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1631 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1632 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1633 glEnable(GL_POLYGON_OFFSET_FILL);
1634 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1635 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1636 checkGLcall("glPolygonOffset(...)");
1637 } else {
1638 glDisable(GL_POLYGON_OFFSET_FILL);
1639 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1643 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1644 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1645 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1646 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1647 } else {
1648 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1649 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1653 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1654 TRACE("Stub\n");
1655 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1656 FIXME(" Stippled Alpha not supported yet.\n");
1659 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1660 TRACE("Stub\n");
1661 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1662 FIXME(" Antialias not supported yet.\n");
1665 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1666 TRACE("Stub\n");
1667 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1668 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1671 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1672 TRACE("Stub\n");
1673 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1674 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1677 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1678 union {
1679 DWORD d;
1680 float f;
1681 } tmpvalue;
1682 tmpvalue.f = 1.0f;
1684 TRACE("Stub\n");
1685 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1687 static BOOL displayed = FALSE;
1689 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1690 if(!displayed)
1691 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1693 displayed = TRUE;
1697 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1698 TRACE("Stub\n");
1699 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1700 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1703 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1704 TRACE("Stub\n");
1705 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1706 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1709 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1710 TRACE("Stub\n");
1711 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1712 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1715 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1716 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1717 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1721 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1722 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1723 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1727 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1728 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1729 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1733 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1734 if(stateblock->renderState[WINED3DRS_ROP2]) {
1735 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1739 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1740 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1741 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1745 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1746 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1747 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1751 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1752 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1753 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1757 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1758 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1759 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1763 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1764 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1765 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1769 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1770 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1771 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1775 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1776 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1777 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1781 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1782 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1783 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1787 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1788 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1789 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1793 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1794 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1795 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1799 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1800 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1801 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1805 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1806 #if defined (GL_VERSION_1_3)
1807 # define useext(A) A
1808 #elif defined (GL_EXT_texture_env_combine)
1809 # define useext(A) A##_EXT
1810 #elif defined (GL_ARB_texture_env_combine)
1811 # define useext(A) A##_ARB
1812 #endif
1814 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1815 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1816 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1817 * flag specifies the complement of the input should be used. */
1818 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1819 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1821 /* Calculate the operand */
1822 if (complement) {
1823 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1824 else *operand = GL_ONE_MINUS_SRC_COLOR;
1825 } else {
1826 if (from_alpha) *operand = GL_SRC_ALPHA;
1827 else *operand = GL_SRC_COLOR;
1830 /* Calculate the source */
1831 switch (arg & WINED3DTA_SELECTMASK) {
1832 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1833 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1834 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1835 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1836 case WINED3DTA_SPECULAR:
1838 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1839 * 'Secondary color' and isn't supported until base GL supports it
1840 * There is no concept of temp registers as far as I can tell
1842 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1843 *source = GL_TEXTURE;
1844 break;
1845 default:
1846 FIXME("Unrecognized texture arg %#x\n", arg);
1847 *source = GL_TEXTURE;
1848 break;
1852 /* Setup the texture operations texture stage states */
1853 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1855 GLenum src1, src2, src3;
1856 GLenum opr1, opr2, opr3;
1857 GLenum comb_target;
1858 GLenum src0_target, src1_target, src2_target;
1859 GLenum opr0_target, opr1_target, opr2_target;
1860 GLenum scal_target;
1861 GLenum opr=0, invopr, src3_target, opr3_target;
1862 BOOL Handled = FALSE;
1863 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1864 IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1866 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1868 /* This is called by a state handler which has the gl lock held and a context for the thread */
1870 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1871 the form (a1 <operation> a2). However, some of the more complex operations
1872 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1873 in a third parameter called a0. Therefore these are operations of the form
1874 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1876 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1877 functions below, expect their syntax to differ slightly to those listed in the
1878 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1879 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1881 if (isAlpha) {
1882 comb_target = useext(GL_COMBINE_ALPHA);
1883 src0_target = useext(GL_SOURCE0_ALPHA);
1884 src1_target = useext(GL_SOURCE1_ALPHA);
1885 src2_target = useext(GL_SOURCE2_ALPHA);
1886 opr0_target = useext(GL_OPERAND0_ALPHA);
1887 opr1_target = useext(GL_OPERAND1_ALPHA);
1888 opr2_target = useext(GL_OPERAND2_ALPHA);
1889 scal_target = GL_ALPHA_SCALE;
1891 else {
1892 comb_target = useext(GL_COMBINE_RGB);
1893 src0_target = useext(GL_SOURCE0_RGB);
1894 src1_target = useext(GL_SOURCE1_RGB);
1895 src2_target = useext(GL_SOURCE2_RGB);
1896 opr0_target = useext(GL_OPERAND0_RGB);
1897 opr1_target = useext(GL_OPERAND1_RGB);
1898 opr2_target = useext(GL_OPERAND2_RGB);
1899 scal_target = useext(GL_RGB_SCALE);
1902 /* If a texture stage references an invalid texture unit the stage just
1903 * passes through the result from the previous stage */
1904 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1905 arg1 = WINED3DTA_CURRENT;
1906 op = WINED3DTOP_SELECTARG1;
1909 /* From MSDN (WINED3DTSS_ALPHAARG1) :
1910 The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage,
1911 then the default argument is WINED3DTA_DIFFUSE.
1912 FIXME? If texture added/removed, may need to reset back as well? */
1913 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1914 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1915 } else {
1916 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1918 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1919 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1921 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1923 Handled = TRUE; /* Assume will be handled */
1925 /* Other texture operations require special extensions: */
1926 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1927 if (isAlpha) {
1928 opr = GL_SRC_ALPHA;
1929 invopr = GL_ONE_MINUS_SRC_ALPHA;
1930 src3_target = GL_SOURCE3_ALPHA_NV;
1931 opr3_target = GL_OPERAND3_ALPHA_NV;
1932 } else {
1933 opr = GL_SRC_COLOR;
1934 invopr = GL_ONE_MINUS_SRC_COLOR;
1935 src3_target = GL_SOURCE3_RGB_NV;
1936 opr3_target = GL_OPERAND3_RGB_NV;
1938 switch (op) {
1939 case WINED3DTOP_DISABLE: /* Only for alpha */
1940 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1941 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1942 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1943 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1944 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1945 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1946 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1947 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1948 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1949 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1950 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1951 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1952 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1953 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1954 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1955 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1956 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1957 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1958 break;
1959 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1960 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1961 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1962 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1963 if (op == WINED3DTOP_SELECTARG1) {
1964 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1965 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1966 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1967 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1968 } else {
1969 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1970 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1971 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1972 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1974 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1975 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1976 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1977 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1978 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1979 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1980 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1981 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1982 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1983 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1984 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1985 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1986 break;
1988 case WINED3DTOP_MODULATE:
1989 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1990 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1991 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1992 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1993 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1994 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1995 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1996 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1997 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1998 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1999 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2000 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2001 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2002 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2003 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2004 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2005 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2006 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2007 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2008 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2009 break;
2010 case WINED3DTOP_MODULATE2X:
2011 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2012 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2013 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2014 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2015 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2016 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2017 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2018 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2019 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2020 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2021 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2022 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2023 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2024 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2025 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2026 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2027 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2028 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2029 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2030 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2031 break;
2032 case WINED3DTOP_MODULATE4X:
2033 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2034 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2035 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2036 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2037 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2038 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2039 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2040 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2041 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2042 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2043 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2044 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2045 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2046 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2047 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2048 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2049 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2050 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2051 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2052 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2053 break;
2055 case WINED3DTOP_ADD:
2056 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2057 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2058 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2059 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2060 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2061 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2062 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2063 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2064 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2065 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2066 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2067 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2068 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2069 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2070 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2071 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2072 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2073 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2074 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2075 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2076 break;
2078 case WINED3DTOP_ADDSIGNED:
2079 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2080 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2081 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2082 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2083 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2084 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2085 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2086 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2087 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2088 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2089 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2090 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2091 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2092 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2093 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2094 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2095 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2096 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2097 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2098 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2099 break;
2101 case WINED3DTOP_ADDSIGNED2X:
2102 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2103 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2104 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2105 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2106 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2107 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2108 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2109 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2110 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2111 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2112 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2113 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2114 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2115 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2116 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2117 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2118 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2119 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2120 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2121 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2122 break;
2124 case WINED3DTOP_ADDSMOOTH:
2125 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2126 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2127 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2128 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2129 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2130 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2131 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2132 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2133 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2134 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2135 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2136 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2137 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2138 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2139 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2140 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2141 switch (opr1) {
2142 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2143 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2144 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2145 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2147 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2148 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2149 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2150 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2151 break;
2153 case WINED3DTOP_BLENDDIFFUSEALPHA:
2154 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2155 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2156 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2157 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2158 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2159 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2160 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2161 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2162 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2163 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2164 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2165 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2166 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2167 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2168 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2169 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2170 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2171 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2172 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2173 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2174 break;
2175 case WINED3DTOP_BLENDTEXTUREALPHA:
2176 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2177 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2178 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2179 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2180 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2181 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2182 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2183 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2184 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2185 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2186 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2187 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2188 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2189 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2190 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2191 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2192 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2193 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2194 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2195 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2196 break;
2197 case WINED3DTOP_BLENDFACTORALPHA:
2198 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2199 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2200 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2201 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2202 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2203 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2204 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2205 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2206 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2207 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2208 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2209 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2210 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2211 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2212 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2213 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2214 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2215 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2216 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2217 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2218 break;
2219 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2220 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2221 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2222 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2223 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2224 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2225 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2226 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2227 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2228 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2229 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2230 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2231 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2232 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2233 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2234 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2235 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2236 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2237 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2238 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2239 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2240 break;
2241 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2242 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2243 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2244 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2245 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2246 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2247 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2248 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2249 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2250 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2251 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2252 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2253 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2254 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2255 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2256 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2257 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2258 switch (opr) {
2259 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2260 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2262 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2263 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2264 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2265 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2266 break;
2267 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2268 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2269 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2270 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2271 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2272 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2273 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2274 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2275 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2276 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2277 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2278 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2279 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2280 switch (opr1) {
2281 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2282 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2284 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2285 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2286 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2287 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2288 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2289 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2290 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2291 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2292 break;
2293 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2294 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2295 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2296 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2297 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2298 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2299 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2300 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2301 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2302 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2303 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2304 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2305 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2306 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2307 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2308 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2309 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2310 switch (opr1) {
2311 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2312 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2313 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2314 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2316 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2317 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2318 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2319 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2320 break;
2321 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2322 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2323 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2324 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2325 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2326 switch (opr1) {
2327 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2328 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2329 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2330 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2332 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2333 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2334 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2335 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2336 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2337 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2338 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2339 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2340 switch (opr1) {
2341 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2342 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2344 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2345 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2346 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2347 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2348 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2349 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2350 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2351 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2352 break;
2353 case WINED3DTOP_MULTIPLYADD:
2354 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2355 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2356 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2357 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2358 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2359 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2360 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2361 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2362 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2363 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2364 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2365 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2366 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2367 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2368 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2369 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2370 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2371 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2372 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2373 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2374 break;
2376 case WINED3DTOP_BUMPENVMAP:
2380 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2381 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2383 default:
2384 Handled = FALSE;
2386 if (Handled) {
2387 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2388 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2390 return;
2392 } /* GL_NV_texture_env_combine4 */
2394 Handled = TRUE; /* Again, assume handled */
2395 switch (op) {
2396 case WINED3DTOP_DISABLE: /* Only for alpha */
2397 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2398 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2399 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2400 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2401 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2402 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2403 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2404 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2405 break;
2406 case WINED3DTOP_SELECTARG1:
2407 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2408 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2409 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2410 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2411 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2412 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2413 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2414 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2415 break;
2416 case WINED3DTOP_SELECTARG2:
2417 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2418 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2419 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2420 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2421 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2422 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2423 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2424 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2425 break;
2426 case WINED3DTOP_MODULATE:
2427 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2428 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2429 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2430 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2431 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2432 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2433 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2434 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2435 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2436 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2437 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2438 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2439 break;
2440 case WINED3DTOP_MODULATE2X:
2441 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2442 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2443 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2444 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2445 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2446 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2447 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2448 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2449 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2450 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2451 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2452 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2453 break;
2454 case WINED3DTOP_MODULATE4X:
2455 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2456 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2457 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2458 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2459 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2460 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2461 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2462 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2463 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2464 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2465 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2466 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2467 break;
2468 case WINED3DTOP_ADD:
2469 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2470 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2471 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2472 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2473 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2474 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2475 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2476 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2477 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2478 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2479 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2480 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2481 break;
2482 case WINED3DTOP_ADDSIGNED:
2483 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2484 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2485 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2486 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2487 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2488 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2489 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2490 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2491 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2492 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2493 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2494 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2495 break;
2496 case WINED3DTOP_ADDSIGNED2X:
2497 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2498 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2499 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2500 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2501 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2502 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2503 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2504 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2505 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2506 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2507 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2508 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2509 break;
2510 case WINED3DTOP_SUBTRACT:
2511 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2512 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2513 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2514 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2515 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2516 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2517 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2518 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2519 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2520 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2521 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2522 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2523 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2524 } else {
2525 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2527 break;
2529 case WINED3DTOP_BLENDDIFFUSEALPHA:
2530 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2531 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2532 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2533 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2534 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2535 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2536 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2537 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2538 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2539 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2540 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2541 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2542 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2543 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2544 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2545 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2546 break;
2547 case WINED3DTOP_BLENDTEXTUREALPHA:
2548 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2549 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2550 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2551 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2552 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2553 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2554 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2555 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2556 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2557 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2558 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2559 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2560 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2561 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2562 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2563 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2564 break;
2565 case WINED3DTOP_BLENDFACTORALPHA:
2566 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2567 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2568 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2569 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2570 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2571 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2572 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2573 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2574 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2575 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2576 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2577 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2578 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2579 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2580 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2581 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2582 break;
2583 case WINED3DTOP_BLENDCURRENTALPHA:
2584 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2585 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2586 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2587 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2588 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2589 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2590 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2591 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2592 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2593 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2594 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2595 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2596 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2597 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2598 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2599 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2600 break;
2601 case WINED3DTOP_DOTPRODUCT3:
2602 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2603 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2604 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2605 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2606 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2607 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2608 } else {
2609 FIXME("This version of opengl does not support GL_DOT3\n");
2611 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2612 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2613 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2614 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2615 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2616 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2617 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2618 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2619 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2620 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2621 break;
2622 case WINED3DTOP_LERP:
2623 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2624 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2625 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2626 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2627 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2628 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2629 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2630 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2631 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2632 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2633 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2634 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2635 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2636 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2637 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2638 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2639 break;
2640 case WINED3DTOP_ADDSMOOTH:
2641 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2642 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2643 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2644 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2645 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2646 switch (opr1) {
2647 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2648 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2649 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2650 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2652 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2653 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2654 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2655 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2656 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2657 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2658 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2659 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2660 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2661 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2662 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2663 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2664 } else
2665 Handled = FALSE;
2666 break;
2667 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2668 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2669 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2670 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2671 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2672 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2673 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2674 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2675 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2676 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2677 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2678 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2679 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2680 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2681 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2682 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2683 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2684 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2685 } else
2686 Handled = FALSE;
2687 break;
2688 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2689 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2690 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2691 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2692 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2693 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2694 switch (opr1) {
2695 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2696 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2697 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2698 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2700 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2701 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2702 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2703 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2704 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2705 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2706 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2707 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2708 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2709 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2710 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2711 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2712 } else
2713 Handled = FALSE;
2714 break;
2715 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2716 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2717 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2718 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2719 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2720 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2721 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2722 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2723 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2724 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2725 switch (opr1) {
2726 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2727 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2728 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2729 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2731 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2732 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2733 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2734 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2735 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2736 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2737 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2738 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2739 } else
2740 Handled = FALSE;
2741 break;
2742 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2743 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2744 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2745 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2746 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2747 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2748 switch (opr1) {
2749 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2750 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2751 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2752 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2754 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2755 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2756 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2757 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2758 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2759 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2760 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2761 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2762 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2763 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2764 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2765 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2766 } else
2767 Handled = FALSE;
2768 break;
2769 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2770 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2771 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2772 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2773 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2774 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2775 switch (opr1) {
2776 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2777 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2778 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2779 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2781 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2782 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2783 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2784 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2785 switch (opr1) {
2786 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2787 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2788 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2789 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2791 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2792 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2793 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2794 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2795 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2796 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2797 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2798 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2799 } else
2800 Handled = FALSE;
2801 break;
2802 case WINED3DTOP_MULTIPLYADD:
2803 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2804 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2805 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2806 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2807 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2808 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2809 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2810 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2811 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2812 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2813 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2814 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2815 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2816 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2817 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2818 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2819 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2820 } else
2821 Handled = FALSE;
2822 break;
2823 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2824 case WINED3DTOP_BUMPENVMAP:
2825 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2826 /* Technically texture shader support without register combiners is possible, but not expected to occur
2827 * on real world cards, so for now a fixme should be enough
2829 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2831 default:
2832 Handled = FALSE;
2835 if (Handled) {
2836 BOOL combineOK = TRUE;
2837 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2838 DWORD op2;
2840 if (isAlpha) {
2841 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2842 } else {
2843 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2846 /* Note: If COMBINE4 in effect can't go back to combine! */
2847 switch (op2) {
2848 case WINED3DTOP_ADDSMOOTH:
2849 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2850 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2851 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2852 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2853 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2854 case WINED3DTOP_MULTIPLYADD:
2855 /* Ignore those implemented in both cases */
2856 switch (op) {
2857 case WINED3DTOP_SELECTARG1:
2858 case WINED3DTOP_SELECTARG2:
2859 combineOK = FALSE;
2860 Handled = FALSE;
2861 break;
2862 default:
2863 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2864 return;
2869 if (combineOK) {
2870 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2871 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2873 return;
2877 /* After all the extensions, if still unhandled, report fixme */
2878 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2882 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2883 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2884 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2885 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2887 TRACE("Setting color op for stage %d\n", stage);
2889 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2890 if (use_ps(stateblock->wineD3DDevice)) return;
2892 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2894 if (mapped_stage != -1) {
2895 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2896 FIXME("Attempt to enable unsupported stage!\n");
2897 return;
2899 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2900 checkGLcall("glActiveTextureARB");
2903 if(stage >= stateblock->lowest_disabled_stage) {
2904 TRACE("Stage disabled\n");
2905 if (mapped_stage != -1) {
2906 /* Disable everything here */
2907 glDisable(GL_TEXTURE_2D);
2908 checkGLcall("glDisable(GL_TEXTURE_2D)");
2909 glDisable(GL_TEXTURE_3D);
2910 checkGLcall("glDisable(GL_TEXTURE_3D)");
2911 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2912 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2913 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2915 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2916 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2917 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2920 /* All done */
2921 return;
2924 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2925 * if the sampler for this stage is dirty
2927 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2928 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2931 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2932 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2933 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2934 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2935 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2938 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2939 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
2940 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2941 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map[stage];
2942 DWORD op, arg1, arg2, arg0;
2944 TRACE("Setting alpha op for stage %d\n", stage);
2945 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2946 if (mapped_stage != -1) {
2947 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2948 FIXME("Attempt to enable unsupported stage!\n");
2949 return;
2951 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2952 checkGLcall("glActiveTextureARB");
2955 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2956 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2957 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2958 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2960 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2962 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2964 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2966 IWineD3DSurfaceImpl *surf;
2968 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2970 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT
2971 && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000)
2973 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2974 * properly. On the other hand applications can still use texture combiners apparently. This code
2975 * takes care that apps cannot remove the texture's alpha channel entirely.
2977 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2978 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2979 * and alpha component of diffuse color to draw things like translucent text and perform other
2980 * blending effects.
2982 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2983 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2984 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2985 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2986 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2987 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2988 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2989 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2990 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2991 * alpha.
2993 * What to do with multitexturing? So far no app has been found that uses color keying with
2994 * multitexturing */
2995 if (op == WINED3DTOP_DISABLE)
2997 arg1 = WINED3DTA_TEXTURE;
2998 op = WINED3DTOP_SELECTARG1;
3000 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
3002 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3004 arg2 = WINED3DTA_TEXTURE;
3005 op = WINED3DTOP_MODULATE;
3007 else arg1 = WINED3DTA_TEXTURE;
3009 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
3011 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
3013 arg1 = WINED3DTA_TEXTURE;
3014 op = WINED3DTOP_MODULATE;
3016 else arg2 = WINED3DTA_TEXTURE;
3022 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
3023 * this if block here, and the other code(color keying, texture unit selection) are the same
3025 TRACE("Setting alpha op for stage %d\n", stage);
3026 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3027 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3028 op, arg1, arg2, arg0,
3029 mapped_stage,
3030 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
3031 } else {
3032 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
3033 op, arg1, arg2, arg0);
3037 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3038 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3039 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3040 BOOL generated;
3041 int coordIdx;
3043 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3044 if(use_vs(stateblock->wineD3DDevice) ||
3045 isStateDirty(context, STATE_VDECL)) {
3046 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3047 return;
3050 if (mapped_stage == -1) return;
3052 if(mapped_stage >= GL_LIMITS(textures)) {
3053 return;
3055 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3056 checkGLcall("glActiveTextureARB");
3057 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3058 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3060 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3061 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
3062 generated,
3063 context->last_was_rhw,
3064 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwStride ?
3065 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwType:
3066 WINED3DDECLTYPE_UNUSED,
3067 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3069 /* The sampler applying function calls us if this changes */
3070 if(context->lastWasPow2Texture[texUnit] && stateblock->textures[texUnit]) {
3071 if(generated) {
3072 FIXME("Non-power2 texture being used with generated texture coords\n");
3074 TRACE("Non power two matrix multiply fixup\n");
3075 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3079 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3080 int texture_idx;
3082 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3083 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3084 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3088 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd, GLint *curVBO)
3090 const UINT *offset = stateblock->streamOffset;
3091 unsigned int mapped_stage = 0;
3092 unsigned int textureNo = 0;
3094 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3095 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3097 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3098 if (mapped_stage == -1) continue;
3100 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
3101 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3102 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
3104 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
3105 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
3106 checkGLcall("glBindBufferARB");
3107 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
3110 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3111 checkGLcall("glClientActiveTextureARB");
3113 /* The coords to supply depend completely on the fvf / vertex shader */
3114 glTexCoordPointer(
3115 WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
3116 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
3117 sd->u.s.texCoords[coordIdx].dwStride,
3118 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
3119 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3120 } else {
3121 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3124 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3125 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3126 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3127 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3131 checkGLcall("loadTexCoords");
3134 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3135 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3136 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3137 static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3138 static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3139 static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3140 static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3142 if (mapped_stage == -1) {
3143 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3144 return;
3147 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3148 return;
3150 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3151 checkGLcall("glActiveTextureARB");
3153 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3155 * FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3156 * one flag, you can still specify an index value, which the system uses to
3157 * determine the texture wrapping mode.
3158 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3159 * means use the vertex position (camera-space) as the input texture coordinates
3160 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3161 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3162 * to the TEXCOORDINDEX value
3166 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3168 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
3169 case WINED3DTSS_TCI_PASSTHRU:
3170 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3171 glDisable(GL_TEXTURE_GEN_S);
3172 glDisable(GL_TEXTURE_GEN_T);
3173 glDisable(GL_TEXTURE_GEN_R);
3174 glDisable(GL_TEXTURE_GEN_Q);
3175 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3176 break;
3178 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3179 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3180 * as the input texture coordinates for this stage's texture transformation. This
3181 * equates roughly to EYE_LINEAR
3184 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3186 glMatrixMode(GL_MODELVIEW);
3187 glPushMatrix();
3188 glLoadIdentity();
3189 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3190 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3191 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3192 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3193 glPopMatrix();
3195 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3196 glEnable(GL_TEXTURE_GEN_S);
3197 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3198 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3199 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3200 glEnable(GL_TEXTURE_GEN_T);
3201 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3202 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3203 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3204 glEnable(GL_TEXTURE_GEN_R);
3205 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3206 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3207 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3209 break;
3211 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3213 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3214 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3216 glMatrixMode(GL_MODELVIEW);
3217 glPushMatrix();
3218 glLoadIdentity();
3219 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3220 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3221 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3222 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3223 glPopMatrix();
3225 glEnable(GL_TEXTURE_GEN_S);
3226 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3227 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3228 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3229 glEnable(GL_TEXTURE_GEN_T);
3230 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3231 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3232 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3233 glEnable(GL_TEXTURE_GEN_R);
3234 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3235 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3236 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3239 break;
3241 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3243 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3244 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3246 glMatrixMode(GL_MODELVIEW);
3247 glPushMatrix();
3248 glLoadIdentity();
3249 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3250 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3251 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3252 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3253 glPopMatrix();
3255 glEnable(GL_TEXTURE_GEN_S);
3256 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3257 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3258 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3259 glEnable(GL_TEXTURE_GEN_T);
3260 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3261 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3262 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3263 glEnable(GL_TEXTURE_GEN_R);
3264 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3265 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3266 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3269 break;
3271 /* Unhandled types: */
3272 default:
3273 /* Todo: */
3274 /* ? disable GL_TEXTURE_GEN_n ? */
3275 glDisable(GL_TEXTURE_GEN_S);
3276 glDisable(GL_TEXTURE_GEN_T);
3277 glDisable(GL_TEXTURE_GEN_R);
3278 glDisable(GL_TEXTURE_GEN_Q);
3279 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3280 break;
3283 /* Update the texture matrix */
3284 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3285 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3288 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3289 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3290 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3291 * and do all the things linked to it
3292 * TODO: Tidy that up to reload only the arrays of the changed unit
3294 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3296 unloadTexCoords(stateblock);
3297 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3301 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3302 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3304 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3305 * has an update pending
3307 if(isStateDirty(context, STATE_VDECL) ||
3308 isStateDirty(context, STATE_PIXELSHADER)) {
3309 return;
3312 device->shader_backend->shader_load_constants((IWineD3DDevice *) device, use_ps(device), use_vs(device));
3315 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3316 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3318 if(stateblock->pixelShader && stage != 0 &&
3319 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3320 /* The pixel shader has to know the luminance scale. Do a constants update if it
3321 * isn't scheduled anyway
3323 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3324 !isStateDirty(context, STATE_PIXELSHADER)) {
3325 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3330 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3331 BOOL texIsPow2 = FALSE;
3332 DWORD sampler = state - STATE_SAMPLER(0);
3333 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3335 if(!texture) return;
3336 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3337 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3338 * scaling is reapplied or removed, the texture matrix has to be reapplied
3340 * The mapped stage is already active because the sampler() function below, which is part of the
3341 * misc pipeline
3343 if(sampler < MAX_TEXTURES) {
3344 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
3346 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3348 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
3349 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
3350 texIsPow2 = TRUE;
3353 else if (texture_dimensions == GL_TEXTURE_CUBE_MAP_ARB)
3355 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
3356 texIsPow2 = TRUE;
3360 if(texIsPow2 || context->lastWasPow2Texture[sampler]) {
3361 context->lastWasPow2Texture[sampler] = texIsPow2;
3362 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3367 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3368 DWORD sampler = state - STATE_SAMPLER(0);
3369 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3370 union {
3371 float f;
3372 DWORD d;
3373 } tmpvalue;
3375 TRACE("Sampler: %d\n", sampler);
3376 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3377 * only has to bind textures and set the per texture states
3380 if (mapped_stage == -1) {
3381 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3382 return;
3385 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3386 return;
3388 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3389 checkGLcall("glActiveTextureARB");
3391 if(stateblock->textures[sampler]) {
3392 IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]);
3393 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler]);
3394 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3396 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3397 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3398 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3399 GL_TEXTURE_LOD_BIAS_EXT,
3400 tmpvalue.f);
3401 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3404 if(!use_ps(stateblock->wineD3DDevice) && sampler < stateblock->lowest_disabled_stage) {
3405 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3406 /* If color keying is enabled update the alpha test, it depends on the existence
3407 * of a color key in stage 0
3409 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3412 } else if(mapped_stage < GL_LIMITS(textures)) {
3413 if(sampler < stateblock->lowest_disabled_stage) {
3414 /* TODO: What should I do with pixel shaders here ??? */
3415 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3416 /* If color keying is enabled update the alpha test, it depends on the existence
3417 * of a color key in stage 0
3419 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3421 } /* Otherwise tex_colorop disables the stage */
3422 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3423 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3427 static void apply_pshader_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3428 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3430 if (use_ps(device)) {
3431 if(!context->last_was_pshader) {
3432 state_fog(state, stateblock, context);
3434 context->last_was_pshader = TRUE;
3435 } else {
3436 if(context->last_was_pshader) {
3437 state_fog(state, stateblock, context);
3439 context->last_was_pshader = FALSE;
3443 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3444 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3445 BOOL use_pshader = use_ps(device);
3446 BOOL use_vshader = use_vs(device);
3447 int i;
3449 if (use_pshader) {
3450 if(!context->last_was_pshader) {
3451 /* Former draw without a pixel shader, some samplers
3452 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3453 * make sure to enable them
3455 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3456 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3457 sampler(STATE_SAMPLER(i), stateblock, context);
3460 } else {
3461 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3462 * if a different texture was bound. I don't have to do anything.
3465 } else {
3466 /* Disabled the pixel shader - color ops weren't applied
3467 * while it was enabled, so re-apply them.
3469 for(i=0; i < MAX_TEXTURES; i++) {
3470 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3471 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3472 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3477 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3478 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3480 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3481 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3486 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3487 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE;
3488 if(stateblock->pixelShader && stage != 0 &&
3489 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3490 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3491 * anyway
3493 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3494 !isStateDirty(context, STATE_PIXELSHADER)) {
3495 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3500 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3501 /* This function is called by transform_view below if the view matrix was changed too
3503 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3504 * does not always update the world matrix, only on a switch between transformed
3505 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3506 * draw, but that should be rather rare and cheaper in total.
3508 glMatrixMode(GL_MODELVIEW);
3509 checkGLcall("glMatrixMode");
3511 if(context->last_was_rhw) {
3512 glLoadIdentity();
3513 checkGLcall("glLoadIdentity()");
3514 } else {
3515 /* In the general case, the view matrix is the identity matrix */
3516 if (stateblock->wineD3DDevice->view_ident) {
3517 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3518 checkGLcall("glLoadMatrixf");
3519 } else {
3520 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3521 checkGLcall("glLoadMatrixf");
3522 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3523 checkGLcall("glMultMatrixf");
3528 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3529 UINT index = state - STATE_CLIPPLANE(0);
3531 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3532 return;
3535 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3536 glMatrixMode(GL_MODELVIEW);
3537 glPushMatrix();
3538 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3540 TRACE("Clipplane [%f,%f,%f,%f]\n",
3541 stateblock->clipplane[index][0],
3542 stateblock->clipplane[index][1],
3543 stateblock->clipplane[index][2],
3544 stateblock->clipplane[index][3]);
3545 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3546 checkGLcall("glClipPlane");
3548 glPopMatrix();
3551 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3552 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3553 GLenum glMat;
3554 TRACE("Setting world matrix %d\n", matrix);
3556 if(matrix >= GL_LIMITS(blends)) {
3557 WARN("Unsupported blend matrix set\n");
3558 return;
3559 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3560 return;
3563 /* GL_MODELVIEW0_ARB: 0x1700
3564 * GL_MODELVIEW1_ARB: 0x850a
3565 * GL_MODELVIEW2_ARB: 0x8722
3566 * GL_MODELVIEW3_ARB: 0x8723
3567 * etc
3568 * GL_MODELVIEW31_ARB: 0x873F
3570 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3571 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3573 glMatrixMode(glMat);
3574 checkGLcall("glMatrixMode(glMat)");
3576 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3577 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3579 if(stateblock->wineD3DDevice->view_ident) {
3580 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3581 checkGLcall("glLoadMatrixf");
3582 } else {
3583 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3584 checkGLcall("glLoadMatrixf");
3585 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3586 checkGLcall("glMultMatrixf");
3590 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3591 static BOOL once = FALSE;
3593 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3594 case WINED3DVBF_1WEIGHTS:
3595 case WINED3DVBF_2WEIGHTS:
3596 case WINED3DVBF_3WEIGHTS:
3597 if(!once) {
3598 once = TRUE;
3599 /* TODO: Implement vertex blending in drawStridedSlow */
3600 FIXME("Vertex blending enabled, but not supported by hardware\n");
3602 break;
3604 case WINED3DVBF_TWEENING:
3605 WARN("Tweening not supported yet\n");
3609 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3610 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3612 switch(val) {
3613 case WINED3DVBF_1WEIGHTS:
3614 case WINED3DVBF_2WEIGHTS:
3615 case WINED3DVBF_3WEIGHTS:
3616 glEnable(GL_VERTEX_BLEND_ARB);
3617 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3619 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3620 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3622 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3624 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3625 int i;
3626 for(i = 1; i < GL_LIMITS(blends); i++) {
3627 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3628 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3631 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3633 break;
3635 case WINED3DVBF_DISABLE:
3636 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3637 glDisable(GL_VERTEX_BLEND_ARB);
3638 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3639 break;
3641 case WINED3DVBF_TWEENING:
3642 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3643 * vertex weights in the vertices?
3644 * For now we don't report that as supported, so a warn should suffice
3646 WARN("Tweening not supported yet\n");
3647 break;
3651 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3652 unsigned int k;
3654 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3655 * NOTE: We have to reset the positions even if the light/plane is not currently
3656 * enabled, since the call to enable it will not reset the position.
3657 * NOTE2: Apparently texture transforms do NOT need reapplying
3660 const PLIGHTINFOEL *light = NULL;
3662 glMatrixMode(GL_MODELVIEW);
3663 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3664 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3665 checkGLcall("glLoadMatrixf(...)");
3667 /* Reset lights. TODO: Call light apply func */
3668 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3669 light = stateblock->activeLights[k];
3670 if(!light) continue;
3671 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3672 checkGLcall("glLightfv posn");
3673 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3674 checkGLcall("glLightfv dirn");
3677 /* Reset Clipping Planes */
3678 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3679 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3680 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3684 if(context->last_was_rhw) {
3685 glLoadIdentity();
3686 checkGLcall("glLoadIdentity()");
3687 /* No need to update the world matrix, the identity is fine */
3688 return;
3691 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3692 * No need to do it here if the state is scheduled for update.
3694 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3695 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3698 /* Avoid looping over a number of matrices if the app never used the functionality */
3699 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3700 for(k = 1; k < GL_LIMITS(blends); k++) {
3701 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3702 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3708 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3709 glMatrixMode(GL_PROJECTION);
3710 checkGLcall("glMatrixMode(GL_PROJECTION)");
3711 glLoadIdentity();
3712 checkGLcall("glLoadIdentity");
3714 if(context->last_was_rhw) {
3715 double X, Y, height, width, minZ, maxZ;
3717 X = stateblock->viewport.X;
3718 Y = stateblock->viewport.Y;
3719 height = stateblock->viewport.Height;
3720 width = stateblock->viewport.Width;
3721 minZ = stateblock->viewport.MinZ;
3722 maxZ = stateblock->viewport.MaxZ;
3724 if(!stateblock->wineD3DDevice->untransformed) {
3725 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3726 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3727 * suppress depth clipping. This can be done because it is an orthogonal projection and
3728 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3729 * Persia 3D need this.
3731 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3732 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3733 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3734 * to the viewer.
3736 * Also note that this breaks z comparison against z values filled in with clear,
3737 * but no app depending on that and disabled clipping has been found yet. Comparing
3738 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3739 * surface removal.
3741 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3742 * but this would break Z buffer operation. Raising the range to something less than
3743 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3744 * problem either.
3746 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3747 if(stateblock->wineD3DDevice->render_offscreen) {
3748 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3749 } else {
3750 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3752 } else {
3753 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3754 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3755 * unmodified to opengl.
3757 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3758 * replacement shader.
3760 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3761 if(stateblock->wineD3DDevice->render_offscreen) {
3762 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3763 } else {
3764 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3767 checkGLcall("glOrtho");
3769 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3770 glTranslatef(0.5, 0.5, 0);
3771 checkGLcall("glTranslatef(0.5, 0.5, 0)");
3772 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3773 * render everything upside down when rendering offscreen. */
3774 if (stateblock->wineD3DDevice->render_offscreen) {
3775 glScalef(1.0, -1.0, 1.0);
3776 checkGLcall("glScalef");
3778 } else {
3779 /* The rule is that the window coordinate 0 does not correspond to the
3780 beginning of the first pixel, but the center of the first pixel.
3781 As a consequence if you want to correctly draw one line exactly from
3782 the left to the right end of the viewport (with all matrices set to
3783 be identity), the x coords of both ends of the line would be not
3784 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3785 instead.
3787 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3788 divide by the Width/Height, so we need the half range(1.0) to translate by
3789 half a pixel.
3791 The other fun is that d3d's output z range after the transformation is [0;1],
3792 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3793 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3794 of Z buffer precision and the clear values do not match in the z test. Thus scale
3795 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3799 * Careful with the order of operations here, we're essentially working backwards:
3800 * x = x + 1/w;
3801 * y = (y - 1/h) * flip;
3802 * z = z * 2 - 1;
3804 * Becomes:
3805 * glTranslatef(0.0, 0.0, -1.0);
3806 * glScalef(1.0, 1.0, 2.0);
3808 * glScalef(1.0, flip, 1.0);
3809 * glTranslatef(1/w, -1/h, 0.0);
3811 * This is equivalent to:
3812 * glTranslatef(1/w, -flip/h, -1.0)
3813 * glScalef(1.0, flip, 2.0);
3816 if (stateblock->wineD3DDevice->render_offscreen) {
3817 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3818 * render everything upside down when rendering offscreen. */
3819 glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3820 checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3821 glScalef(1.0, -1.0, 2.0);
3822 } else {
3823 glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3824 checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3825 glScalef(1.0, 1.0, 2.0);
3827 checkGLcall("glScalef");
3829 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3830 checkGLcall("glLoadMatrixf");
3834 /* This should match any arrays loaded in loadVertexData.
3835 * stateblock impl is required for GL_SUPPORT
3836 * TODO: Only load / unload arrays if we have to.
3838 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3839 glDisableClientState(GL_VERTEX_ARRAY);
3840 glDisableClientState(GL_NORMAL_ARRAY);
3841 glDisableClientState(GL_COLOR_ARRAY);
3842 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3843 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3845 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3846 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3848 unloadTexCoords(stateblock);
3851 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3853 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3854 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3855 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3856 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3857 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3858 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3859 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3861 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3862 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3864 context->numbered_array_mask &= ~(1 << i);
3867 /* This should match any arrays loaded in loadNumberedArrays
3868 * TODO: Only load / unload arrays if we have to.
3870 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3872 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3873 GLint maxAttribs = 16;
3874 int i;
3876 /* Leave all the attribs disabled */
3877 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3878 /* MESA does not support it right not */
3879 if (glGetError() != GL_NO_ERROR)
3880 maxAttribs = 16;
3881 for (i = 0; i < maxAttribs; ++i) {
3882 unload_numbered_array(stateblock, context, i);
3886 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3887 const WineDirect3DVertexStridedData *strided, WineD3DContext *context)
3889 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3890 int i;
3891 const UINT *offset = stateblock->streamOffset;
3892 IWineD3DVertexBufferImpl *vb;
3893 DWORD_PTR shift_index;
3895 /* Default to no instancing */
3896 stateblock->wineD3DDevice->instancedDraw = FALSE;
3898 for (i = 0; i < MAX_ATTRIBS; i++) {
3899 if (!strided->u.input[i].VBO && !strided->u.input[i].lpData)
3901 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3902 continue;
3905 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3906 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3907 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3908 stateblock->wineD3DDevice->instancedDraw = TRUE;
3909 continue;
3912 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3914 if(strided->u.input[i].dwStride) {
3915 if(curVBO != strided->u.input[i].VBO) {
3916 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3917 checkGLcall("glBindBufferARB");
3918 curVBO = strided->u.input[i].VBO;
3920 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3921 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3922 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3923 * vbo we won't be load converted attributes anyway
3925 if(curVBO && vb->conv_shift) {
3926 TRACE("Loading attribute from shifted buffer\n");
3927 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
3928 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3929 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3930 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3931 shift_index = shift_index % strided->u.input[i].dwStride;
3932 GL_EXTCALL(glVertexAttribPointerARB(i,
3933 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3934 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3935 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3936 vb->conv_stride,
3938 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
3939 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3940 offset[strided->u.input[i].streamNo]));
3942 } else {
3943 GL_EXTCALL(glVertexAttribPointerARB(i,
3944 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
3945 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3946 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3947 strided->u.input[i].dwStride,
3949 strided->u.input[i].lpData +
3950 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3951 offset[strided->u.input[i].streamNo]) );
3954 if (!(context->numbered_array_mask & (1 << i)))
3956 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3957 context->numbered_array_mask |= (1 << i);
3959 } else {
3960 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3961 * set up the attribute statically. But we have to figure out the system memory address.
3963 const BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3964 if(strided->u.input[i].VBO) {
3965 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3966 ptr += (long) vb->resource.allocatedMemory;
3969 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3971 switch(strided->u.input[i].dwType) {
3972 case WINED3DDECLTYPE_FLOAT1:
3973 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3974 break;
3975 case WINED3DDECLTYPE_FLOAT2:
3976 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3977 break;
3978 case WINED3DDECLTYPE_FLOAT3:
3979 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3980 break;
3981 case WINED3DDECLTYPE_FLOAT4:
3982 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3983 break;
3985 case WINED3DDECLTYPE_UBYTE4:
3986 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3987 break;
3988 case WINED3DDECLTYPE_UBYTE4N:
3989 case WINED3DDECLTYPE_D3DCOLOR:
3990 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3991 break;
3993 case WINED3DDECLTYPE_SHORT2:
3994 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3995 break;
3996 case WINED3DDECLTYPE_SHORT4:
3997 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3998 break;
4000 case WINED3DDECLTYPE_SHORT2N:
4002 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
4003 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
4004 break;
4006 case WINED3DDECLTYPE_USHORT2N:
4008 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
4009 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
4010 break;
4012 case WINED3DDECLTYPE_SHORT4N:
4013 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
4014 break;
4015 case WINED3DDECLTYPE_USHORT4N:
4016 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
4017 break;
4019 case WINED3DDECLTYPE_UDEC3:
4020 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
4021 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
4022 break;
4023 case WINED3DDECLTYPE_DEC3N:
4024 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
4025 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
4026 break;
4028 case WINED3DDECLTYPE_FLOAT16_2:
4029 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4030 * byte float according to the IEEE standard
4032 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4033 break;
4034 case WINED3DDECLTYPE_FLOAT16_4:
4035 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4036 break;
4038 case WINED3DDECLTYPE_UNUSED:
4039 default:
4040 ERR("Unexpected declaration in stride 0 attributes\n");
4041 break;
4046 checkGLcall("Loading numbered arrays");
4049 /* Used from 2 different functions, and too big to justify making it inlined */
4050 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd)
4052 const UINT *offset = stateblock->streamOffset;
4053 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
4055 TRACE("Using fast vertex array code\n");
4057 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4058 stateblock->wineD3DDevice->instancedDraw = FALSE;
4060 /* Blend Data ---------------------------------------------- */
4061 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
4062 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
4064 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4065 TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
4066 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4068 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4069 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4071 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
4073 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4074 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
4075 sd->u.s.blendWeights.dwStride,
4076 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4078 if(curVBO != sd->u.s.blendWeights.VBO) {
4079 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
4080 checkGLcall("glBindBufferARB");
4081 curVBO = sd->u.s.blendWeights.VBO;
4084 GL_EXTCALL(glWeightPointerARB)(
4085 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
4086 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
4087 sd->u.s.blendWeights.dwStride,
4088 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4090 checkGLcall("glWeightPointerARB");
4092 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
4093 static BOOL warned;
4094 if (!warned)
4096 FIXME("blendMatrixIndices support\n");
4097 warned = TRUE;
4100 } else {
4101 /* TODO: support blends in drawStridedSlow
4102 * No need to write a FIXME here, this is done after the general vertex decl decoding
4104 WARN("unsupported blending in openGl\n");
4106 } else {
4107 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4108 static const GLbyte one = 1;
4109 GL_EXTCALL(glWeightbvARB(1, &one));
4110 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4114 /* Point Size ----------------------------------------------*/
4115 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
4117 /* no such functionality in the fixed function GL pipeline */
4118 TRACE("Cannot change ptSize here in openGl\n");
4119 /* TODO: Implement this function in using shaders if they are available */
4123 /* Vertex Pointers -----------------------------------------*/
4124 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
4125 /* Note dwType == float3 or float4 == 2 or 3 */
4126 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
4127 sd->u.s.position.dwStride,
4128 sd->u.s.position.dwType + 1,
4129 sd->u.s.position.lpData));
4131 if(curVBO != sd->u.s.position.VBO) {
4132 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
4133 checkGLcall("glBindBufferARB");
4134 curVBO = sd->u.s.position.VBO;
4137 /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
4138 handling for rhw mode should not impact screen position whereas in GL it does.
4139 This may result in very slightly distorted textures in rhw mode.
4140 There's always the other option of fixing the view matrix to
4141 prevent w from having any effect.
4143 This only applies to user pointer sources, in VBOs the vertices are fixed up
4145 if(sd->u.s.position.VBO == 0) {
4146 glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
4147 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4148 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4149 } else {
4150 glVertexPointer(
4151 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
4152 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4153 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4155 checkGLcall("glVertexPointer(...)");
4156 glEnableClientState(GL_VERTEX_ARRAY);
4157 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4160 /* Normals -------------------------------------------------*/
4161 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
4162 /* Note dwType == float3 or float4 == 2 or 3 */
4163 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
4164 sd->u.s.normal.dwStride,
4165 sd->u.s.normal.lpData));
4166 if(curVBO != sd->u.s.normal.VBO) {
4167 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
4168 checkGLcall("glBindBufferARB");
4169 curVBO = sd->u.s.normal.VBO;
4171 glNormalPointer(
4172 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
4173 sd->u.s.normal.dwStride,
4174 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
4175 checkGLcall("glNormalPointer(...)");
4176 glEnableClientState(GL_NORMAL_ARRAY);
4177 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4179 } else {
4180 glNormal3f(0, 0, 0);
4181 checkGLcall("glNormal3f(0, 0, 0)");
4184 /* Diffuse Colour --------------------------------------------*/
4185 /* WARNING: Data here MUST be in RGBA format, so cannot */
4186 /* go directly into fast mode from app pgm, because */
4187 /* directx requires data in BGRA format. */
4188 /* currently fixupVertices swizzles the format, but this isn't*/
4189 /* very practical when using VBOs */
4190 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4191 /* , or the user doesn't care and wants the speed advantage */
4193 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
4194 /* Note dwType == float3 or float4 == 2 or 3 */
4195 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4196 sd->u.s.diffuse.dwStride,
4197 sd->u.s.diffuse.lpData));
4199 if(curVBO != sd->u.s.diffuse.VBO) {
4200 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
4201 checkGLcall("glBindBufferARB");
4202 curVBO = sd->u.s.diffuse.VBO;
4205 glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
4206 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
4207 sd->u.s.diffuse.dwStride,
4208 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
4209 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4210 glEnableClientState(GL_COLOR_ARRAY);
4211 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4213 } else {
4214 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4215 checkGLcall("glColor4f(1, 1, 1, 1)");
4218 /* Specular Colour ------------------------------------------*/
4219 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
4220 TRACE("setting specular colour\n");
4221 /* Note dwType == float3 or float4 == 2 or 3 */
4222 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4223 sd->u.s.specular.dwStride,
4224 sd->u.s.specular.lpData));
4225 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4226 if(curVBO != sd->u.s.specular.VBO) {
4227 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
4228 checkGLcall("glBindBufferARB");
4229 curVBO = sd->u.s.specular.VBO;
4231 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
4232 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
4233 sd->u.s.specular.dwStride,
4234 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
4235 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4236 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4237 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4238 } else {
4240 /* Missing specular color is not critical, no warnings */
4241 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4244 } else {
4245 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4246 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4247 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4248 } else {
4250 /* Missing specular color is not critical, no warnings */
4251 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4255 /* Texture coords -------------------------------------------*/
4256 loadTexCoords(stateblock, sd, &curVBO);
4259 static inline void drawPrimitiveTraceDataLocations(const WineDirect3DVertexStridedData *dataLocations)
4261 /* Dump out what parts we have supplied */
4262 TRACE("Strided Data:\n");
4263 TRACE_STRIDED((dataLocations), position);
4264 TRACE_STRIDED((dataLocations), blendWeights);
4265 TRACE_STRIDED((dataLocations), blendMatrixIndices);
4266 TRACE_STRIDED((dataLocations), normal);
4267 TRACE_STRIDED((dataLocations), pSize);
4268 TRACE_STRIDED((dataLocations), diffuse);
4269 TRACE_STRIDED((dataLocations), specular);
4270 TRACE_STRIDED((dataLocations), texCoords[0]);
4271 TRACE_STRIDED((dataLocations), texCoords[1]);
4272 TRACE_STRIDED((dataLocations), texCoords[2]);
4273 TRACE_STRIDED((dataLocations), texCoords[3]);
4274 TRACE_STRIDED((dataLocations), texCoords[4]);
4275 TRACE_STRIDED((dataLocations), texCoords[5]);
4276 TRACE_STRIDED((dataLocations), texCoords[6]);
4277 TRACE_STRIDED((dataLocations), texCoords[7]);
4278 TRACE_STRIDED((dataLocations), position2);
4279 TRACE_STRIDED((dataLocations), normal2);
4280 TRACE_STRIDED((dataLocations), tangent);
4281 TRACE_STRIDED((dataLocations), binormal);
4282 TRACE_STRIDED((dataLocations), tessFactor);
4283 TRACE_STRIDED((dataLocations), fog);
4284 TRACE_STRIDED((dataLocations), depth);
4285 TRACE_STRIDED((dataLocations), sample);
4287 return;
4290 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4291 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4292 BOOL fixup = FALSE;
4293 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
4294 BOOL useVertexShaderFunction;
4295 BOOL load_numbered = FALSE;
4296 BOOL load_named = FALSE;
4298 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4300 if(device->up_strided) {
4301 /* Note: this is a ddraw fixed-function code path */
4302 TRACE("================ Strided Input ===================\n");
4303 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
4305 if(TRACE_ON(d3d)) {
4306 drawPrimitiveTraceDataLocations(dataLocations);
4308 } else {
4309 /* Note: This is a fixed function or shader codepath.
4310 * This means it must handle both types of strided data.
4311 * Shaders must go through here to zero the strided data, even if they
4312 * don't set any declaration at all
4314 TRACE("================ Vertex Declaration ===================\n");
4315 memset(dataLocations, 0, sizeof(*dataLocations));
4316 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
4317 useVertexShaderFunction, dataLocations, &fixup);
4320 if (dataLocations->u.s.position_transformed) {
4321 useVertexShaderFunction = FALSE;
4324 if(useVertexShaderFunction) {
4325 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4326 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4327 device->useDrawStridedSlow = TRUE;
4328 } else {
4329 load_numbered = TRUE;
4330 device->useDrawStridedSlow = FALSE;
4332 } else if (fixup ||
4333 (dataLocations->u.s.pSize.lpData == NULL &&
4334 dataLocations->u.s.diffuse.lpData == NULL &&
4335 dataLocations->u.s.specular.lpData == NULL)) {
4336 /* Load the vertex data using named arrays */
4337 load_named = TRUE;
4338 device->useDrawStridedSlow = FALSE;
4339 } else {
4340 TRACE("Not loading vertex data\n");
4341 device->useDrawStridedSlow = TRUE;
4344 if (context->numberedArraysLoaded && !load_numbered)
4346 unloadNumberedArrays(stateblock, context);
4347 context->numberedArraysLoaded = FALSE;
4348 context->numbered_array_mask = 0;
4350 else if (context->namedArraysLoaded)
4352 unloadVertexData(stateblock);
4353 context->namedArraysLoaded = FALSE;
4356 if (load_numbered)
4358 TRACE("Loading numbered arrays\n");
4359 loadNumberedArrays(stateblock, dataLocations, context);
4360 context->numberedArraysLoaded = TRUE;
4362 else if (load_named)
4364 TRACE("Loading vertex data\n");
4365 loadVertexData(stateblock, dataLocations);
4366 context->namedArraysLoaded = TRUE;
4369 /* Generate some fixme's if unsupported functionality is being used */
4370 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
4371 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
4372 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
4373 FIXME("Tweening is only valid with vertex shaders\n");
4375 if (!useVertexShaderFunction && BUFFER_OR_DATA(binormal)) {
4376 FIXME("Binormal bump mapping is only valid with vertex shaders\n");
4378 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
4379 FIXME("Extended attributes are only valid with vertex shaders\n");
4381 #undef BUFFER_OR_DATA
4384 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4385 BOOL updateFog = FALSE;
4386 BOOL useVertexShaderFunction = use_vs(stateblock->wineD3DDevice);
4387 BOOL usePixelShaderFunction = use_ps(stateblock->wineD3DDevice);
4388 BOOL transformed;
4389 /* Some stuff is in the device until we have per context tracking */
4390 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4391 BOOL wasrhw = context->last_was_rhw;
4393 if (useVertexShaderFunction)
4395 if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
4396 updateFog = TRUE;
4398 } else if(context->last_was_foggy_shader) {
4399 updateFog = TRUE;
4402 transformed = device->strided_streams.u.s.position_transformed;
4403 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4404 updateFog = TRUE;
4407 /* Reapply lighting if it is not scheduled for reapplication already */
4408 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4409 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4412 if (transformed) {
4413 context->last_was_rhw = TRUE;
4414 } else {
4416 /* Untransformed, so relies on the view and projection matrices */
4417 context->last_was_rhw = FALSE;
4418 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4419 device->untransformed = TRUE;
4421 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4422 * Not needed as long as only hw shaders are supported
4425 /* This sets the shader output position correction constants.
4426 * TODO: Move to the viewport state
4428 if (useVertexShaderFunction) {
4429 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4430 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4434 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4435 * off this function will be called again anyway to make sure they're properly set
4437 if(!useVertexShaderFunction) {
4438 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4439 * or transformed / untransformed was switched
4441 if(wasrhw != context->last_was_rhw &&
4442 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4443 !isStateDirty(context, STATE_VIEWPORT)) {
4444 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4446 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4447 * mode.
4449 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4450 * this check will fail and the matrix not applied again. This is OK because a simple
4451 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4452 * needs of the vertex declaration.
4454 * World and view matrix go into the same gl matrix, so only apply them when neither is
4455 * dirty
4457 if(transformed != wasrhw &&
4458 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4459 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4460 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4463 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4464 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4467 if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4468 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4470 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4471 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4473 } else {
4474 if(!context->last_was_vshader) {
4475 int i;
4476 static BOOL warned = FALSE;
4477 /* Disable all clip planes to get defined results on all drivers. See comment in the
4478 * state_clipping state handler
4480 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4481 glDisable(GL_CLIP_PLANE0 + i);
4482 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4485 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4486 FIXME("Clipping not supported with vertex shaders\n");
4487 warned = TRUE;
4489 if(wasrhw) {
4490 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4491 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4492 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4493 * fixed function vertex processing states back in a sane state before switching to shaders
4495 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4496 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4498 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4499 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4505 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4506 * application
4508 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4509 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4511 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4512 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4516 context->last_was_vshader = useVertexShaderFunction;
4518 if(updateFog) {
4519 state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
4521 if(!useVertexShaderFunction) {
4522 int i;
4523 for(i = 0; i < MAX_TEXTURES; i++) {
4524 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4525 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4531 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4532 UINT width, height;
4533 IWineD3DSurfaceImpl *target;
4535 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4536 checkGLcall("glDepthRange");
4537 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4539 if(stateblock->wineD3DDevice->render_offscreen) {
4540 glViewport(stateblock->viewport.X,
4541 stateblock->viewport.Y,
4542 stateblock->viewport.Width, stateblock->viewport.Height);
4543 } else {
4544 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4545 target->get_drawable_size(target, &width, &height);
4547 glViewport(stateblock->viewport.X,
4548 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4549 stateblock->viewport.Width, stateblock->viewport.Height);
4552 checkGLcall("glViewport");
4555 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4556 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4557 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4558 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4559 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4561 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4562 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4566 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4567 UINT Index = state - STATE_ACTIVELIGHT(0);
4568 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4570 if(!lightInfo) {
4571 glDisable(GL_LIGHT0 + Index);
4572 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4573 } else {
4574 float quad_att;
4575 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4577 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4578 glMatrixMode(GL_MODELVIEW);
4579 glPushMatrix();
4580 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4582 /* Diffuse: */
4583 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4584 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4585 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4586 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4587 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4588 checkGLcall("glLightfv");
4590 /* Specular */
4591 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4592 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4593 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4594 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4595 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4596 checkGLcall("glLightfv");
4598 /* Ambient */
4599 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4600 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4601 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4602 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4603 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4604 checkGLcall("glLightfv");
4606 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4607 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4608 } else {
4609 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
4612 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4613 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4614 * Attenuation0 to NaN and crashes in the gl lib
4617 switch (lightInfo->OriginalParms.Type) {
4618 case WINED3DLIGHT_POINT:
4619 /* Position */
4620 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4621 checkGLcall("glLightfv");
4622 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4623 checkGLcall("glLightf");
4624 /* Attenuation - Are these right? guessing... */
4625 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4626 checkGLcall("glLightf");
4627 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4628 checkGLcall("glLightf");
4629 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4630 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4631 checkGLcall("glLightf");
4632 /* FIXME: Range */
4633 break;
4635 case WINED3DLIGHT_SPOT:
4636 /* Position */
4637 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4638 checkGLcall("glLightfv");
4639 /* Direction */
4640 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4641 checkGLcall("glLightfv");
4642 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4643 checkGLcall("glLightf");
4644 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4645 checkGLcall("glLightf");
4646 /* Attenuation - Are these right? guessing... */
4647 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4648 checkGLcall("glLightf");
4649 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4650 checkGLcall("glLightf");
4651 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4652 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4653 checkGLcall("glLightf");
4654 /* FIXME: Range */
4655 break;
4657 case WINED3DLIGHT_DIRECTIONAL:
4658 /* Direction */
4659 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4660 checkGLcall("glLightfv");
4661 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4662 checkGLcall("glLightf");
4663 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4664 checkGLcall("glLightf");
4665 break;
4667 default:
4668 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4671 /* Restore the modelview matrix */
4672 glPopMatrix();
4674 glEnable(GL_LIGHT0 + Index);
4675 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4678 return;
4681 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4682 RECT *pRect = &stateblock->scissorRect;
4683 UINT height;
4684 UINT width;
4685 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4687 target->get_drawable_size(target, &width, &height);
4688 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4689 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4691 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4692 pRect->right - pRect->left, pRect->bottom - pRect->top);
4694 if (stateblock->wineD3DDevice->render_offscreen) {
4695 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4696 } else {
4697 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4699 checkGLcall("glScissor");
4702 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4703 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4704 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4705 } else {
4706 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
4707 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
4711 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4712 if(stateblock->wineD3DDevice->render_offscreen) {
4713 glFrontFace(GL_CCW);
4714 checkGLcall("glFrontFace(GL_CCW)");
4715 } else {
4716 glFrontFace(GL_CW);
4717 checkGLcall("glFrontFace(GL_CW)");
4721 const struct StateEntryTemplate misc_state_template[] = {
4722 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4723 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4724 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4725 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4726 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4727 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4728 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4729 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4730 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4731 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4732 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
4733 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
4734 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
4735 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
4736 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4737 * vshader loadings are untied from each other
4739 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4740 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4741 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4742 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4743 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4744 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4745 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4746 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4747 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4748 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4749 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4750 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4751 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4752 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4753 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4754 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4755 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4756 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4757 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4758 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4759 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4760 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4761 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4762 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4763 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4764 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4765 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4766 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4767 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4768 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4769 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4770 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4771 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4772 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4773 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4774 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4775 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4776 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4777 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4778 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4779 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4780 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4781 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4782 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4783 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4784 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4785 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4786 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4787 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4788 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4790 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
4791 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4792 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
4793 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
4794 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
4795 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
4796 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
4797 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
4798 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
4799 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
4800 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
4801 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
4802 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
4803 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
4804 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4805 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4806 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4807 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4808 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
4809 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
4810 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
4811 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
4812 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
4813 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
4814 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
4815 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
4816 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
4817 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
4818 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
4819 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
4820 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
4821 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4822 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4823 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4824 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4825 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4826 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4827 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4828 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4829 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
4830 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4831 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4832 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4833 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4834 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4835 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4836 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4837 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4838 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4839 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4840 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4841 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4842 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4843 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4844 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4845 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4846 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4847 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4848 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4849 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4850 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4851 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
4852 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
4853 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
4854 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
4855 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
4856 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
4857 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4858 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4859 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4860 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4861 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4862 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4863 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4864 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4865 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 },
4866 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
4867 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4868 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4869 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 },
4870 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
4871 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4872 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4873 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4874 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4875 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
4876 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 },
4877 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4878 /* Samplers */
4879 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
4880 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
4881 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
4882 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
4883 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
4884 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
4885 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
4886 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
4887 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
4888 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
4889 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
4890 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
4891 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
4892 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
4893 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
4894 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
4895 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
4896 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
4897 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
4898 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
4899 {0 /* Terminate */, { 0, 0 }, 0 },
4902 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4903 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
4904 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
4905 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4906 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4907 /* Clip planes */
4908 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
4909 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
4910 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
4911 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
4912 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
4913 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
4914 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
4915 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
4916 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
4917 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
4918 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
4919 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
4920 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
4921 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
4922 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
4923 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
4924 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
4925 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
4926 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
4927 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
4928 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
4929 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
4930 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
4931 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
4932 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
4933 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
4934 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
4935 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
4936 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
4937 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
4938 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
4939 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
4940 /* Lights */
4941 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
4942 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
4943 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
4944 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
4945 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
4946 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
4947 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
4948 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
4949 /* Viewport */
4950 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
4951 /* Transform states follow */
4952 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
4953 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
4954 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4955 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4956 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4957 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4958 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4959 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4960 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4961 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4962 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4963 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, 0 },
4964 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, 0 },
4965 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, 0 },
4966 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, 0 },
4967 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, 0 },
4968 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, 0 },
4969 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, 0 },
4970 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, 0 },
4971 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, 0 },
4972 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, 0 },
4973 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, 0 },
4974 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, 0 },
4975 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, 0 },
4976 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, 0 },
4977 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, 0 },
4978 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, 0 },
4979 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, 0 },
4980 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, 0 },
4981 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, 0 },
4982 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, 0 },
4983 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, 0 },
4984 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, 0 },
4985 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, 0 },
4986 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, 0 },
4987 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, 0 },
4988 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, 0 },
4989 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, 0 },
4990 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, 0 },
4991 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, 0 },
4992 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, 0 },
4993 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, 0 },
4994 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, 0 },
4995 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, 0 },
4996 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, 0 },
4997 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, 0 },
4998 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, 0 },
4999 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, 0 },
5000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, 0 },
5001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, 0 },
5002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, 0 },
5003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, 0 },
5004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, 0 },
5005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, 0 },
5006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, 0 },
5007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, 0 },
5008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, 0 },
5009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, 0 },
5010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, 0 },
5011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, 0 },
5012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, 0 },
5013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, 0 },
5014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, 0 },
5015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, 0 },
5016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, 0 },
5017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, 0 },
5018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, 0 },
5019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, 0 },
5020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, 0 },
5021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, 0 },
5022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, 0 },
5023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, 0 },
5024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, 0 },
5025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, 0 },
5026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, 0 },
5027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, 0 },
5028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, 0 },
5029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, 0 },
5030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, 0 },
5031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, 0 },
5032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, 0 },
5033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, 0 },
5034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, 0 },
5035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, 0 },
5036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, 0 },
5037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, 0 },
5038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, 0 },
5039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, 0 },
5040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, 0 },
5041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, 0 },
5042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, 0 },
5043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, 0 },
5044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, 0 },
5045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, 0 },
5046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, 0 },
5047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, 0 },
5048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, 0 },
5049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, 0 },
5050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, 0 },
5051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, 0 },
5052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, 0 },
5053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, 0 },
5054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, 0 },
5055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, 0 },
5056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, 0 },
5057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, 0 },
5058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, 0 },
5059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, 0 },
5060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, 0 },
5061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, 0 },
5062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, 0 },
5063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, 0 },
5064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, 0 },
5065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, 0 },
5066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, 0 },
5067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, 0 },
5068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, 0 },
5069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, 0 },
5070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, 0 },
5071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, 0 },
5072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, 0 },
5073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, 0 },
5074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, 0 },
5075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, 0 },
5076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, 0 },
5077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, 0 },
5078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, 0 },
5079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, 0 },
5080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, 0 },
5081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, 0 },
5082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, 0 },
5083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, 0 },
5084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, 0 },
5085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, 0 },
5086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, 0 },
5087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, 0 },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, 0 },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, 0 },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, 0 },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, 0 },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, 0 },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, 0 },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, 0 },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, 0 },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, 0 },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, 0 },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, 0 },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, 0 },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, 0 },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, 0 },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, 0 },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, 0 },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, 0 },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, 0 },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, 0 },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, 0 },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, 0 },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, 0 },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, 0 },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, 0 },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, 0 },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, 0 },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, 0 },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, 0 },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, 0 },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, 0 },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, 0 },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, 0 },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, 0 },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, 0 },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, 0 },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, 0 },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, 0 },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, 0 },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, 0 },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, 0 },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, 0 },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, 0 },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, 0 },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, 0 },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, 0 },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, 0 },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, 0 },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, 0 },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, 0 },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, 0 },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, 0 },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, 0 },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, 0 },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, 0 },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, 0 },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, 0 },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, 0 },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, 0 },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, 0 },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, 0 },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, 0 },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, 0 },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, 0 },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, 0 },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, 0 },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, 0 },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, 0 },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, 0 },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, 0 },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, 0 },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, 0 },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, 0 },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, 0 },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, 0 },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, 0 },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, 0 },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, 0 },
5165 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, 0 },
5166 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, 0 },
5167 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, 0 },
5168 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, 0 },
5169 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, 0 },
5170 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, 0 },
5171 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, 0 },
5172 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, 0 },
5173 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, 0 },
5174 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, 0 },
5175 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, 0 },
5176 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, 0 },
5177 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, 0 },
5178 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, 0 },
5179 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, 0 },
5180 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, 0 },
5181 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, 0 },
5182 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, 0 },
5183 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, 0 },
5184 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, 0 },
5185 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, 0 },
5186 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, 0 },
5187 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, 0 },
5188 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, 0 },
5189 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, 0 },
5190 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, 0 },
5191 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, 0 },
5192 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, 0 },
5193 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, 0 },
5194 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, 0 },
5195 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, 0 },
5196 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, 0 },
5197 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, 0 },
5198 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, 0 },
5199 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, 0 },
5200 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, 0 },
5201 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, 0 },
5202 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, 0 },
5203 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, 0 },
5204 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, 0 },
5205 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, 0 },
5206 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, 0 },
5207 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, 0 },
5208 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, 0 },
5209 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, 0 },
5210 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, 0 },
5211 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, 0 },
5212 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, 0 },
5213 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, 0 },
5214 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, 0 },
5215 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, 0 },
5216 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, 0 },
5217 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, 0 },
5218 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5219 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5220 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5221 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5222 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5223 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5224 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5225 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5226 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5227 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5228 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5229 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5230 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5231 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5232 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5233 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5234 /* Fog */
5235 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5236 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5237 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5238 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5239 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog }, 0 },
5240 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
5241 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
5242 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5243 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 },
5244 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5245 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5246 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
5247 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
5248 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5249 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
5250 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
5251 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5252 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5253 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5254 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5255 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5256 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, 0 },
5257 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5258 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5259 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5260 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5261 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5262 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 },
5263 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5264 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5265 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5266 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5267 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5268 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5269 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5270 /* pixel shaders need a different fog input */
5271 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pshader_fog }, 0 },
5272 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5273 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5274 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5276 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5277 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5278 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
5279 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5280 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5281 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
5282 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5283 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5284 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
5285 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5286 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5287 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
5288 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5289 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5290 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
5291 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5292 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5293 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
5294 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5295 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5296 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
5297 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5298 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5299 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
5300 {0 /* Terminate */, { 0, 0 }, 0 },
5303 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5304 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5305 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5306 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5307 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5308 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5309 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5310 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5311 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5312 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5313 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5314 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5315 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5316 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5317 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5318 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5319 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5320 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5321 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5322 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5323 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5324 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5325 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5326 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5327 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5328 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5329 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5330 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5331 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5332 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5333 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5334 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5335 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5336 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5337 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5338 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5339 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5340 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5341 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5342 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5343 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5344 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5345 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5346 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5347 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5348 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5349 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5350 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5351 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5352 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5353 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5354 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5355 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5356 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5357 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5358 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5359 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5360 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5361 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5362 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5363 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5364 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5365 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5366 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5367 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5368 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5369 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5370 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5371 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5372 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5373 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5374 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5375 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5376 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5377 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5378 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5379 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5380 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5381 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5382 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5383 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5384 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5385 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5386 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
5387 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
5388 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
5389 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
5390 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
5391 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
5392 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
5393 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
5394 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
5395 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
5396 {0 /* Terminate */, { 0, 0 }, 0 },
5398 #undef GLINFO_LOCATION
5400 #define GLINFO_LOCATION (*gl_info)
5401 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5403 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5405 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5406 WINED3DTEXOPCAPS_ADDSIGNED |
5407 WINED3DTEXOPCAPS_ADDSIGNED2X |
5408 WINED3DTEXOPCAPS_MODULATE |
5409 WINED3DTEXOPCAPS_MODULATE2X |
5410 WINED3DTEXOPCAPS_MODULATE4X |
5411 WINED3DTEXOPCAPS_SELECTARG1 |
5412 WINED3DTEXOPCAPS_SELECTARG2 |
5413 WINED3DTEXOPCAPS_DISABLE;
5415 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5416 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5417 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5418 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5419 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5420 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5421 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5422 WINED3DTEXOPCAPS_LERP |
5423 WINED3DTEXOPCAPS_SUBTRACT;
5425 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5426 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5427 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5428 WINED3DTEXOPCAPS_MULTIPLYADD |
5429 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5430 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5431 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5433 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5434 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5436 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5437 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5440 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5441 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5442 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5444 if (TRACE_ON(d3d))
5446 TRACE("Checking support for fixup:\n");
5447 dump_color_fixup_desc(fixup);
5450 /* We only support identity conversions. */
5451 if (is_identity_fixup(fixup))
5453 TRACE("[OK]\n");
5454 return TRUE;
5457 TRACE("[FAILED]\n");
5458 return FALSE;
5461 const struct fragment_pipeline ffp_fragment_pipeline = {
5462 ffp_enable,
5463 ffp_fragment_get_caps,
5464 ffp_fragment_alloc,
5465 ffp_fragment_free,
5466 ffp_color_fixup_supported,
5467 ffp_fragmentstate_template,
5468 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5471 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5473 unsigned int i;
5474 for(i = 0; funcs[i]; i++);
5475 return i;
5478 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5479 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5480 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5483 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5484 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5485 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5486 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5489 void compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5490 const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5491 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5493 unsigned int i, type, handlers;
5494 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5495 const struct StateEntryTemplate *cur;
5496 BOOL set[STATE_HIGHEST + 1];
5498 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5500 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5501 StateTable[i].representative = 0;
5502 StateTable[i].apply = state_undefined;
5505 for(type = 0; type < 3; type++) {
5506 /* This switch decides the order in which the states are applied */
5507 switch(type) {
5508 case 0: cur = misc; break;
5509 case 1: cur = fragment->states; break;
5510 case 2: cur = vertex; break;
5511 default: cur = NULL; /* Stupid compiler */
5513 if(!cur) continue;
5515 /* GL extension filtering should not prevent multiple handlers being applied from different
5516 * pipeline parts
5518 memset(set, 0, sizeof(set));
5520 for(i = 0; cur[i].state; i++) {
5522 /* Only use the first matching state with the available extension from one template.
5523 * e.g.
5524 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5525 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5527 * if GL_XYZ_fancy is supported, ignore the 2nd line
5529 if(set[cur[i].state]) continue;
5530 /* Skip state lines depending on unsupported extensions */
5531 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5532 set[cur[i].state] = TRUE;
5533 /* In some cases having an extension means that nothing has to be
5534 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5535 * supported, the texture coordinate fixup can be ignored. If the
5536 * apply function is used, mark the state set(done above) to prevent
5537 * applying later lines, but do not record anything in the state
5538 * table
5540 if(!cur[i].content.apply) continue;
5542 handlers = num_handlers(multistate_funcs[cur[i].state]);
5543 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5544 switch(handlers) {
5545 case 0:
5546 StateTable[cur[i].state].apply = cur[i].content.apply;
5547 break;
5548 case 1:
5549 StateTable[cur[i].state].apply = multistate_apply_2;
5550 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5552 sizeof(**dev_multistate_funcs) * 2);
5553 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5554 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5555 break;
5556 case 2:
5557 StateTable[cur[i].state].apply = multistate_apply_3;
5558 HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
5559 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5561 sizeof(**dev_multistate_funcs) * 3);
5562 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5563 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5564 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5565 break;
5566 default:
5567 ERR("Unexpected amount of state handlers for state %u: %u\n",
5568 cur[i].state, handlers + 1);
5571 if(StateTable[cur[i].state].representative &&
5572 StateTable[cur[i].state].representative != cur[i].content.representative) {
5573 FIXME("State %u has different representatives in different pipeline parts\n",
5574 cur[i].state);
5576 StateTable[cur[i].state].representative = cur[i].content.representative;
5580 #undef GLINFO_LOCATION