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