2 * Direct3D state management
4 * Copyright 2002 Lionel Ulmer
5 * Copyright 2002-2005 Jason Edmeades
6 * Copyright 2003-2004 Raphael Junqueira
7 * Copyright 2004 Christian Costa
8 * Copyright 2005 Oliver Stieber
9 * Copyright 2006 Henri Verbeet
10 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
39 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42 /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43 * e.g as a parameter for drawing, or which are unimplemented in windows d3d
45 if(STATE_IS_RENDER(state)) {
46 WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47 TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
49 /* Shouldn't have an unknown type here */
50 FIXME("%d no direct mapping to gl of state with unknown type\n", state);
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55 /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56 * list without causing confusing terminal output. Deliberately no special debug name here
57 * because its undefined.
59 WARN("undefined state %d\n", state);
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63 WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
66 case WINED3DFILL_POINT:
67 glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
70 case WINED3DFILL_WIREFRAME:
71 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
74 case WINED3DFILL_SOLID:
75 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76 checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
79 FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
86 /* Lighting is not enabled if transformed vertices are drawn
87 * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
88 * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
89 * vertex declaration applying function calls this function for updating
92 if(isStateDirty(context, STATE_VDECL)) {
96 transformed = ((stateblock->wineD3DDevice->strided_streams.u.s.position.lpData != NULL ||
97 stateblock->wineD3DDevice->strided_streams.u.s.position.VBO != 0) &&
98 stateblock->wineD3DDevice->strided_streams.position_transformed) ? TRUE : FALSE;
100 if (stateblock->renderState[WINED3DRS_LIGHTING] && !transformed) {
101 glEnable(GL_LIGHTING);
102 checkGLcall("glEnable GL_LIGHTING");
104 glDisable(GL_LIGHTING);
105 checkGLcall("glDisable GL_LIGHTING");
109 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
110 /* No z test without depth stencil buffers */
111 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
112 TRACE("No Z buffer - disabling depth test\n");
113 glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
114 checkGLcall("glDisable GL_DEPTH_TEST");
118 switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
119 case WINED3DZB_FALSE:
120 glDisable(GL_DEPTH_TEST);
121 checkGLcall("glDisable GL_DEPTH_TEST");
124 glEnable(GL_DEPTH_TEST);
125 checkGLcall("glEnable GL_DEPTH_TEST");
128 glEnable(GL_DEPTH_TEST);
129 checkGLcall("glEnable GL_DEPTH_TEST");
130 FIXME("W buffer is not well handled\n");
133 FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
137 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
138 /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
141 switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
142 case WINED3DCULL_NONE:
143 glDisable(GL_CULL_FACE);
144 checkGLcall("glDisable GL_CULL_FACE");
147 glEnable(GL_CULL_FACE);
148 checkGLcall("glEnable GL_CULL_FACE");
149 glCullFace(GL_FRONT);
150 checkGLcall("glCullFace(GL_FRONT)");
152 case WINED3DCULL_CCW:
153 glEnable(GL_CULL_FACE);
154 checkGLcall("glEnable GL_CULL_FACE");
156 checkGLcall("glCullFace(GL_BACK)");
159 FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
163 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
164 switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
165 case WINED3DSHADE_FLAT:
166 glShadeModel(GL_FLAT);
167 checkGLcall("glShadeModel(GL_FLAT)");
169 case WINED3DSHADE_GOURAUD:
170 glShadeModel(GL_SMOOTH);
171 checkGLcall("glShadeModel(GL_SMOOTH)");
173 case WINED3DSHADE_PHONG:
174 FIXME("WINED3DSHADE_PHONG isn't supported\n");
177 FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
181 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
182 if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
184 checkGLcall("glEnable GL_DITHER");
186 glDisable(GL_DITHER);
187 checkGLcall("glDisable GL_DITHER");
191 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
192 /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
193 * this has to be merged with ZENABLE and ZFUNC
195 if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
197 checkGLcall("glDepthMask(1)");
200 checkGLcall("glDepthMask(0)");
204 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
205 int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
208 if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
209 static BOOL once = FALSE;
210 /* There are a few issues with this: First, our inability to
211 * select a proper Z depth, most of the time we're stuck with
212 * D24S8, even if the app selects D32 or D16. There seem to be
213 * some other precision problems which have to be debugged to
214 * make NOTEQUAL and EQUAL work properly
218 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
223 checkGLcall("glDepthFunc");
227 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
229 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
231 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
232 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
233 checkGLcall("glLightModel for MODEL_AMBIENT");
236 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
237 int srcBlend = GL_ZERO;
238 int dstBlend = GL_ZERO;
239 const StaticPixelFormatDesc *rtFormat;
240 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
242 /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
243 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE] ||
244 stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
245 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
246 const 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)) {
253 checkGLcall("glDisable GL_BLEND");
257 checkGLcall("glEnable GL_BLEND");
261 checkGLcall("glDisable GL_BLEND");
262 /* Nothing more to do - get out */
266 switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
267 case WINED3DBLEND_ZERO : dstBlend = GL_ZERO; break;
268 case WINED3DBLEND_ONE : dstBlend = GL_ONE; break;
269 case WINED3DBLEND_SRCCOLOR : dstBlend = GL_SRC_COLOR; break;
270 case WINED3DBLEND_INVSRCCOLOR : dstBlend = GL_ONE_MINUS_SRC_COLOR; break;
271 case WINED3DBLEND_SRCALPHA : dstBlend = GL_SRC_ALPHA; break;
272 case WINED3DBLEND_INVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA; break;
273 case WINED3DBLEND_DESTCOLOR : dstBlend = GL_DST_COLOR; break;
274 case WINED3DBLEND_INVDESTCOLOR : dstBlend = GL_ONE_MINUS_DST_COLOR; break;
276 /* To compensate the lack of format switching with backbuffer offscreen rendering,
277 * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
278 * if the render target doesn't support alpha blending. A nonexistent alpha channel
279 * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
281 case WINED3DBLEND_DESTALPHA :
282 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
283 dstBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
285 case WINED3DBLEND_INVDESTALPHA :
286 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
287 dstBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
290 case WINED3DBLEND_SRCALPHASAT :
291 dstBlend = GL_SRC_ALPHA_SATURATE;
292 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
295 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
296 * values which are still valid up to d3d9. They should not occur as dest blend values
298 case WINED3DBLEND_BOTHSRCALPHA : dstBlend = GL_SRC_ALPHA;
299 srcBlend = GL_SRC_ALPHA;
300 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
303 case WINED3DBLEND_BOTHINVSRCALPHA : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
304 srcBlend = GL_ONE_MINUS_SRC_ALPHA;
305 FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
308 case WINED3DBLEND_BLENDFACTOR : dstBlend = GL_CONSTANT_COLOR; break;
309 case WINED3DBLEND_INVBLENDFACTOR : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
311 FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
314 switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
315 case WINED3DBLEND_ZERO : srcBlend = GL_ZERO; break;
316 case WINED3DBLEND_ONE : srcBlend = GL_ONE; break;
317 case WINED3DBLEND_SRCCOLOR : srcBlend = GL_SRC_COLOR; break;
318 case WINED3DBLEND_INVSRCCOLOR : srcBlend = GL_ONE_MINUS_SRC_COLOR; break;
319 case WINED3DBLEND_SRCALPHA : srcBlend = GL_SRC_ALPHA; break;
320 case WINED3DBLEND_INVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA; break;
321 case WINED3DBLEND_DESTCOLOR : srcBlend = GL_DST_COLOR; break;
322 case WINED3DBLEND_INVDESTCOLOR : srcBlend = GL_ONE_MINUS_DST_COLOR; break;
323 case WINED3DBLEND_SRCALPHASAT : srcBlend = GL_SRC_ALPHA_SATURATE; break;
325 case WINED3DBLEND_DESTALPHA :
326 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
327 srcBlend = rtFormat->alphaMask ? GL_DST_ALPHA : GL_ONE;
329 case WINED3DBLEND_INVDESTALPHA :
330 rtFormat = getFormatDescEntry(target->resource.format, NULL, NULL);
331 srcBlend = rtFormat->alphaMask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
334 case WINED3DBLEND_BOTHSRCALPHA : srcBlend = GL_SRC_ALPHA;
335 dstBlend = GL_ONE_MINUS_SRC_ALPHA;
338 case WINED3DBLEND_BOTHINVSRCALPHA : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
339 dstBlend = GL_SRC_ALPHA;
342 case WINED3DBLEND_BLENDFACTOR : srcBlend = GL_CONSTANT_COLOR; break;
343 case WINED3DBLEND_INVBLENDFACTOR : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR; break;
345 FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
348 if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
349 stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
350 glEnable(GL_LINE_SMOOTH);
351 checkGLcall("glEnable(GL_LINE_SMOOTH)");
352 if(srcBlend != GL_SRC_ALPHA) {
353 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
355 if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
356 WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
359 glDisable(GL_LINE_SMOOTH);
360 checkGLcall("glDisable(GL_LINE_SMOOTH)");
363 /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
364 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
365 state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
368 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
369 int srcBlendAlpha = GL_ZERO;
370 int dstBlendAlpha = GL_ZERO;
372 /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
373 if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
374 WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
378 switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
379 case WINED3DBLEND_ZERO : dstBlendAlpha = GL_ZERO; break;
380 case WINED3DBLEND_ONE : dstBlendAlpha = GL_ONE; break;
381 case WINED3DBLEND_SRCCOLOR : dstBlendAlpha = GL_SRC_COLOR; break;
382 case WINED3DBLEND_INVSRCCOLOR : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
383 case WINED3DBLEND_SRCALPHA : dstBlendAlpha = GL_SRC_ALPHA; break;
384 case WINED3DBLEND_INVSRCALPHA : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
385 case WINED3DBLEND_DESTCOLOR : dstBlendAlpha = GL_DST_COLOR; break;
386 case WINED3DBLEND_INVDESTCOLOR : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
387 case WINED3DBLEND_DESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
388 case WINED3DBLEND_INVDESTALPHA : dstBlendAlpha = GL_DST_ALPHA; break;
389 case WINED3DBLEND_SRCALPHASAT :
390 dstBlend = GL_SRC_ALPHA_SATURATE;
391 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
393 /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
394 * values which are still valid up to d3d9. They should not occur as dest blend values
396 case WINED3DBLEND_BOTHSRCALPHA :
397 dstBlendAlpha = GL_SRC_ALPHA;
398 srcBlendAlpha = GL_SRC_ALPHA;
399 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
401 case WINED3DBLEND_BOTHINVSRCALPHA :
402 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
403 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
404 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
406 case WINED3DBLEND_BLENDFACTOR : dstBlendAlpha = GL_CONSTANT_COLOR; break;
407 case WINED3DBLEND_INVBLENDFACTOR : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
409 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
412 switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
413 case WINED3DBLEND_ZERO : srcBlendAlpha = GL_ZERO; break;
414 case WINED3DBLEND_ONE : srcBlendAlpha = GL_ONE; break;
415 case WINED3DBLEND_SRCCOLOR : srcBlendAlpha = GL_SRC_COLOR; break;
416 case WINED3DBLEND_INVSRCCOLOR : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR; break;
417 case WINED3DBLEND_SRCALPHA : srcBlendAlpha = GL_SRC_ALPHA; break;
418 case WINED3DBLEND_INVSRCALPHA : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; break;
419 case WINED3DBLEND_DESTCOLOR : srcBlendAlpha = GL_DST_COLOR; break;
420 case WINED3DBLEND_INVDESTCOLOR : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR; break;
421 case WINED3DBLEND_SRCALPHASAT : srcBlendAlpha = GL_SRC_ALPHA_SATURATE; break;
422 case WINED3DBLEND_DESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
423 case WINED3DBLEND_INVDESTALPHA : srcBlendAlpha = GL_DST_ALPHA; break;
424 case WINED3DBLEND_BOTHSRCALPHA :
425 srcBlendAlpha = GL_SRC_ALPHA;
426 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
428 case WINED3DBLEND_BOTHINVSRCALPHA :
429 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
430 dstBlendAlpha = GL_SRC_ALPHA;
432 case WINED3DBLEND_BLENDFACTOR : srcBlendAlpha = GL_CONSTANT_COLOR; break;
433 case WINED3DBLEND_INVBLENDFACTOR : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR; break;
435 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
438 GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
439 checkGLcall("glBlendFuncSeparateEXT");
441 TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
442 glBlendFunc(srcBlend, dstBlend);
443 checkGLcall("glBlendFunc");
446 /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
447 so it may need updating */
448 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
449 const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
450 StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
454 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
455 WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
458 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
461 TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
462 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
463 GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
464 checkGLcall("glBlendColor");
467 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
470 BOOL enable_ckey = FALSE;
472 /* 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");
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
518 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
519 glParm = GL_NOTEQUAL;
522 ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
523 glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
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))
537 /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
538 * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
539 * conditions I got sick of tracking down. The shader state handler disables all clip planes because
540 * of that - don't do anything here and keep them disabled
542 if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
543 static BOOL warned = FALSE;
545 FIXME("Clipping not supported with vertex shaders\n");
552 /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
553 * of already set values
556 /* If enabling / disabling all
557 * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
559 if (stateblock->renderState[WINED3DRS_CLIPPING]) {
560 enable = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
561 disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
562 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
563 glDisable(GL_DEPTH_CLAMP_NV);
564 checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
567 disable = 0xffffffff;
569 if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
570 glEnable(GL_DEPTH_CLAMP_NV);
571 checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
575 if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
576 if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
577 if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
578 if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
579 if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
580 if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
582 if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
583 if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
584 if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
585 if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
586 if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
587 if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
589 /** update clipping status */
591 stateblock->clip_status.ClipUnion = 0;
592 stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
594 stateblock->clip_status.ClipUnion = 0;
595 stateblock->clip_status.ClipIntersection = 0;
599 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
600 WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
603 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
604 int blendEquation = GL_FUNC_ADD;
605 int blendEquationAlpha = GL_FUNC_ADD;
607 /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
608 if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
609 WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
613 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
614 case WINED3DBLENDOP_ADD : blendEquation = GL_FUNC_ADD; break;
615 case WINED3DBLENDOP_SUBTRACT : blendEquation = GL_FUNC_SUBTRACT; break;
616 case WINED3DBLENDOP_REVSUBTRACT : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
617 case WINED3DBLENDOP_MIN : blendEquation = GL_MIN; break;
618 case WINED3DBLENDOP_MAX : blendEquation = GL_MAX; break;
620 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
623 switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
624 case WINED3DBLENDOP_ADD : blendEquationAlpha = GL_FUNC_ADD; break;
625 case WINED3DBLENDOP_SUBTRACT : blendEquationAlpha = GL_FUNC_SUBTRACT; break;
626 case WINED3DBLENDOP_REVSUBTRACT : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
627 case WINED3DBLENDOP_MIN : blendEquationAlpha = GL_MIN; break;
628 case WINED3DBLENDOP_MAX : blendEquationAlpha = GL_MAX; break;
630 FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
633 if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
634 TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
635 GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
636 checkGLcall("glBlendEquationSeparateEXT");
638 TRACE("glBlendEquation(%x)\n", blendEquation);
639 GL_EXTCALL(glBlendEquationEXT(blendEquation));
640 checkGLcall("glBlendEquation");
645 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
646 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
647 * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
648 * specular color. This is wrong:
649 * Separate specular color means the specular colour is maintained separately, whereas
650 * single color means it is merged in. However in both cases they are being used to
652 * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
653 * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
657 * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
658 * Instead, we need to setup the FinalCombiner properly.
660 * The default setup for the FinalCombiner is:
662 * <variable> <input> <mapping> <usage>
663 * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA
664 * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB
665 * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB
666 * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
667 * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
668 * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB
669 * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA
671 * That's pretty much fine as it is, except for variable B, which needs to take
672 * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
673 * whether WINED3DRS_SPECULARENABLE is enabled or not.
676 TRACE("Setting specular enable state and materials\n");
677 if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
678 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
679 checkGLcall("glMaterialfv");
681 if(stateblock->material.Power > GL_LIMITS(shininess)) {
682 /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
683 * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
684 * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
685 * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
686 * them, it should be safe to do so without major visual distortions.
688 WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
689 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
691 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
693 checkGLcall("glMaterialf(GL_SHININESS)");
695 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
696 glEnable(GL_COLOR_SUM_EXT);
698 TRACE("Specular colors cannot be enabled in this version of opengl\n");
700 checkGLcall("glEnable(GL_COLOR_SUM)");
702 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
703 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
704 checkGLcall("glFinalCombinerInputNV()");
707 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
709 /* for the case of enabled lighting: */
710 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
711 checkGLcall("glMaterialfv");
713 /* for the case of disabled lighting: */
714 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
715 glDisable(GL_COLOR_SUM_EXT);
717 TRACE("Specular colors cannot be disabled in this version of opengl\n");
719 checkGLcall("glDisable(GL_COLOR_SUM)");
721 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
722 GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
723 checkGLcall("glFinalCombinerInputNV()");
727 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
728 stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
729 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
730 stateblock->material.Ambient.b, stateblock->material.Ambient.a);
731 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
732 stateblock->material.Specular.b, stateblock->material.Specular.a);
733 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
734 stateblock->material.Emissive.b, stateblock->material.Emissive.a);
736 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
737 checkGLcall("glMaterialfv(GL_AMBIENT)");
738 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
739 checkGLcall("glMaterialfv(GL_DIFFUSE)");
740 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
741 checkGLcall("glMaterialfv(GL_EMISSION)");
744 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
747 /* Note the texture color applies to all textures whereas
748 * GL_TEXTURE_ENV_COLOR applies to active only
751 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
753 /* And now the default texture color as well */
754 for (i = 0; i < GL_LIMITS(texture_stages); i++) {
755 /* Note the WINED3DRS value applies to all textures, but GL has one
756 * per texture, so apply it now ready to be used!
758 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
759 checkGLcall("glActiveTextureARB");
761 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
762 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
767 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
768 glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
769 checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
770 GL_EXTCALL(glActiveStencilFaceEXT(face));
771 checkGLcall("glActiveStencilFaceEXT(...)");
772 glStencilFunc(func, ref, mask);
773 checkGLcall("glStencilFunc(...)");
774 glStencilOp(stencilFail, depthFail, stencilPass);
775 checkGLcall("glStencilOp(...)");
779 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
780 DWORD onesided_enable = FALSE;
781 DWORD twosided_enable = FALSE;
782 GLint func = GL_ALWAYS;
783 GLint func_ccw = GL_ALWAYS;
786 GLint stencilFail = GL_KEEP;
787 GLint depthFail = GL_KEEP;
788 GLint stencilPass = GL_KEEP;
789 GLint stencilFail_ccw = GL_KEEP;
790 GLint depthFail_ccw = GL_KEEP;
791 GLint stencilPass_ccw = GL_KEEP;
793 /* No stencil test without a stencil buffer */
794 if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
795 glDisable(GL_STENCIL_TEST);
796 checkGLcall("glDisable GL_STENCIL_TEST");
800 onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
801 twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
802 if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
804 if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
805 func_ccw = GL_ALWAYS;
806 ref = stateblock->renderState[WINED3DRS_STENCILREF];
807 mask = stateblock->renderState[WINED3DRS_STENCILMASK];
808 stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
809 depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
810 stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
811 stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
812 depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
813 stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
815 TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
816 "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
817 "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
818 onesided_enable, twosided_enable, ref, mask,
819 func, stencilFail, depthFail, stencilPass,
820 func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
822 if (twosided_enable && onesided_enable) {
823 glEnable(GL_STENCIL_TEST);
824 checkGLcall("glEnable GL_STENCIL_TEST");
826 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
827 /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
828 * which has an effect on the code below too. If we apply the front face
829 * afterwards, we are sure that the active stencil face is set to front,
830 * and other stencil functions which do not use two sided stencil do not have
833 renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
834 stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
835 renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
836 stencilFail, depthFail, stencilPass);
837 } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
838 GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
839 checkGLcall("glStencilFuncSeparateATI(...)");
840 GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
841 checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
842 GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
843 checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
845 ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
847 } else if(onesided_enable) {
848 if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
849 glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
850 checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
853 /* This code disables the ATI extension as well, since the standard stencil functions are equal
854 * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
856 glEnable(GL_STENCIL_TEST);
857 checkGLcall("glEnable GL_STENCIL_TEST");
858 glStencilFunc(func, ref, mask);
859 checkGLcall("glStencilFunc(...)");
860 glStencilOp(stencilFail, depthFail, stencilPass);
861 checkGLcall("glStencilOp(...)");
863 glDisable(GL_STENCIL_TEST);
864 checkGLcall("glDisable GL_STENCIL_TEST");
868 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
871 if(stateblock->wineD3DDevice->stencilBufferTarget) {
872 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
877 GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
878 checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
880 checkGLcall("glStencilMask");
881 GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
882 checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
886 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
889 if(stateblock->wineD3DDevice->stencilBufferTarget) {
890 mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
896 checkGLcall("glStencilMask");
899 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
900 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
902 /* Table fog on: Never use fog coords, and use per-fragment fog */
903 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
904 glHint(GL_FOG_HINT, GL_NICEST);
905 if(context->fog_coord) {
906 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
907 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
908 context->fog_coord = FALSE;
913 /* Otherwise use per-vertex fog in any case */
914 glHint(GL_FOG_HINT, GL_FASTEST);
916 if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
917 /* No fog at all, or transformed vertices: Use fog coord */
918 if(!context->fog_coord) {
919 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
920 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
921 context->fog_coord = TRUE;
924 /* Otherwise, use the fragment depth */
925 if(context->fog_coord) {
926 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
927 checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
928 context->fog_coord = FALSE;
933 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
934 float fogstart, fogend;
940 switch(context->fog_source) {
946 case FOGSOURCE_COORD:
952 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
953 fogstart = tmpvalue.f;
954 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
956 /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
957 if(fogstart == fogend) {
958 fogstart = -1.0 / 0.0;
964 /* This should not happen.context->fog_source is set in wined3d, not the app.
965 * Still this is needed to make the compiler happy
967 ERR("Unexpected fog coordinate source\n");
972 glFogf(GL_FOG_START, fogstart);
973 checkGLcall("glFogf(GL_FOG_START, fogstart)");
974 TRACE("Fog Start == %f\n", fogstart);
976 glFogf(GL_FOG_END, fogend);
977 checkGLcall("glFogf(GL_FOG_END, fogend)");
978 TRACE("Fog End == %f\n", fogend);
981 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
982 enum fogsource new_source;
984 if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
985 /* No fog? Disable it, and we're done :-) */
986 glDisableWINE(GL_FOG);
987 checkGLcall("glDisable GL_FOG");
993 * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
994 * It can use the Z value of the vertex, or the alpha component of the specular color.
995 * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
996 * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
997 * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
999 * FOGTABLEMODE != NONE:
1000 * The Z value is used, with the equation specified, no matter what vertex type.
1002 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
1003 * Per vertex fog is calculated using the specified fog equation and the parameters
1005 * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1006 * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1007 * Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1010 * Rules for vertex fog with shaders:
1012 * When mixing fixed function functionality with the programmable pipeline, D3D expects
1013 * the fog computation to happen during transformation while openGL expects it to happen
1014 * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1015 * the pixel shader while openGL always expects the pixel shader to handle the blending.
1016 * To solve this problem, WineD3D does:
1017 * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1019 * and 2) disables the fog computation (in either the fixed function or programmable
1020 * rasterizer) if using a vertex program.
1022 * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1023 * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1024 * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1025 * the specular color, a vertex shader counts as pretransformed geometry in this case.
1026 * There are some GL differences between specular fog coords and vertex shaders though.
1028 * With table fog the vertex shader fog coordinate is ignored.
1030 * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1034 /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1035 * the system will apply only pixel(=table) fog effects."
1037 if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1038 if(use_vs(stateblock)) {
1039 glFogi(GL_FOG_MODE, GL_LINEAR);
1040 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1041 new_source = FOGSOURCE_VS;
1043 switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1044 /* If processed vertices are used, fall through to the NONE case */
1045 case WINED3DFOG_EXP:
1046 if(!context->last_was_rhw) {
1047 glFogi(GL_FOG_MODE, GL_EXP);
1048 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1049 new_source = FOGSOURCE_FFP;
1054 case WINED3DFOG_EXP2:
1055 if(!context->last_was_rhw) {
1056 glFogi(GL_FOG_MODE, GL_EXP2);
1057 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1058 new_source = FOGSOURCE_FFP;
1063 case WINED3DFOG_LINEAR:
1064 if(!context->last_was_rhw) {
1065 glFogi(GL_FOG_MODE, GL_LINEAR);
1066 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1067 new_source = FOGSOURCE_FFP;
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 new_source = FOGSOURCE_COORD;
1078 glFogi(GL_FOG_MODE, GL_LINEAR);
1079 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1083 FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1084 new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1088 new_source = FOGSOURCE_FFP;
1090 switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1091 case WINED3DFOG_EXP:
1092 glFogi(GL_FOG_MODE, GL_EXP);
1093 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1096 case WINED3DFOG_EXP2:
1097 glFogi(GL_FOG_MODE, GL_EXP2);
1098 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1101 case WINED3DFOG_LINEAR:
1102 glFogi(GL_FOG_MODE, GL_LINEAR);
1103 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1106 case WINED3DFOG_NONE: /* Won't happen */
1108 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1112 glEnableWINE(GL_FOG);
1113 checkGLcall("glEnable GL_FOG");
1114 if(new_source != context->fog_source) {
1115 context->fog_source = new_source;
1116 state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1120 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1121 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1122 WARN("Range fog enabled, but not supported by this opengl implementation\n");
1126 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1127 if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1128 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1129 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1131 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1132 checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1136 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1138 D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1139 glFogfv(GL_FOG_COLOR, &col[0]);
1140 checkGLcall("glFog GL_FOG_COLOR");
1143 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1148 tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1149 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1150 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1153 /* TODO: Merge with primitive type + init_materials()!! */
1154 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1155 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1157 const WineDirect3DStridedData *diffuse = &device->strided_streams.u.s.diffuse;
1158 BOOL isDiffuseSupplied;
1160 /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1161 * The vertex declaration will call this function if the fixed function pipeline is used.
1164 if(isStateDirty(context, STATE_VDECL)) {
1168 isDiffuseSupplied = diffuse->lpData || diffuse->VBO;
1170 context->num_untracked_materials = 0;
1171 if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1172 TRACE("diff %d, amb %d, emis %d, spec %d\n",
1173 stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1174 stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1175 stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1176 stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1178 if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1179 if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1180 Parm = GL_AMBIENT_AND_DIFFUSE;
1184 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1185 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1186 context->num_untracked_materials++;
1188 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1189 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1190 context->num_untracked_materials++;
1192 } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1194 if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1195 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1196 context->num_untracked_materials++;
1198 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1199 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1200 context->num_untracked_materials++;
1202 } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1204 if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1205 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1206 context->num_untracked_materials++;
1208 } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1213 /* Nothing changed, return. */
1214 if (Parm == context->tracking_parm) return;
1217 glDisable(GL_COLOR_MATERIAL);
1218 checkGLcall("glDisable GL_COLOR_MATERIAL");
1220 glColorMaterial(GL_FRONT_AND_BACK, Parm);
1221 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1222 glEnable(GL_COLOR_MATERIAL);
1223 checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1226 /* Apparently calls to glMaterialfv are ignored for properties we're
1227 * tracking with glColorMaterial, so apply those here. */
1228 switch (context->tracking_parm) {
1229 case GL_AMBIENT_AND_DIFFUSE:
1230 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1231 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1232 checkGLcall("glMaterialfv");
1236 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1237 checkGLcall("glMaterialfv");
1241 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1242 checkGLcall("glMaterialfv");
1246 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1247 checkGLcall("glMaterialfv");
1251 /* Only change material color if specular is enabled, otherwise it is set to black */
1252 if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1253 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1254 checkGLcall("glMaterialfv");
1256 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1257 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1258 checkGLcall("glMaterialfv");
1263 context->tracking_parm = Parm;
1266 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1269 WINED3DLINEPATTERN lp;
1271 tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1273 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1275 if (tmppattern.lp.wRepeatFactor) {
1276 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1277 checkGLcall("glLineStipple(repeat, linepattern)");
1278 glEnable(GL_LINE_STIPPLE);
1279 checkGLcall("glEnable(GL_LINE_STIPPLE);");
1281 glDisable(GL_LINE_STIPPLE);
1282 checkGLcall("glDisable(GL_LINE_STIPPLE);");
1286 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1292 if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1293 tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1294 TRACE("ZBias value %f\n", tmpvalue.f);
1295 glPolygonOffset(0, -tmpvalue.f);
1296 checkGLcall("glPolygonOffset(0, -Value)");
1297 glEnable(GL_POLYGON_OFFSET_FILL);
1298 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1299 glEnable(GL_POLYGON_OFFSET_LINE);
1300 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1301 glEnable(GL_POLYGON_OFFSET_POINT);
1302 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1304 glDisable(GL_POLYGON_OFFSET_FILL);
1305 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1306 glDisable(GL_POLYGON_OFFSET_LINE);
1307 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1308 glDisable(GL_POLYGON_OFFSET_POINT);
1309 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1314 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1315 if(isStateDirty(context, STATE_VDECL)) {
1318 /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1319 * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1320 * by zero and is not properly defined in opengl, so avoid it
1322 if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS] && (
1323 stateblock->wineD3DDevice->strided_streams.u.s.normal.lpData ||
1324 stateblock->wineD3DDevice->strided_streams.u.s.normal.VBO)) {
1325 glEnable(GL_NORMALIZE);
1326 checkGLcall("glEnable(GL_NORMALIZE);");
1328 glDisable(GL_NORMALIZE);
1329 checkGLcall("glDisable(GL_NORMALIZE);");
1333 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1339 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1340 if(tmpvalue.f != 1.0) {
1341 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1343 tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1344 if(tmpvalue.f != 64.0) {
1345 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1350 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1356 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1357 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1359 /* Max point size trumps min point size */
1364 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1365 checkGLcall("glPointParameterfEXT(...)");
1366 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1367 checkGLcall("glPointParameterfEXT(...)");
1370 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1376 min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1377 max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1379 /* Max point size trumps min point size */
1384 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1385 checkGLcall("glPointParameterfARB(...)");
1386 GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1387 checkGLcall("glPointParameterfARB(...)");
1390 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1391 /* TODO: Group this with the viewport */
1393 * POINTSCALEENABLE controls how point size value is treated. If set to
1394 * true, the point size is scaled with respect to height of viewport.
1395 * When set to false point size is in pixels.
1398 /* Default values */
1399 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1403 } pointSize, A, B, C;
1405 pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1406 A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1407 B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1408 C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1410 if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1411 GLfloat scaleFactor;
1412 float h = stateblock->viewport.Height;
1414 if(pointSize.f < GL_LIMITS(pointsizemin)) {
1416 * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1417 * 0.0f. This means that OpenGL will clamp really small point sizes to the
1418 * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1419 * are less than 1.0f. scale_factor = 1.0f / point_size.
1421 scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1422 /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1423 * is 1.0, but then accepts points below that and draws too small points
1425 pointSize.f = GL_LIMITS(pointsizemin);
1426 } else if(pointSize.f > GL_LIMITS(pointsize)) {
1427 /* gl already scales the input to glPointSize,
1428 * d3d scales the result after the point size scale.
1429 * If the point size is bigger than the max size, use the
1430 * scaling to scale it bigger, and set the gl point size to max
1432 scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1433 TRACE("scale: %f\n", scaleFactor);
1434 pointSize.f = GL_LIMITS(pointsize);
1438 scaleFactor = pow(h * scaleFactor, 2);
1440 att[0] = A.f / scaleFactor;
1441 att[1] = B.f / scaleFactor;
1442 att[2] = C.f / scaleFactor;
1445 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1446 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1447 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1449 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1450 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1451 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1452 } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1453 WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1456 glPointSize(pointSize.f);
1457 checkGLcall("glPointSize(...);");
1460 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1461 DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1463 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1464 Value & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
1465 Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1466 Value & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
1467 Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1468 glColorMask(Value & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1469 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1470 Value & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1471 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1472 checkGLcall("glColorMask(...)");
1474 /* depends on WINED3DRS_COLORWRITEENABLE. */
1475 if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1476 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1477 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1478 ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1479 stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1480 stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1481 stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1485 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1486 if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1487 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1488 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1490 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1491 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1495 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1496 if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1497 TRACE("Last Pixel Drawing Enabled\n");
1501 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1504 TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1509 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1510 /* TODO: NV_POINT_SPRITE */
1511 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1512 TRACE("Point sprites not supported\n");
1516 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1517 if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1518 glEnable(GL_POINT_SPRITE_ARB);
1519 checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1521 glDisable(GL_POINT_SPRITE_ARB);
1522 checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1526 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1528 http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1529 http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1530 Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1531 http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1533 so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1536 if(stateblock->renderState[WINED3DRS_WRAP0] ||
1537 stateblock->renderState[WINED3DRS_WRAP1] ||
1538 stateblock->renderState[WINED3DRS_WRAP2] ||
1539 stateblock->renderState[WINED3DRS_WRAP3] ||
1540 stateblock->renderState[WINED3DRS_WRAP4] ||
1541 stateblock->renderState[WINED3DRS_WRAP5] ||
1542 stateblock->renderState[WINED3DRS_WRAP6] ||
1543 stateblock->renderState[WINED3DRS_WRAP7] ||
1544 stateblock->renderState[WINED3DRS_WRAP8] ||
1545 stateblock->renderState[WINED3DRS_WRAP9] ||
1546 stateblock->renderState[WINED3DRS_WRAP10] ||
1547 stateblock->renderState[WINED3DRS_WRAP11] ||
1548 stateblock->renderState[WINED3DRS_WRAP12] ||
1549 stateblock->renderState[WINED3DRS_WRAP13] ||
1550 stateblock->renderState[WINED3DRS_WRAP14] ||
1551 stateblock->renderState[WINED3DRS_WRAP15] ) {
1552 FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1556 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1557 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1558 WARN("Multisample antialiasing not supported by gl\n");
1562 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1563 if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1564 glEnable(GL_MULTISAMPLE_ARB);
1565 checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1567 glDisable(GL_MULTISAMPLE_ARB);
1568 checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1572 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1573 if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1574 glEnable(GL_SCISSOR_TEST);
1575 checkGLcall("glEnable(GL_SCISSOR_TEST)");
1577 glDisable(GL_SCISSOR_TEST);
1578 checkGLcall("glDisable(GL_SCISSOR_TEST)");
1582 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1588 if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1589 stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1590 tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1591 glEnable(GL_POLYGON_OFFSET_FILL);
1592 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1593 glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1594 checkGLcall("glPolygonOffset(...)");
1596 glDisable(GL_POLYGON_OFFSET_FILL);
1597 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1601 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1602 if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1603 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1604 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1606 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1607 checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1611 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1613 if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1614 FIXME(" Stippled Alpha not supported yet.\n");
1617 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1619 if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1620 FIXME(" Antialias not supported yet.\n");
1623 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1625 if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1626 FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1629 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1631 if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1632 FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1635 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1643 if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1645 static BOOL displayed = FALSE;
1647 tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1649 FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1655 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1657 if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1658 FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1661 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1663 if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1664 FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1667 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1669 if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1670 FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1673 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1674 if(stateblock->renderState[WINED3DRS_WRAPU]) {
1675 FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1679 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1680 if(stateblock->renderState[WINED3DRS_WRAPV]) {
1681 FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1685 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1686 if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1687 FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1691 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1692 if(stateblock->renderState[WINED3DRS_ROP2]) {
1693 FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1697 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1698 if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1699 FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1703 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1704 if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1705 FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1709 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1710 if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1711 FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1715 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1716 if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1717 FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1721 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1722 if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1723 FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1727 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1728 if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1729 FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1733 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1734 if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1735 FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1739 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1740 if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1741 FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1745 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1746 if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1747 FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1751 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1752 if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1753 FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1757 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1758 if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1759 FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1763 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1764 #if defined (GL_VERSION_1_3)
1765 # define useext(A) A
1766 #elif defined (GL_EXT_texture_env_combine)
1767 # define useext(A) A##_EXT
1768 #elif defined (GL_ARB_texture_env_combine)
1769 # define useext(A) A##_ARB
1772 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1773 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1774 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1775 * flag specifies the complement of the input should be used. */
1776 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1777 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1779 /* Calculate the operand */
1781 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1782 else *operand = GL_ONE_MINUS_SRC_COLOR;
1784 if (from_alpha) *operand = GL_SRC_ALPHA;
1785 else *operand = GL_SRC_COLOR;
1788 /* Calculate the source */
1789 switch (arg & WINED3DTA_SELECTMASK) {
1790 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1791 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1792 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1793 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1794 case WINED3DTA_SPECULAR:
1796 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1797 * 'Secondary color' and isn't supported until base GL supports it
1798 * There is no concept of temp registers as far as I can tell
1800 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1801 *source = GL_TEXTURE;
1804 FIXME("Unrecognized texture arg %#x\n", arg);
1805 *source = GL_TEXTURE;
1810 /* Setup the texture operations texture stage states */
1811 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1813 GLenum src1, src2, src3;
1814 GLenum opr1, opr2, opr3;
1816 GLenum src0_target, src1_target, src2_target;
1817 GLenum opr0_target, opr1_target, opr2_target;
1819 GLenum opr=0, invopr, src3_target, opr3_target;
1820 BOOL Handled = FALSE;
1821 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1822 IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1824 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1826 /* This is called by a state handler which has the gl lock held and a context for the thread */
1828 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1829 the form (a1 <operation> a2). However, some of the more complex operations
1830 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1831 in a third parameter called a0. Therefore these are operations of the form
1832 a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1834 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1835 functions below, expect their syntax to differ slightly to those listed in the
1836 manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1837 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1840 comb_target = useext(GL_COMBINE_ALPHA);
1841 src0_target = useext(GL_SOURCE0_ALPHA);
1842 src1_target = useext(GL_SOURCE1_ALPHA);
1843 src2_target = useext(GL_SOURCE2_ALPHA);
1844 opr0_target = useext(GL_OPERAND0_ALPHA);
1845 opr1_target = useext(GL_OPERAND1_ALPHA);
1846 opr2_target = useext(GL_OPERAND2_ALPHA);
1847 scal_target = GL_ALPHA_SCALE;
1850 comb_target = useext(GL_COMBINE_RGB);
1851 src0_target = useext(GL_SOURCE0_RGB);
1852 src1_target = useext(GL_SOURCE1_RGB);
1853 src2_target = useext(GL_SOURCE2_RGB);
1854 opr0_target = useext(GL_OPERAND0_RGB);
1855 opr1_target = useext(GL_OPERAND1_RGB);
1856 opr2_target = useext(GL_OPERAND2_RGB);
1857 scal_target = useext(GL_RGB_SCALE);
1860 /* If a texture stage references an invalid texture unit the stage just
1861 * passes through the result from the previous stage */
1862 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1863 arg1 = WINED3DTA_CURRENT;
1864 op = WINED3DTOP_SELECTARG1;
1867 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1868 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1870 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1872 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1873 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1875 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1877 Handled = TRUE; /* Assume will be handled */
1879 /* Other texture operations require special extensions: */
1880 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1883 invopr = GL_ONE_MINUS_SRC_ALPHA;
1884 src3_target = GL_SOURCE3_ALPHA_NV;
1885 opr3_target = GL_OPERAND3_ALPHA_NV;
1888 invopr = GL_ONE_MINUS_SRC_COLOR;
1889 src3_target = GL_SOURCE3_RGB_NV;
1890 opr3_target = GL_OPERAND3_RGB_NV;
1893 case WINED3DTOP_DISABLE: /* Only for alpha */
1894 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1895 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1896 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1897 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1898 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1899 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1900 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1901 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1902 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1903 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1904 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1905 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1906 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1907 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1908 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1909 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1910 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1911 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1913 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1914 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1915 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1916 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1917 if (op == WINED3DTOP_SELECTARG1) {
1918 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1919 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1920 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1921 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1923 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1924 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1925 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1926 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1928 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1929 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1930 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1931 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1932 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1933 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1934 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1935 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1936 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1937 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1938 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1939 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1942 case WINED3DTOP_MODULATE:
1943 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1944 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1945 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1946 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1947 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1948 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1949 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1950 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1951 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1952 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1953 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1954 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1955 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1956 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1957 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1958 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1959 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1960 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1961 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1962 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1964 case WINED3DTOP_MODULATE2X:
1965 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1966 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1967 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1968 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1969 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1970 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1971 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1972 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1973 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1974 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1975 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1976 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1977 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1978 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1979 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1980 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1981 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1982 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1983 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1984 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1986 case WINED3DTOP_MODULATE4X:
1987 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1988 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1989 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1990 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1991 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1992 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1993 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1994 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1995 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1996 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1997 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1998 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1999 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2000 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2001 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2002 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2003 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2004 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2005 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2006 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2009 case WINED3DTOP_ADD:
2010 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2011 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2012 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2013 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2014 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2015 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2016 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2017 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2018 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2019 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2020 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2021 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2022 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2023 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2024 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2025 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2026 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2027 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2028 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2029 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2032 case WINED3DTOP_ADDSIGNED:
2033 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2034 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
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, GL_ZERO);
2040 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2041 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2042 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2043 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2044 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2045 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
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, invopr);
2050 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2051 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2052 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2055 case WINED3DTOP_ADDSIGNED2X:
2056 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2057 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
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, 2);
2075 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2078 case WINED3DTOP_ADDSMOOTH:
2079 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2080 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
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, src1);
2094 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2096 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2097 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2098 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2099 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2101 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2102 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2103 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2104 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2107 case WINED3DTOP_BLENDDIFFUSEALPHA:
2108 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2109 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2110 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2111 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2112 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2113 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2114 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2115 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2116 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2117 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2118 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2119 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2120 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2121 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2122 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2123 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2124 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2125 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2126 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2127 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2129 case WINED3DTOP_BLENDTEXTUREALPHA:
2130 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2131 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2132 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2133 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2134 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2135 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2136 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2137 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2138 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2139 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2140 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2141 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2142 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2143 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2144 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2145 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2146 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2147 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2148 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2149 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2151 case WINED3DTOP_BLENDFACTORALPHA:
2152 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2153 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2154 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2155 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2156 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2157 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2158 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2159 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2160 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2161 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2162 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2163 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2164 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2165 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2166 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2167 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2168 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2169 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2170 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2171 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2173 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2174 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2175 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2176 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2177 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2178 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2179 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2180 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2181 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2182 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2183 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2184 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2185 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2186 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2187 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2188 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2189 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2190 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2191 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2192 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2193 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2195 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2196 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2197 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2198 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
2199 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2200 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2201 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
2202 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2203 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2204 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2205 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2206 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
2207 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2208 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2209 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
2210 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2211 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2213 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2214 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2216 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2217 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2218 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2219 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2221 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2222 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2223 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2224 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2225 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2226 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2227 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2228 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2229 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2230 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2231 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2232 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2233 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2235 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2236 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2238 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2239 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2240 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2241 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2242 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2243 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2244 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2245 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2247 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2248 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2249 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2250 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2251 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2252 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2253 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2254 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2255 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2256 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2257 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2258 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2259 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2260 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2261 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2262 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2263 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2265 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2266 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2267 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2268 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2270 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2271 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2272 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2273 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2275 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2276 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2277 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2278 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2279 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2281 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2282 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2283 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2284 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2286 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2287 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2288 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2289 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2290 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2291 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2292 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2293 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2295 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2296 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2298 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2299 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2300 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2301 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2302 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2303 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2304 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2305 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2307 case WINED3DTOP_MULTIPLYADD:
2308 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2309 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2310 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2311 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2312 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2313 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2314 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2315 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2316 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2317 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2318 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2319 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2320 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2321 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2322 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2323 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2324 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2325 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2326 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2327 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2330 case WINED3DTOP_BUMPENVMAP:
2334 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2335 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2341 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2342 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2346 } /* GL_NV_texture_env_combine4 */
2348 Handled = TRUE; /* Again, assume handled */
2350 case WINED3DTOP_DISABLE: /* Only for alpha */
2351 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2352 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2353 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2354 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2355 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2356 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2357 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2358 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2360 case WINED3DTOP_SELECTARG1:
2361 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2362 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2363 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2364 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2365 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2366 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2367 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2368 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2370 case WINED3DTOP_SELECTARG2:
2371 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2372 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2373 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2374 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2375 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2376 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2377 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2378 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2380 case WINED3DTOP_MODULATE:
2381 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2382 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2383 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2384 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2385 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2386 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2387 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2388 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2389 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2390 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2391 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2392 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2394 case WINED3DTOP_MODULATE2X:
2395 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2396 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2397 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2398 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2399 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2400 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2401 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2402 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2403 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2404 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2405 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2406 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2408 case WINED3DTOP_MODULATE4X:
2409 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2410 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2411 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2412 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2413 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2414 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2415 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2416 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2417 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2418 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2419 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2420 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2422 case WINED3DTOP_ADD:
2423 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2424 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2425 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2426 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2427 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2428 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2429 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2430 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2431 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2432 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2433 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2434 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2436 case WINED3DTOP_ADDSIGNED:
2437 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2438 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2439 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2440 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2441 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2442 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2443 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2444 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2445 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2446 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2447 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2448 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2450 case WINED3DTOP_ADDSIGNED2X:
2451 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2452 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2453 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2454 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2455 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2456 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2457 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2458 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2459 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2460 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2461 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2462 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2464 case WINED3DTOP_SUBTRACT:
2465 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2466 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2467 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2468 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2469 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2470 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2471 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2472 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2473 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2474 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2475 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2476 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2477 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2479 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2483 case WINED3DTOP_BLENDDIFFUSEALPHA:
2484 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2485 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2486 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2487 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2488 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2489 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2490 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2491 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2492 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2493 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2494 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2495 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2496 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2497 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2498 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2499 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2501 case WINED3DTOP_BLENDTEXTUREALPHA:
2502 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2503 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2504 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2505 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2506 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2507 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2508 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2509 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2510 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2511 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2512 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2513 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2514 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2515 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2516 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2517 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2519 case WINED3DTOP_BLENDFACTORALPHA:
2520 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2521 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2522 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2523 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2524 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2525 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2526 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2527 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2528 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2529 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2530 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2531 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2532 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2533 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2534 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2535 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2537 case WINED3DTOP_BLENDCURRENTALPHA:
2538 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2539 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2540 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2541 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2542 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2543 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2544 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2545 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2546 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2547 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2548 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2549 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2550 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2551 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2552 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2553 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2555 case WINED3DTOP_DOTPRODUCT3:
2556 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2557 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2558 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2559 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2560 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2561 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2563 FIXME("This version of opengl does not support GL_DOT3\n");
2565 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2566 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2567 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2568 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2569 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2570 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2571 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2572 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2573 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2574 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2576 case WINED3DTOP_LERP:
2577 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2578 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2579 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2580 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2581 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2582 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2583 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2584 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2585 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2586 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2587 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2588 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2589 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2590 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2591 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2592 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2594 case WINED3DTOP_ADDSMOOTH:
2595 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2596 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2597 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2598 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2599 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2601 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2602 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2603 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2604 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2606 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2607 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2608 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2609 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2610 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2611 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2612 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2613 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2614 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2615 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2616 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2617 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2621 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2622 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2623 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2624 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2625 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2626 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2627 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2628 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2629 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2630 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2631 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2632 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2633 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2634 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2635 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2636 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2637 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2638 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2642 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2643 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2644 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2645 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2646 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2647 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2649 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2650 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2651 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2652 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2654 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2655 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2656 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2657 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2658 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2659 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2660 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2661 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2662 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2663 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2664 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2665 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2669 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2670 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2671 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2672 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2673 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2674 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2675 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2676 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2677 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2678 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2680 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2681 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2682 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2683 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2685 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2686 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2687 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2688 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2689 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2690 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2691 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2692 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2696 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2697 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2698 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2699 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2700 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2701 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2703 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2704 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2705 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2706 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2708 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2709 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2710 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2711 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2712 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2713 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2714 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2715 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2716 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2717 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2718 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2719 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2723 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2724 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2725 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2726 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2727 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2728 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2730 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2731 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2732 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2733 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2735 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2736 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2737 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2738 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2740 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2741 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2742 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2743 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2745 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2746 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2747 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2748 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2749 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2750 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2751 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2752 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2756 case WINED3DTOP_MULTIPLYADD:
2757 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2758 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2759 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2760 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2761 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2762 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2763 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2764 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2765 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2766 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2767 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2768 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2769 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2770 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2771 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2772 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2773 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2777 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2778 case WINED3DTOP_BUMPENVMAP:
2779 if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2780 /* Technically texture shader support without register combiners is possible, but not expected to occur
2781 * on real world cards, so for now a fixme should be enough
2783 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2790 BOOL combineOK = TRUE;
2791 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2795 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2797 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2800 /* Note: If COMBINE4 in effect can't go back to combine! */
2802 case WINED3DTOP_ADDSMOOTH:
2803 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2804 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2805 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2806 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2807 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2808 case WINED3DTOP_MULTIPLYADD:
2809 /* Ignore those implemented in both cases */
2811 case WINED3DTOP_SELECTARG1:
2812 case WINED3DTOP_SELECTARG2:
2817 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2824 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2825 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2831 /* After all the extensions, if still unhandled, report fixme */
2832 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2836 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2837 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2838 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2839 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2841 TRACE("Setting color op for stage %d\n", stage);
2843 /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2844 if (use_ps(stateblock)) return;
2846 if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2848 if (mapped_stage != -1) {
2849 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2850 FIXME("Attempt to enable unsupported stage!\n");
2853 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2854 checkGLcall("glActiveTextureARB");
2857 if(stage >= stateblock->lowest_disabled_stage) {
2858 TRACE("Stage disabled\n");
2859 if (mapped_stage != -1) {
2860 /* Disable everything here */
2861 glDisable(GL_TEXTURE_2D);
2862 checkGLcall("glDisable(GL_TEXTURE_2D)");
2863 glDisable(GL_TEXTURE_3D);
2864 checkGLcall("glDisable(GL_TEXTURE_3D)");
2865 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2866 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2867 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2869 if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2870 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2871 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2878 /* The sampler will also activate the correct texture dimensions, so no need to do it here
2879 * if the sampler for this stage is dirty
2881 if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2882 if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2885 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2886 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2887 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2888 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2889 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2892 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2893 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2894 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2895 BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2896 DWORD op, arg1, arg2, arg0;
2898 TRACE("Setting alpha op for stage %d\n", stage);
2899 /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2900 if (mapped_stage != -1) {
2901 if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2902 FIXME("Attempt to enable unsupported stage!\n");
2905 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2906 checkGLcall("glActiveTextureARB");
2909 op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2910 arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2911 arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2912 arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2914 if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2916 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2918 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2920 IWineD3DSurfaceImpl *surf;
2922 surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2924 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT
2925 && getFormatDescEntry(surf->resource.format, NULL, NULL)->alphaMask == 0x00000000)
2927 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2928 * properly. On the other hand applications can still use texture combiners apparently. This code
2929 * takes care that apps cannot remove the texture's alpha channel entirely.
2931 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2932 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2933 * and alpha component of diffuse color to draw things like translucent text and perform other
2936 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2937 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2938 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2939 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2940 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2941 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2942 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2943 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2944 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2947 * What to do with multitexturing? So far no app has been found that uses color keying with
2949 if (op == WINED3DTOP_DISABLE)
2951 arg1 = WINED3DTA_TEXTURE;
2952 op = WINED3DTOP_SELECTARG1;
2954 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
2956 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2958 arg2 = WINED3DTA_TEXTURE;
2959 op = WINED3DTOP_MODULATE;
2961 else arg1 = WINED3DTA_TEXTURE;
2963 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
2965 if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2967 arg1 = WINED3DTA_TEXTURE;
2968 op = WINED3DTOP_MODULATE;
2970 else arg2 = WINED3DTA_TEXTURE;
2976 /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
2977 * this if block here, and the other code(color keying, texture unit selection) are the same
2979 TRACE("Setting alpha op for stage %d\n", stage);
2980 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2981 set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2982 op, arg1, arg2, arg0,
2984 stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
2986 set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2987 op, arg1, arg2, arg0);
2991 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2992 DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2993 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2997 /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2998 if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3000 TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3004 if (mapped_stage == -1) return;
3006 if(mapped_stage >= GL_LIMITS(textures)) {
3009 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3010 checkGLcall("glActiveTextureARB");
3011 generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3012 coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3014 set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3015 stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS],
3017 context->last_was_rhw,
3018 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwStride ?
3019 stateblock->wineD3DDevice->strided_streams.u.s.texCoords[coordIdx].dwType:
3020 WINED3DDECLTYPE_UNUSED,
3021 stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3023 /* The sampler applying function calls us if this changes */
3024 if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3027 FIXME("Non-power2 texture being used with generated texture coords\n");
3029 TRACE("Non power two matrix multiply fixup\n");
3030 glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3034 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3037 for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3038 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3039 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3043 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd, GLint *curVBO)
3045 const UINT *offset = stateblock->streamOffset;
3046 unsigned int mapped_stage = 0;
3047 unsigned int textureNo = 0;
3049 for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3050 int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3052 mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3053 if (mapped_stage == -1) continue;
3055 if (coordIdx < MAX_TEXTURES && (sd->u.s.texCoords[coordIdx].lpData || sd->u.s.texCoords[coordIdx].VBO)) {
3056 TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3057 textureNo, mapped_stage, coordIdx, sd->u.s.texCoords[coordIdx].lpData);
3059 if (*curVBO != sd->u.s.texCoords[coordIdx].VBO) {
3060 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.texCoords[coordIdx].VBO));
3061 checkGLcall("glBindBufferARB");
3062 *curVBO = sd->u.s.texCoords[coordIdx].VBO;
3065 GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3066 checkGLcall("glClientActiveTextureARB");
3068 /* The coords to supply depend completely on the fvf / vertex shader */
3070 WINED3D_ATR_FORMAT(sd->u.s.texCoords[coordIdx].dwType),
3071 WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
3072 sd->u.s.texCoords[coordIdx].dwStride,
3073 sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
3074 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3076 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3079 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3080 /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3081 for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3082 GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3086 checkGLcall("loadTexCoords");
3089 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3090 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3091 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3092 static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3093 static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3094 static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3095 static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3097 if (mapped_stage == -1) {
3098 TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3102 if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3105 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3106 checkGLcall("glActiveTextureARB");
3108 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3110 * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3111 * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3112 * means use the vertex position (camera-space) as the input texture coordinates
3113 * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3114 * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3115 * to the TEXCOORDINDEX value
3119 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3121 switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) {
3122 case WINED3DTSS_TCI_PASSTHRU:
3123 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3124 glDisable(GL_TEXTURE_GEN_S);
3125 glDisable(GL_TEXTURE_GEN_T);
3126 glDisable(GL_TEXTURE_GEN_R);
3127 glDisable(GL_TEXTURE_GEN_Q);
3128 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R,Q)");
3131 case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3132 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3133 * as the input texture coordinates for this stage's texture transformation. This
3134 * equates roughly to EYE_LINEAR
3137 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3139 glMatrixMode(GL_MODELVIEW);
3142 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3143 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3144 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3145 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3148 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3149 glEnable(GL_TEXTURE_GEN_S);
3150 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3151 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3152 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3153 glEnable(GL_TEXTURE_GEN_T);
3154 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3155 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3156 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3157 glEnable(GL_TEXTURE_GEN_R);
3158 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3159 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3160 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3164 case WINED3DTSS_TCI_CAMERASPACENORMAL:
3166 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3167 TRACE("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane\n");
3169 glMatrixMode(GL_MODELVIEW);
3172 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3173 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3174 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3175 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3178 glEnable(GL_TEXTURE_GEN_S);
3179 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3180 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3181 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3182 glEnable(GL_TEXTURE_GEN_T);
3183 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3184 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3185 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3186 glEnable(GL_TEXTURE_GEN_R);
3187 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3188 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3189 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3194 case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3196 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3197 TRACE("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane\n");
3199 glMatrixMode(GL_MODELVIEW);
3202 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3203 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3204 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3205 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3208 glEnable(GL_TEXTURE_GEN_S);
3209 checkGLcall("glEnable(GL_TEXTURE_GEN_S)");
3210 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3211 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3212 glEnable(GL_TEXTURE_GEN_T);
3213 checkGLcall("glEnable(GL_TEXTURE_GEN_T)");
3214 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3215 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3216 glEnable(GL_TEXTURE_GEN_R);
3217 checkGLcall("glEnable(GL_TEXTURE_GEN_R)");
3218 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3219 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3224 /* Unhandled types: */
3227 /* ? disable GL_TEXTURE_GEN_n ? */
3228 glDisable(GL_TEXTURE_GEN_S);
3229 glDisable(GL_TEXTURE_GEN_T);
3230 glDisable(GL_TEXTURE_GEN_R);
3231 glDisable(GL_TEXTURE_GEN_Q);
3232 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %x\n", stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3236 /* Update the texture matrix */
3237 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3238 transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3241 if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3242 /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3243 * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3244 * and do all the things linked to it
3245 * TODO: Tidy that up to reload only the arrays of the changed unit
3247 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3249 unloadTexCoords(stateblock);
3250 loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3254 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3255 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3257 /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3258 * has an update pending
3260 if(isStateDirty(context, STATE_VDECL) ||
3261 isStateDirty(context, STATE_PIXELSHADER)) {
3265 device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock));
3268 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3269 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3271 if(stateblock->pixelShader && stage != 0 &&
3272 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3273 /* The pixel shader has to know the luminance scale. Do a constants update if it
3274 * isn't scheduled anyway
3276 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3277 !isStateDirty(context, STATE_PIXELSHADER)) {
3278 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3283 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3284 BOOL texIsPow2 = FALSE;
3285 DWORD sampler = state - STATE_SAMPLER(0);
3286 IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3288 if(!texture) return;
3289 /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3290 * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3291 * scaling is reapplied or removed, the texture matrix has to be reapplied
3293 * The mapped stage is already active because the sampler() function below, which is part of the
3296 if(sampler < MAX_TEXTURES) {
3297 UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
3299 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3301 if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
3302 ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
3306 else if (texture_dimensions == GL_TEXTURE_CUBE_MAP_ARB)
3308 if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
3313 if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3315 if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3316 else context->lastWasPow2Texture &= ~(1 << sampler);
3317 transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3322 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3323 DWORD sampler = state - STATE_SAMPLER(0);
3324 DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3330 TRACE("Sampler: %d\n", sampler);
3331 /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3332 * only has to bind textures and set the per texture states
3335 if (mapped_stage == -1) {
3336 TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3340 if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3343 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3344 checkGLcall("glActiveTextureARB");
3346 if(stateblock->textures[sampler]) {
3347 BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3348 IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3349 tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3350 IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3351 IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3353 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3354 tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3355 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3356 GL_TEXTURE_LOD_BIAS_EXT,
3358 checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3361 if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3363 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3364 /* If color keying is enabled update the alpha test, it depends on the existence
3365 * of a color key in stage 0
3367 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3370 } else if(mapped_stage < GL_LIMITS(textures)) {
3371 if(sampler < stateblock->lowest_disabled_stage) {
3372 /* TODO: What should I do with pixel shaders here ??? */
3373 if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3374 /* If color keying is enabled update the alpha test, it depends on the existence
3375 * of a color key in stage 0
3377 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3379 } /* Otherwise tex_colorop disables the stage */
3380 glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3381 checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3385 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3386 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3387 BOOL use_pshader = use_ps(stateblock);
3388 BOOL use_vshader = use_vs(stateblock);
3392 if(!context->last_was_pshader) {
3393 /* Former draw without a pixel shader, some samplers
3394 * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3395 * make sure to enable them
3397 for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3398 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3399 sampler(STATE_SAMPLER(i), stateblock, context);
3403 /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3404 * if a different texture was bound. I don't have to do anything.
3408 /* Disabled the pixel shader - color ops weren't applied
3409 * while it was enabled, so re-apply them.
3411 for(i=0; i < MAX_TEXTURES; i++) {
3412 if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3413 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3414 (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3419 if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3420 device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3422 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3423 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3428 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3429 DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3430 if(stateblock->pixelShader && stage != 0 &&
3431 ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3432 /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3435 if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3436 !isStateDirty(context, STATE_PIXELSHADER)) {
3437 shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3442 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3443 /* This function is called by transform_view below if the view matrix was changed too
3445 * Deliberately no check if the vertex declaration is dirty because the vdecl state
3446 * does not always update the world matrix, only on a switch between transformed
3447 * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3448 * draw, but that should be rather rare and cheaper in total.
3450 glMatrixMode(GL_MODELVIEW);
3451 checkGLcall("glMatrixMode");
3453 if(context->last_was_rhw) {
3455 checkGLcall("glLoadIdentity()");
3457 /* In the general case, the view matrix is the identity matrix */
3458 if (stateblock->wineD3DDevice->view_ident) {
3459 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3460 checkGLcall("glLoadMatrixf");
3462 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3463 checkGLcall("glLoadMatrixf");
3464 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3465 checkGLcall("glMultMatrixf");
3470 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3471 UINT index = state - STATE_CLIPPLANE(0);
3473 if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3477 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3478 glMatrixMode(GL_MODELVIEW);
3480 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3482 TRACE("Clipplane [%f,%f,%f,%f]\n",
3483 stateblock->clipplane[index][0],
3484 stateblock->clipplane[index][1],
3485 stateblock->clipplane[index][2],
3486 stateblock->clipplane[index][3]);
3487 glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3488 checkGLcall("glClipPlane");
3493 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3494 UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3496 TRACE("Setting world matrix %d\n", matrix);
3498 if(matrix >= GL_LIMITS(blends)) {
3499 WARN("Unsupported blend matrix set\n");
3501 } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3505 /* GL_MODELVIEW0_ARB: 0x1700
3506 * GL_MODELVIEW1_ARB: 0x850a
3507 * GL_MODELVIEW2_ARB: 0x8722
3508 * GL_MODELVIEW3_ARB: 0x8723
3510 * GL_MODELVIEW31_ARB: 0x873F
3512 if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3513 else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3515 glMatrixMode(glMat);
3516 checkGLcall("glMatrixMode(glMat)");
3518 /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3519 * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3521 if(stateblock->wineD3DDevice->view_ident) {
3522 glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3523 checkGLcall("glLoadMatrixf");
3525 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3526 checkGLcall("glLoadMatrixf");
3527 glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3528 checkGLcall("glMultMatrixf");
3532 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3533 static BOOL once = FALSE;
3535 switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3536 case WINED3DVBF_1WEIGHTS:
3537 case WINED3DVBF_2WEIGHTS:
3538 case WINED3DVBF_3WEIGHTS:
3541 /* TODO: Implement vertex blending in drawStridedSlow */
3542 FIXME("Vertex blending enabled, but not supported by hardware\n");
3546 case WINED3DVBF_TWEENING:
3547 WARN("Tweening not supported yet\n");
3551 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3552 WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3555 case WINED3DVBF_1WEIGHTS:
3556 case WINED3DVBF_2WEIGHTS:
3557 case WINED3DVBF_3WEIGHTS:
3558 glEnable(GL_VERTEX_BLEND_ARB);
3559 checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3561 /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3562 * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3564 GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3566 if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3568 for(i = 1; i < GL_LIMITS(blends); i++) {
3569 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3570 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3573 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3577 case WINED3DVBF_DISABLE:
3578 case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3579 glDisable(GL_VERTEX_BLEND_ARB);
3580 checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3583 case WINED3DVBF_TWEENING:
3584 /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3585 * vertex weights in the vertices?
3586 * For now we don't report that as supported, so a warn should suffice
3588 WARN("Tweening not supported yet\n");
3593 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3596 /* If we are changing the View matrix, reset the light and clipping planes to the new view
3597 * NOTE: We have to reset the positions even if the light/plane is not currently
3598 * enabled, since the call to enable it will not reset the position.
3599 * NOTE2: Apparently texture transforms do NOT need reapplying
3602 const PLIGHTINFOEL *light = NULL;
3604 glMatrixMode(GL_MODELVIEW);
3605 checkGLcall("glMatrixMode(GL_MODELVIEW)");
3606 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3607 checkGLcall("glLoadMatrixf(...)");
3609 /* Reset lights. TODO: Call light apply func */
3610 for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3611 light = stateblock->activeLights[k];
3612 if(!light) continue;
3613 glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3614 checkGLcall("glLightfv posn");
3615 glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3616 checkGLcall("glLightfv dirn");
3619 /* Reset Clipping Planes */
3620 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3621 if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3622 clipplane(STATE_CLIPPLANE(k), stateblock, context);
3626 if(context->last_was_rhw) {
3628 checkGLcall("glLoadIdentity()");
3629 /* No need to update the world matrix, the identity is fine */
3633 /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3634 * No need to do it here if the state is scheduled for update.
3636 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3637 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3640 /* Avoid looping over a number of matrices if the app never used the functionality */
3641 if(stateblock->wineD3DDevice->vertexBlendUsed) {
3642 for(k = 1; k < GL_LIMITS(blends); k++) {
3643 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3644 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3650 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3651 glMatrixMode(GL_PROJECTION);
3652 checkGLcall("glMatrixMode(GL_PROJECTION)");
3654 checkGLcall("glLoadIdentity");
3656 if(context->last_was_rhw) {
3657 double X, Y, height, width, minZ, maxZ;
3659 X = stateblock->viewport.X;
3660 Y = stateblock->viewport.Y;
3661 height = stateblock->viewport.Height;
3662 width = stateblock->viewport.Width;
3663 minZ = stateblock->viewport.MinZ;
3664 maxZ = stateblock->viewport.MaxZ;
3666 if(!stateblock->wineD3DDevice->untransformed) {
3667 /* Transformed vertices are supposed to bypass the whole transform pipeline including
3668 * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3669 * suppress depth clipping. This can be done because it is an orthogonal projection and
3670 * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3671 * Persia 3D need this.
3673 * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3674 * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3675 * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3678 * Also note that this breaks z comparison against z values filled in with clear,
3679 * but no app depending on that and disabled clipping has been found yet. Comparing
3680 * primitives against themselves works, so the Z buffer is still intact for normal hidden
3683 * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3684 * but this would break Z buffer operation. Raising the range to something less than
3685 * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3688 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3689 if(stateblock->wineD3DDevice->render_offscreen) {
3690 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3692 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3695 /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3696 * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3697 * unmodified to opengl.
3699 * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3700 * replacement shader.
3702 TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3703 if(stateblock->wineD3DDevice->render_offscreen) {
3704 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3706 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3709 checkGLcall("glOrtho");
3711 /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3712 glTranslatef(0.5, 0.5, 0);
3713 checkGLcall("glTranslatef(0.5, 0.5, 0)");
3714 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3715 * render everything upside down when rendering offscreen. */
3716 if (stateblock->wineD3DDevice->render_offscreen) {
3717 glScalef(1.0, -1.0, 1.0);
3718 checkGLcall("glScalef");
3721 /* The rule is that the window coordinate 0 does not correspond to the
3722 beginning of the first pixel, but the center of the first pixel.
3723 As a consequence if you want to correctly draw one line exactly from
3724 the left to the right end of the viewport (with all matrices set to
3725 be identity), the x coords of both ends of the line would be not
3726 -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3729 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3730 divide by the Width/Height, so we need the half range(1.0) to translate by
3733 The other fun is that d3d's output z range after the transformation is [0;1],
3734 but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3735 scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3736 of Z buffer precision and the clear values do not match in the z test. Thus scale
3737 [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3741 * Careful with the order of operations here, we're essentially working backwards:
3743 * y = (y - 1/h) * flip;
3747 * glTranslatef(0.0, 0.0, -1.0);
3748 * glScalef(1.0, 1.0, 2.0);
3750 * glScalef(1.0, flip, 1.0);
3751 * glTranslatef(1/w, -1/h, 0.0);
3753 * This is equivalent to:
3754 * glTranslatef(1/w, -flip/h, -1.0)
3755 * glScalef(1.0, flip, 2.0);
3758 if (stateblock->wineD3DDevice->render_offscreen) {
3759 /* D3D texture coordinates are flipped compared to OpenGL ones, so
3760 * render everything upside down when rendering offscreen. */
3761 glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3762 checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3763 glScalef(1.0, -1.0, 2.0);
3765 glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3766 checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3767 glScalef(1.0, 1.0, 2.0);
3769 checkGLcall("glScalef");
3771 glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3772 checkGLcall("glLoadMatrixf");
3776 /* This should match any arrays loaded in loadVertexData.
3777 * stateblock impl is required for GL_SUPPORT
3778 * TODO: Only load / unload arrays if we have to.
3780 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3781 glDisableClientState(GL_VERTEX_ARRAY);
3782 glDisableClientState(GL_NORMAL_ARRAY);
3783 glDisableClientState(GL_COLOR_ARRAY);
3784 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3785 glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3787 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3788 glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3790 unloadTexCoords(stateblock);
3793 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3795 GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3796 checkGLcall("glDisableVertexAttribArrayARB(reg)");
3797 /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3798 * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3799 * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3800 * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3801 * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3803 GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3804 checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3806 context->numbered_array_mask &= ~(1 << i);
3809 /* This should match any arrays loaded in loadNumberedArrays
3810 * TODO: Only load / unload arrays if we have to.
3812 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3814 /* disable any attribs (this is the same for both GLSL and ARB modes) */
3815 GLint maxAttribs = 16;
3818 /* Leave all the attribs disabled */
3819 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3820 /* MESA does not support it right not */
3821 if (glGetError() != GL_NO_ERROR)
3823 for (i = 0; i < maxAttribs; ++i) {
3824 unload_numbered_array(stateblock, context, i);
3828 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3829 const WineDirect3DVertexStridedData *strided, WineD3DContext *context)
3831 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3833 const UINT *offset = stateblock->streamOffset;
3834 IWineD3DVertexBufferImpl *vb;
3835 DWORD_PTR shift_index;
3837 /* Default to no instancing */
3838 stateblock->wineD3DDevice->instancedDraw = FALSE;
3840 for (i = 0; i < MAX_ATTRIBS; i++) {
3841 if (!(strided->use_map & (1 << i)))
3843 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3847 /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3848 if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
3849 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3850 stateblock->wineD3DDevice->instancedDraw = TRUE;
3854 TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
3856 if(strided->u.input[i].dwStride) {
3857 if(curVBO != strided->u.input[i].VBO) {
3858 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
3859 checkGLcall("glBindBufferARB");
3860 curVBO = strided->u.input[i].VBO;
3862 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3863 /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3864 * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3865 * vbo we won't be load converted attributes anyway
3867 if(curVBO && vb->conv_shift) {
3868 TRACE("Loading attribute from shifted buffer\n");
3869 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
3870 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
3871 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
3872 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
3873 shift_index = shift_index % strided->u.input[i].dwStride;
3874 GL_EXTCALL(glVertexAttribPointerARB(i,
3875 WINED3D_ATR_FORMAT(strided->u.input[i].dwType),
3876 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3877 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3880 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
3881 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3882 offset[strided->u.input[i].streamNo]));
3885 GL_EXTCALL(glVertexAttribPointerARB(i,
3886 WINED3D_ATR_FORMAT(strided->u.input[i].dwType),
3887 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
3888 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
3889 strided->u.input[i].dwStride,
3891 strided->u.input[i].lpData +
3892 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
3893 offset[strided->u.input[i].streamNo]) );
3896 if (!(context->numbered_array_mask & (1 << i)))
3898 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3899 context->numbered_array_mask |= (1 << i);
3902 /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3903 * set up the attribute statically. But we have to figure out the system memory address.
3905 const BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
3906 if(strided->u.input[i].VBO) {
3907 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
3908 ptr += (long) vb->resource.allocatedMemory;
3911 if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3913 switch(strided->u.input[i].dwType) {
3914 case WINED3DDECLTYPE_FLOAT1:
3915 GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3917 case WINED3DDECLTYPE_FLOAT2:
3918 GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3920 case WINED3DDECLTYPE_FLOAT3:
3921 GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3923 case WINED3DDECLTYPE_FLOAT4:
3924 GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3927 case WINED3DDECLTYPE_UBYTE4:
3928 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3930 case WINED3DDECLTYPE_D3DCOLOR:
3931 if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
3933 const DWORD *src = (const DWORD *)ptr;
3934 DWORD c = *src & 0xff00ff00;
3935 c |= (*src & 0xff0000) >> 16;
3936 c |= (*src & 0xff) << 16;
3937 GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
3940 /* else fallthrough */
3941 case WINED3DDECLTYPE_UBYTE4N:
3942 GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3945 case WINED3DDECLTYPE_SHORT2:
3946 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3948 case WINED3DDECLTYPE_SHORT4:
3949 GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3952 case WINED3DDECLTYPE_SHORT2N:
3954 const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
3955 GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3958 case WINED3DDECLTYPE_USHORT2N:
3960 const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
3961 GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3964 case WINED3DDECLTYPE_SHORT4N:
3965 GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
3967 case WINED3DDECLTYPE_USHORT4N:
3968 GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
3971 case WINED3DDECLTYPE_UDEC3:
3972 FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3973 /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
3975 case WINED3DDECLTYPE_DEC3N:
3976 FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3977 /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
3980 case WINED3DDECLTYPE_FLOAT16_2:
3981 /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3982 * byte float according to the IEEE standard
3984 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3986 case WINED3DDECLTYPE_FLOAT16_4:
3987 FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3990 case WINED3DDECLTYPE_UNUSED:
3992 ERR("Unexpected declaration in stride 0 attributes\n");
3998 checkGLcall("Loading numbered arrays");
4001 /* Used from 2 different functions, and too big to justify making it inlined */
4002 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const WineDirect3DVertexStridedData *sd)
4004 const UINT *offset = stateblock->streamOffset;
4005 GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
4007 TRACE("Using fast vertex array code\n");
4009 /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4010 stateblock->wineD3DDevice->instancedDraw = FALSE;
4012 /* Blend Data ---------------------------------------------- */
4013 if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
4014 (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
4016 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4017 TRACE("Blend %d %p %d\n", WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType),
4018 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4020 glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4021 checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4023 GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) + 1));
4025 VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4026 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4027 sd->u.s.blendWeights.dwStride,
4028 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4030 if(curVBO != sd->u.s.blendWeights.VBO) {
4031 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
4032 checkGLcall("glBindBufferARB");
4033 curVBO = sd->u.s.blendWeights.VBO;
4036 GL_EXTCALL(glWeightPointerARB)(
4037 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType),
4038 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
4039 sd->u.s.blendWeights.dwStride,
4040 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
4042 checkGLcall("glWeightPointerARB");
4044 if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
4048 FIXME("blendMatrixIndices support\n");
4053 /* TODO: support blends in drawStridedSlow
4054 * No need to write a FIXME here, this is done after the general vertex decl decoding
4056 WARN("unsupported blending in openGl\n");
4059 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4060 static const GLbyte one = 1;
4061 GL_EXTCALL(glWeightbvARB(1, &one));
4062 checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4066 /* Point Size ----------------------------------------------*/
4067 if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
4069 /* no such functionality in the fixed function GL pipeline */
4070 TRACE("Cannot change ptSize here in openGl\n");
4071 /* TODO: Implement this function in using shaders if they are available */
4075 /* Vertex Pointers -----------------------------------------*/
4076 if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
4077 /* Note dwType == float3 or float4 == 2 or 3 */
4078 VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
4079 sd->u.s.position.dwStride,
4080 sd->u.s.position.dwType + 1,
4081 sd->u.s.position.lpData));
4083 if(curVBO != sd->u.s.position.VBO) {
4084 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
4085 checkGLcall("glBindBufferARB");
4086 curVBO = sd->u.s.position.VBO;
4089 /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4090 handling for rhw mode should not impact screen position whereas in GL it does.
4091 This may result in very slightly distorted textures in rhw mode.
4092 There's always the other option of fixing the view matrix to
4093 prevent w from having any effect.
4095 This only applies to user pointer sources, in VBOs the vertices are fixed up
4097 if(sd->u.s.position.VBO == 0) {
4098 glVertexPointer(3 /* min(WINED3D_ATR_FORMAT(sd->u.s.position.dwType),3) */,
4099 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4100 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4103 WINED3D_ATR_FORMAT(sd->u.s.position.dwType),
4104 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
4105 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
4107 checkGLcall("glVertexPointer(...)");
4108 glEnableClientState(GL_VERTEX_ARRAY);
4109 checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4112 /* Normals -------------------------------------------------*/
4113 if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
4114 /* Note dwType == float3 or float4 == 2 or 3 */
4115 VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
4116 sd->u.s.normal.dwStride,
4117 sd->u.s.normal.lpData));
4118 if(curVBO != sd->u.s.normal.VBO) {
4119 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
4120 checkGLcall("glBindBufferARB");
4121 curVBO = sd->u.s.normal.VBO;
4124 WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
4125 sd->u.s.normal.dwStride,
4126 sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
4127 checkGLcall("glNormalPointer(...)");
4128 glEnableClientState(GL_NORMAL_ARRAY);
4129 checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4132 glNormal3f(0, 0, 0);
4133 checkGLcall("glNormal3f(0, 0, 0)");
4136 /* Diffuse Colour --------------------------------------------*/
4137 /* WARNING: Data here MUST be in RGBA format, so cannot */
4138 /* go directly into fast mode from app pgm, because */
4139 /* directx requires data in BGRA format. */
4140 /* currently fixupVertices swizzles the format, but this isn't*/
4141 /* very practical when using VBOs */
4142 /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4143 /* , or the user doesn't care and wants the speed advantage */
4145 if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
4146 /* Note dwType == float3 or float4 == 2 or 3 */
4147 VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4148 sd->u.s.diffuse.dwStride,
4149 sd->u.s.diffuse.lpData));
4151 if(curVBO != sd->u.s.diffuse.VBO) {
4152 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
4153 checkGLcall("glBindBufferARB");
4154 curVBO = sd->u.s.diffuse.VBO;
4157 glColorPointer(WINED3D_ATR_FORMAT(sd->u.s.diffuse.dwType),
4158 WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
4159 sd->u.s.diffuse.dwStride,
4160 sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
4161 checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4162 glEnableClientState(GL_COLOR_ARRAY);
4163 checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4166 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4167 checkGLcall("glColor4f(1, 1, 1, 1)");
4170 /* Specular Colour ------------------------------------------*/
4171 if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
4172 TRACE("setting specular colour\n");
4173 /* Note dwType == float3 or float4 == 2 or 3 */
4174 VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
4175 sd->u.s.specular.dwStride,
4176 sd->u.s.specular.lpData));
4177 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4178 if(curVBO != sd->u.s.specular.VBO) {
4179 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
4180 checkGLcall("glBindBufferARB");
4181 curVBO = sd->u.s.specular.VBO;
4183 GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_FORMAT(sd->u.s.specular.dwType),
4184 WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
4185 sd->u.s.specular.dwStride,
4186 sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
4187 checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4188 glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4189 checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4192 /* Missing specular color is not critical, no warnings */
4193 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4197 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4198 GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4199 checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4202 /* Missing specular color is not critical, no warnings */
4203 VTRACE(("Specular colour is not supported in this GL implementation\n"));
4207 /* Texture coords -------------------------------------------*/
4208 loadTexCoords(stateblock, sd, &curVBO);
4211 static inline void drawPrimitiveTraceDataLocations(const WineDirect3DVertexStridedData *dataLocations)
4213 /* Dump out what parts we have supplied */
4214 TRACE("Strided Data:\n");
4215 TRACE_STRIDED((dataLocations), position);
4216 TRACE_STRIDED((dataLocations), blendWeights);
4217 TRACE_STRIDED((dataLocations), blendMatrixIndices);
4218 TRACE_STRIDED((dataLocations), normal);
4219 TRACE_STRIDED((dataLocations), pSize);
4220 TRACE_STRIDED((dataLocations), diffuse);
4221 TRACE_STRIDED((dataLocations), specular);
4222 TRACE_STRIDED((dataLocations), texCoords[0]);
4223 TRACE_STRIDED((dataLocations), texCoords[1]);
4224 TRACE_STRIDED((dataLocations), texCoords[2]);
4225 TRACE_STRIDED((dataLocations), texCoords[3]);
4226 TRACE_STRIDED((dataLocations), texCoords[4]);
4227 TRACE_STRIDED((dataLocations), texCoords[5]);
4228 TRACE_STRIDED((dataLocations), texCoords[6]);
4229 TRACE_STRIDED((dataLocations), texCoords[7]);
4230 TRACE_STRIDED((dataLocations), position2);
4231 TRACE_STRIDED((dataLocations), normal2);
4232 TRACE_STRIDED((dataLocations), tangent);
4233 TRACE_STRIDED((dataLocations), binormal);
4234 TRACE_STRIDED((dataLocations), tessFactor);
4235 TRACE_STRIDED((dataLocations), fog);
4236 TRACE_STRIDED((dataLocations), depth);
4237 TRACE_STRIDED((dataLocations), sample);
4242 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4243 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4245 WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
4246 BOOL useVertexShaderFunction;
4247 BOOL load_numbered = FALSE;
4248 BOOL load_named = FALSE;
4250 useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4252 if(device->up_strided) {
4253 /* Note: this is a ddraw fixed-function code path */
4254 TRACE("================ Strided Input ===================\n");
4255 memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
4258 drawPrimitiveTraceDataLocations(dataLocations);
4261 /* Note: This is a fixed function or shader codepath.
4262 * This means it must handle both types of strided data.
4263 * Shaders must go through here to zero the strided data, even if they
4264 * don't set any declaration at all
4266 TRACE("================ Vertex Declaration ===================\n");
4267 memset(dataLocations, 0, sizeof(*dataLocations));
4268 primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
4269 useVertexShaderFunction, dataLocations, &fixup);
4272 if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4274 if(useVertexShaderFunction) {
4275 if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4276 TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4277 device->useDrawStridedSlow = TRUE;
4279 load_numbered = TRUE;
4280 device->useDrawStridedSlow = FALSE;
4282 } else if (fixup || (!dataLocations->u.s.pSize.lpData
4283 && !dataLocations->position_transformed
4284 && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)
4285 || (!dataLocations->u.s.diffuse.lpData
4286 && !dataLocations->u.s.specular.lpData))))
4288 /* Load the vertex data using named arrays */
4290 device->useDrawStridedSlow = FALSE;
4292 TRACE("Not loading vertex data\n");
4293 device->useDrawStridedSlow = TRUE;
4296 if (context->numberedArraysLoaded && !load_numbered)
4298 unloadNumberedArrays(stateblock, context);
4299 context->numberedArraysLoaded = FALSE;
4300 context->numbered_array_mask = 0;
4302 else if (context->namedArraysLoaded)
4304 unloadVertexData(stateblock);
4305 context->namedArraysLoaded = FALSE;
4310 TRACE("Loading numbered arrays\n");
4311 loadNumberedArrays(stateblock, dataLocations, context);
4312 context->numberedArraysLoaded = TRUE;
4314 else if (load_named)
4316 TRACE("Loading vertex data\n");
4317 loadVertexData(stateblock, dataLocations);
4318 context->namedArraysLoaded = TRUE;
4321 /* Generate some fixme's if unsupported functionality is being used */
4322 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
4323 /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
4324 if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
4325 FIXME("Tweening is only valid with vertex shaders\n");
4327 if (!useVertexShaderFunction && BUFFER_OR_DATA(binormal)) {
4328 FIXME("Binormal bump mapping is only valid with vertex shaders\n");
4330 if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
4331 FIXME("Extended attributes are only valid with vertex shaders\n");
4333 #undef BUFFER_OR_DATA
4336 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4337 BOOL updateFog = FALSE;
4338 BOOL useVertexShaderFunction = use_vs(stateblock);
4339 BOOL usePixelShaderFunction = use_ps(stateblock);
4341 /* Some stuff is in the device until we have per context tracking */
4342 IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4343 BOOL wasrhw = context->last_was_rhw;
4345 transformed = device->strided_streams.position_transformed;
4346 if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4350 /* Reapply lighting if it is not scheduled for reapplication already */
4351 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4352 state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4356 context->last_was_rhw = TRUE;
4359 /* Untransformed, so relies on the view and projection matrices */
4360 context->last_was_rhw = FALSE;
4361 /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4362 device->untransformed = TRUE;
4364 /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4365 * Not needed as long as only hw shaders are supported
4368 /* This sets the shader output position correction constants.
4369 * TODO: Move to the viewport state
4371 if (useVertexShaderFunction) {
4372 device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4373 device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4377 /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4378 * off this function will be called again anyway to make sure they're properly set
4380 if(!useVertexShaderFunction) {
4381 /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4382 * or transformed / untransformed was switched
4384 if(wasrhw != context->last_was_rhw &&
4385 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4386 !isStateDirty(context, STATE_VIEWPORT)) {
4387 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4389 /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4392 * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4393 * this check will fail and the matrix not applied again. This is OK because a simple
4394 * world matrix change reapplies the matrix - These checks here are only to satisfy the
4395 * needs of the vertex declaration.
4397 * World and view matrix go into the same gl matrix, so only apply them when neither is
4400 if(transformed != wasrhw &&
4401 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4402 !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4403 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4406 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4407 state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4410 if(context->last_was_vshader) {
4412 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4413 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4416 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4417 state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4420 if(!context->last_was_vshader) {
4422 static BOOL warned = FALSE;
4423 /* Disable all clip planes to get defined results on all drivers. See comment in the
4424 * state_clipping state handler
4426 for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4427 glDisable(GL_CLIP_PLANE0 + i);
4428 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4431 if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4432 FIXME("Clipping not supported with vertex shaders\n");
4436 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4437 * shaders themselves do not need it, but the matrices are not reapplied automatically when
4438 * switching back from vertex shaders to fixed function processing. So make sure we leave the
4439 * fixed function vertex processing states back in a sane state before switching to shaders
4441 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4442 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4444 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4445 transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4452 /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4455 if (!isStateDirty(context, STATE_PIXELSHADER)) {
4456 device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4458 if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4459 shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4463 context->last_was_vshader = useVertexShaderFunction;
4466 device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4468 if(!useVertexShaderFunction) {
4470 for(i = 0; i < MAX_TEXTURES; i++) {
4471 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4472 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4478 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4480 IWineD3DSurfaceImpl *target;
4482 glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4483 checkGLcall("glDepthRange");
4484 /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4486 if(stateblock->wineD3DDevice->render_offscreen) {
4487 glViewport(stateblock->viewport.X,
4488 stateblock->viewport.Y,
4489 stateblock->viewport.Width, stateblock->viewport.Height);
4491 target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4492 target->get_drawable_size(target, &width, &height);
4494 glViewport(stateblock->viewport.X,
4495 (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4496 stateblock->viewport.Width, stateblock->viewport.Height);
4499 checkGLcall("glViewport");
4502 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4503 stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4504 stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4505 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4506 transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4508 if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4509 state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4513 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4514 UINT Index = state - STATE_ACTIVELIGHT(0);
4515 const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4518 glDisable(GL_LIGHT0 + Index);
4519 checkGLcall("glDisable(GL_LIGHT0 + Index)");
4522 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4524 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4525 glMatrixMode(GL_MODELVIEW);
4527 glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4530 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4531 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4532 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4533 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4534 glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4535 checkGLcall("glLightfv");
4538 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4539 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4540 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4541 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4542 glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4543 checkGLcall("glLightfv");
4546 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4547 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4548 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4549 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4550 glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4551 checkGLcall("glLightfv");
4553 if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4554 quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4556 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
4559 /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4560 * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4561 * Attenuation0 to NaN and crashes in the gl lib
4564 switch (lightInfo->OriginalParms.Type) {
4565 case WINED3DLIGHT_POINT:
4567 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4568 checkGLcall("glLightfv");
4569 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4570 checkGLcall("glLightf");
4571 /* Attenuation - Are these right? guessing... */
4572 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4573 checkGLcall("glLightf");
4574 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4575 checkGLcall("glLightf");
4576 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4577 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4578 checkGLcall("glLightf");
4582 case WINED3DLIGHT_SPOT:
4584 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4585 checkGLcall("glLightfv");
4587 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4588 checkGLcall("glLightfv");
4589 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4590 checkGLcall("glLightf");
4591 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4592 checkGLcall("glLightf");
4593 /* Attenuation - Are these right? guessing... */
4594 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
4595 checkGLcall("glLightf");
4596 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
4597 checkGLcall("glLightf");
4598 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4599 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4600 checkGLcall("glLightf");
4604 case WINED3DLIGHT_DIRECTIONAL:
4606 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4607 checkGLcall("glLightfv");
4608 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4609 checkGLcall("glLightf");
4610 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4611 checkGLcall("glLightf");
4615 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4618 /* Restore the modelview matrix */
4621 glEnable(GL_LIGHT0 + Index);
4622 checkGLcall("glEnable(GL_LIGHT0 + Index)");
4628 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4629 RECT *pRect = &stateblock->scissorRect;
4632 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4634 target->get_drawable_size(target, &width, &height);
4635 /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4636 * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4638 TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4639 pRect->right - pRect->left, pRect->bottom - pRect->top);
4641 if (stateblock->wineD3DDevice->render_offscreen) {
4642 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4644 glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4646 checkGLcall("glScissor");
4649 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4650 if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4651 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4653 IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
4654 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
4658 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4659 if(stateblock->wineD3DDevice->render_offscreen) {
4660 glFrontFace(GL_CCW);
4661 checkGLcall("glFrontFace(GL_CCW)");
4664 checkGLcall("glFrontFace(GL_CW)");
4668 const struct StateEntryTemplate misc_state_template[] = {
4669 { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4670 { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4671 { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4672 { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4673 { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4674 { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4675 { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4676 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4677 { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4678 { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, 0 },
4679 { STATE_STREAMSRC, { STATE_VDECL, streamsrc }, 0 },
4680 { STATE_VDECL, { STATE_VDECL, streamsrc }, 0 },
4681 { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, 0 },
4682 { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, 0 },
4683 /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4684 * vshader loadings are untied from each other
4686 { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4687 { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, 0 },
4688 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4689 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4690 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4691 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4692 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4693 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4694 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4695 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4696 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4697 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4698 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4699 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4700 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4701 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4702 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4703 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4704 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4705 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4706 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4707 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4708 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4709 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4710 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4711 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4712 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4713 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4714 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4715 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4716 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4717 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4718 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4719 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, 0 },
4720 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4721 { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4722 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4723 { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4724 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4725 { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4726 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4727 { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4728 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4729 { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4730 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4731 { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4732 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4733 { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4734 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4735 { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, 0 },
4737 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, 0 },
4738 { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT },
4739 { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, 0 },
4740 { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, 0 },
4741 { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, 0 },
4742 { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, 0 },
4743 { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, 0 },
4744 { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, 0 },
4745 { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, 0 },
4746 { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, 0 },
4747 { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, 0 },
4748 { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, 0 },
4749 { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, 0 },
4750 { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, 0 },
4751 { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4752 { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4753 { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4754 { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, 0 },
4755 { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, 0 },
4756 { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, 0 },
4757 { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, 0 },
4758 { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, 0 },
4759 { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, 0 },
4760 { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, 0 },
4761 { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, 0 },
4762 { STATE_RENDER(WINED3DRS_ZBIAS), { STATE_RENDER(WINED3DRS_ZBIAS), state_zbias }, 0 },
4763 { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, 0 },
4764 { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, 0 },
4765 { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, 0 },
4766 { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, 0 },
4767 { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0 },
4768 { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4769 { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4770 { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4771 { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4772 { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4773 { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4774 { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4775 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE },
4776 { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, 0 },
4777 { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4778 { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4779 { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4780 { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4781 { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, 0 },
4782 { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4783 { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4784 { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4785 { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4786 { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4787 { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4788 { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4789 { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4790 { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4791 { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4792 { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4793 { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4794 { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4795 { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4796 { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4797 { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, 0 },
4798 { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, 0 },
4799 { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, 0 },
4800 { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, 0 },
4801 { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, 0 },
4802 { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, 0 },
4803 { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, 0 },
4804 { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4805 { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4806 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4807 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4808 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4809 { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4810 { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, 0 },
4811 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE },
4812 { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, 0 },
4813 { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, 0 },
4814 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4815 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX },
4816 { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, 0 },
4817 { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, 0 },
4818 { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4819 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4820 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4821 { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, 0 },
4822 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR },
4823 { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, 0 },
4824 { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, 0 },
4826 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, 0 },
4827 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, 0 },
4828 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, 0 },
4829 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, 0 },
4830 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, 0 },
4831 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, 0 },
4832 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, 0 },
4833 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, 0 },
4834 { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, 0 },
4835 { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, 0 },
4836 { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, 0 },
4837 { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, 0 },
4838 { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, 0 },
4839 { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, 0 },
4840 { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, 0 },
4841 { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, 0 },
4842 { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, 0 },
4843 { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, 0 },
4844 { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, 0 },
4845 { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, 0 },
4846 {0 /* Terminate */, { 0, 0 }, 0 },
4849 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4850 { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, 0 },
4851 { STATE_VSHADER, { STATE_VDECL, vertexdeclaration }, 0 },
4852 { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4853 { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, 0 },
4855 { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, 0 },
4856 { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, 0 },
4857 { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, 0 },
4858 { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, 0 },
4859 { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, 0 },
4860 { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, 0 },
4861 { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, 0 },
4862 { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, 0 },
4863 { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, 0 },
4864 { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, 0 },
4865 { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, 0 },
4866 { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, 0 },
4867 { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, 0 },
4868 { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, 0 },
4869 { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, 0 },
4870 { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, 0 },
4871 { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, 0 },
4872 { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, 0 },
4873 { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, 0 },
4874 { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, 0 },
4875 { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, 0 },
4876 { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, 0 },
4877 { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, 0 },
4878 { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, 0 },
4879 { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, 0 },
4880 { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, 0 },
4881 { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, 0 },
4882 { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, 0 },
4883 { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, 0 },
4884 { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, 0 },
4885 { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, 0 },
4886 { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, 0 },
4888 { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, 0 },
4889 { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, 0 },
4890 { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, 0 },
4891 { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, 0 },
4892 { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, 0 },
4893 { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, 0 },
4894 { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, 0 },
4895 { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, 0 },
4897 { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, 0 },
4898 /* Transform states follow */
4899 { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, 0 },
4900 { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, 0 },
4901 { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4902 { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4903 { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4904 { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4905 { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4906 { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4907 { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4908 { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), transform_texture }, 0 },
4909 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, 0 },
4910 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, 0 },
4911 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, 0 },
4912 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, 0 },
4913 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, 0 },
4914 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, 0 },
4915 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, 0 },
4916 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, 0 },
4917 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, 0 },
4918 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, 0 },
4919 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, 0 },
4920 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, 0 },
4921 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, 0 },
4922 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, 0 },
4923 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, 0 },
4924 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, 0 },
4925 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, 0 },
4926 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, 0 },
4927 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, 0 },
4928 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, 0 },
4929 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, 0 },
4930 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, 0 },
4931 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, 0 },
4932 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, 0 },
4933 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, 0 },
4934 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, 0 },
4935 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, 0 },
4936 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, 0 },
4937 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, 0 },
4938 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, 0 },
4939 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, 0 },
4940 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, 0 },
4941 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, 0 },
4942 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, 0 },
4943 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, 0 },
4944 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, 0 },
4945 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, 0 },
4946 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, 0 },
4947 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, 0 },
4948 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, 0 },
4949 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, 0 },
4950 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, 0 },
4951 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, 0 },
4952 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, 0 },
4953 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, 0 },
4954 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, 0 },
4955 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, 0 },
4956 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, 0 },
4957 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, 0 },
4958 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, 0 },
4959 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, 0 },
4960 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, 0 },
4961 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, 0 },
4962 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, 0 },
4963 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, 0 },
4964 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, 0 },
4965 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, 0 },
4966 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, 0 },
4967 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, 0 },
4968 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, 0 },
4969 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, 0 },
4970 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, 0 },
4971 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, 0 },
4972 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, 0 },
4973 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, 0 },
4974 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, 0 },
4975 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, 0 },
4976 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, 0 },
4977 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, 0 },
4978 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, 0 },
4979 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, 0 },
4980 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, 0 },
4981 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, 0 },
4982 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, 0 },
4983 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, 0 },
4984 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, 0 },
4985 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, 0 },
4986 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, 0 },
4987 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, 0 },
4988 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, 0 },
4989 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, 0 },
4990 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, 0 },
4991 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, 0 },
4992 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, 0 },
4993 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, 0 },
4994 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, 0 },
4995 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, 0 },
4996 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, 0 },
4997 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, 0 },
4998 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, 0 },
4999 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, 0 },
5000 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, 0 },
5001 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, 0 },
5002 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, 0 },
5003 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, 0 },
5004 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, 0 },
5005 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, 0 },
5006 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, 0 },
5007 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, 0 },
5008 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, 0 },
5009 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, 0 },
5010 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, 0 },
5011 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, 0 },
5012 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, 0 },
5013 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, 0 },
5014 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, 0 },
5015 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, 0 },
5016 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, 0 },
5017 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, 0 },
5018 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, 0 },
5019 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, 0 },
5020 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, 0 },
5021 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, 0 },
5022 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, 0 },
5023 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, 0 },
5024 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, 0 },
5025 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, 0 },
5026 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, 0 },
5027 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, 0 },
5028 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, 0 },
5029 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, 0 },
5030 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, 0 },
5031 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, 0 },
5032 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, 0 },
5033 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, 0 },
5034 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, 0 },
5035 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, 0 },
5036 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, 0 },
5037 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, 0 },
5038 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, 0 },
5039 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, 0 },
5040 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, 0 },
5041 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, 0 },
5042 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, 0 },
5043 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, 0 },
5044 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, 0 },
5045 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, 0 },
5046 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, 0 },
5047 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, 0 },
5048 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, 0 },
5049 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, 0 },
5050 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, 0 },
5051 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, 0 },
5052 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, 0 },
5053 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, 0 },
5054 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, 0 },
5055 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, 0 },
5056 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, 0 },
5057 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, 0 },
5058 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, 0 },
5059 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, 0 },
5060 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, 0 },
5061 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, 0 },
5062 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, 0 },
5063 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, 0 },
5064 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, 0 },
5065 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, 0 },
5066 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, 0 },
5067 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, 0 },
5068 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, 0 },
5069 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, 0 },
5070 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, 0 },
5071 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, 0 },
5072 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, 0 },
5073 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, 0 },
5074 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, 0 },
5075 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, 0 },
5076 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, 0 },
5077 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, 0 },
5078 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, 0 },
5079 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, 0 },
5080 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, 0 },
5081 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, 0 },
5082 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, 0 },
5083 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, 0 },
5084 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, 0 },
5085 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, 0 },
5086 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, 0 },
5087 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, 0 },
5088 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, 0 },
5089 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, 0 },
5090 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, 0 },
5091 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, 0 },
5092 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, 0 },
5093 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, 0 },
5094 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, 0 },
5095 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, 0 },
5096 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, 0 },
5097 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, 0 },
5098 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, 0 },
5099 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, 0 },
5100 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, 0 },
5101 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, 0 },
5102 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, 0 },
5103 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, 0 },
5104 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, 0 },
5105 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, 0 },
5106 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, 0 },
5107 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, 0 },
5108 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, 0 },
5109 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, 0 },
5110 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, 0 },
5111 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, 0 },
5112 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, 0 },
5113 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, 0 },
5114 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, 0 },
5115 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, 0 },
5116 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, 0 },
5117 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, 0 },
5118 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, 0 },
5119 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, 0 },
5120 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, 0 },
5121 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, 0 },
5122 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, 0 },
5123 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, 0 },
5124 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, 0 },
5125 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, 0 },
5126 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, 0 },
5127 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, 0 },
5128 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, 0 },
5129 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, 0 },
5130 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, 0 },
5131 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, 0 },
5132 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, 0 },
5133 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, 0 },
5134 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, 0 },
5135 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, 0 },
5136 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, 0 },
5137 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, 0 },
5138 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, 0 },
5139 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, 0 },
5140 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, 0 },
5141 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, 0 },
5142 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, 0 },
5143 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, 0 },
5144 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, 0 },
5145 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, 0 },
5146 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, 0 },
5147 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, 0 },
5148 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, 0 },
5149 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, 0 },
5150 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, 0 },
5151 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, 0 },
5152 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, 0 },
5153 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, 0 },
5154 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, 0 },
5155 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, 0 },
5156 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, 0 },
5157 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, 0 },
5158 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, 0 },
5159 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, 0 },
5160 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, 0 },
5161 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, 0 },
5162 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, 0 },
5163 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, 0 },
5164 { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, 0 },
5165 { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5166 { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5167 { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5168 { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5169 { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5170 { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5171 { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5172 { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, 0 },
5173 { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5174 { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5175 { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5176 { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5177 { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5178 { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5179 { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5180 { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, 0 },
5182 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5183 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5184 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, 0 },
5185 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE },
5186 { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, 0 },
5187 { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5188 { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, 0 },
5189 { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, 0 },
5190 { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, 0 },
5191 { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5192 { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, 0 },
5193 { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, 0 },
5194 { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5195 { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5196 { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5197 { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, 0 },
5198 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND },
5199 { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, 0 },
5200 { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5201 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5202 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5203 { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5204 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE },
5205 { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, 0 },
5206 { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5207 { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5208 { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5209 { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, 0 },
5210 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS },
5211 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS },
5212 { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, 0 },
5213 /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5214 * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5215 * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5217 { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5218 { STATE_SAMPLER(0), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5219 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, 0 },
5220 { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5221 { STATE_SAMPLER(1), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5222 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, 0 },
5223 { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5224 { STATE_SAMPLER(2), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5225 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, 0 },
5226 { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5227 { STATE_SAMPLER(3), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5228 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, 0 },
5229 { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5230 { STATE_SAMPLER(4), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5231 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, 0 },
5232 { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5233 { STATE_SAMPLER(5), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5234 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, 0 },
5235 { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5236 { STATE_SAMPLER(6), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5237 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, 0 },
5238 { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO },
5239 { STATE_SAMPLER(7), { 0, NULL }, WINE_NORMALIZED_TEXRECT },
5240 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, 0 },
5241 {0 /* Terminate */, { 0, 0 }, 0 },
5244 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5245 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5246 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5247 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5248 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5249 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5250 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5251 { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5252 { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5253 { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5254 { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5255 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5256 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5257 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5258 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5259 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5260 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5261 { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5262 { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5263 { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5264 { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5265 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5266 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5267 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5268 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5269 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5270 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5271 { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5272 { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5273 { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5274 { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5275 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5276 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5277 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5278 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5279 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5280 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5281 { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5282 { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5283 { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5284 { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5285 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5286 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5287 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5288 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5289 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5290 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5291 { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5292 { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5293 { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5294 { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5295 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5296 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5297 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5298 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5299 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5300 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5301 { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5302 { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5303 { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5304 { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5305 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5306 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5307 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5308 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5309 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5310 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5311 { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5312 { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5313 { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5314 { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5315 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5316 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5317 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5318 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5319 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5320 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5321 { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5322 { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, 0 },
5323 { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, 0 },
5324 { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl }, 0 },
5325 { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5326 { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, apply_pixelshader }, 0 },
5327 { STATE_RENDER(WINED3DRS_BORDERCOLOR), { STATE_RENDER(WINED3DRS_BORDERCOLOR), state_bordercolor }, 0 },
5328 { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, 0 },
5329 { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, 0 },
5330 { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, 0 },
5331 { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5332 { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5333 { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, 0 },
5334 { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
5335 { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, 0 },
5336 { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, 0 },
5337 { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, 0 },
5338 { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, 0 },
5339 { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, 0 },
5340 { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, 0 },
5341 { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, 0 },
5342 { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, 0 },
5343 { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, 0 },
5344 {0 /* Terminate */, { 0, 0 }, 0 },
5346 #undef GLINFO_LOCATION
5348 #define GLINFO_LOCATION (*gl_info)
5349 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5351 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5353 pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
5354 WINED3DTEXOPCAPS_ADDSIGNED |
5355 WINED3DTEXOPCAPS_ADDSIGNED2X |
5356 WINED3DTEXOPCAPS_MODULATE |
5357 WINED3DTEXOPCAPS_MODULATE2X |
5358 WINED3DTEXOPCAPS_MODULATE4X |
5359 WINED3DTEXOPCAPS_SELECTARG1 |
5360 WINED3DTEXOPCAPS_SELECTARG2 |
5361 WINED3DTEXOPCAPS_DISABLE;
5363 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5364 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5365 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5366 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
5367 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
5368 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
5369 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
5370 WINED3DTEXOPCAPS_LERP |
5371 WINED3DTEXOPCAPS_SUBTRACT;
5373 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5374 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5375 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
5376 WINED3DTEXOPCAPS_MULTIPLYADD |
5377 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5378 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5379 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5381 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5382 pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5384 pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
5385 pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5388 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5389 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5390 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5394 TRACE("Checking support for fixup:\n");
5395 dump_color_fixup_desc(fixup);
5398 /* We only support identity conversions. */
5399 if (is_identity_fixup(fixup))
5405 TRACE("[FAILED]\n");
5409 const struct fragment_pipeline ffp_fragment_pipeline = {
5411 ffp_fragment_get_caps,
5414 ffp_color_fixup_supported,
5415 ffp_fragmentstate_template,
5416 FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5419 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5422 for(i = 0; funcs[i]; i++);
5426 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5427 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5428 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5431 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5432 stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5433 stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5434 stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5437 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5438 const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5439 const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5441 unsigned int i, type, handlers;
5442 APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5443 const struct StateEntryTemplate *cur;
5444 BOOL set[STATE_HIGHEST + 1];
5446 memset(multistate_funcs, 0, sizeof(multistate_funcs));
5448 for(i = 0; i < STATE_HIGHEST + 1; i++) {
5449 StateTable[i].representative = 0;
5450 StateTable[i].apply = state_undefined;
5453 for(type = 0; type < 3; type++) {
5454 /* This switch decides the order in which the states are applied */
5456 case 0: cur = misc; break;
5457 case 1: cur = fragment->states; break;
5458 case 2: cur = vertex; break;
5459 default: cur = NULL; /* Stupid compiler */
5463 /* GL extension filtering should not prevent multiple handlers being applied from different
5466 memset(set, 0, sizeof(set));
5468 for(i = 0; cur[i].state; i++) {
5469 APPLYSTATEFUNC *funcs_array;
5471 /* Only use the first matching state with the available extension from one template.
5473 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5474 * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 }
5476 * if GL_XYZ_fancy is supported, ignore the 2nd line
5478 if(set[cur[i].state]) continue;
5479 /* Skip state lines depending on unsupported extensions */
5480 if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5481 set[cur[i].state] = TRUE;
5482 /* In some cases having an extension means that nothing has to be
5483 * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5484 * supported, the texture coordinate fixup can be ignored. If the
5485 * apply function is used, mark the state set(done above) to prevent
5486 * applying later lines, but do not record anything in the state
5489 if(!cur[i].content.apply) continue;
5491 handlers = num_handlers(multistate_funcs[cur[i].state]);
5492 multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5495 StateTable[cur[i].state].apply = cur[i].content.apply;
5498 StateTable[cur[i].state].apply = multistate_apply_2;
5499 dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5501 sizeof(**dev_multistate_funcs) * 2);
5502 if (!dev_multistate_funcs[cur[i].state]) {
5506 dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5507 dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5510 StateTable[cur[i].state].apply = multistate_apply_3;
5511 funcs_array = HeapReAlloc(GetProcessHeap(),
5513 dev_multistate_funcs[cur[i].state],
5514 sizeof(**dev_multistate_funcs) * 3);
5519 dev_multistate_funcs[cur[i].state] = funcs_array;
5520 dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5523 ERR("Unexpected amount of state handlers for state %u: %u\n",
5524 cur[i].state, handlers + 1);
5527 if(StateTable[cur[i].state].representative &&
5528 StateTable[cur[i].state].representative != cur[i].content.representative) {
5529 FIXME("State %u has different representatives in different pipeline parts\n",
5532 StateTable[cur[i].state].representative = cur[i].content.representative;
5539 for (i = 0; i <= STATE_HIGHEST; ++i) {
5540 HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5543 memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5545 return E_OUTOFMEMORY;
5547 #undef GLINFO_LOCATION