From: Amine Khaldi Date: Tue, 14 Jun 2011 17:04:03 +0000 (+0000) Subject: [CMAKE] X-Git-Tag: backups/ros-amd64-bringup@60669^2~377 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=6ba68445bf4c455d493fa05b93255a0e41c74016 [CMAKE] * Skip ftp, libxslt and ksproxy from msvc build. * Remove msvchelper.h as it's not needed anymore for d3d8 and d3d9. * Merge r50731 from the cmake branch. * Merge r50732 from the cmake branch and apply the same fix to state.c. svn path=/trunk/; revision=52232 --- 6ba68445bf4c455d493fa05b93255a0e41c74016 diff --cc reactos/base/applications/network/CMakeLists.txt index d961ff60aa5,00000000000..5d5899a4103 mode 100644,000000..100644 --- a/reactos/base/applications/network/CMakeLists.txt +++ b/reactos/base/applications/network/CMakeLists.txt @@@ -1,16 -1,0 +1,18 @@@ + +add_subdirectory(arp) +add_subdirectory(dwnl) +add_subdirectory(finger) - add_subdirectory(ftp) ++if(NOT MSVC) ++ add_subdirectory(ftp) # FIXME: fix msvc build ++endif() +add_subdirectory(ipconfig) +add_subdirectory(net) +add_subdirectory(netstat) +add_subdirectory(nslookup) +add_subdirectory(ping) +add_subdirectory(route) +if(NOT MSVC) - add_subdirectory(telnet) ++ add_subdirectory(telnet) # FIXME: fix msvc build +endif() +add_subdirectory(tracert) +add_subdirectory(whois) diff --cc reactos/dll/3rdparty/CMakeLists.txt index bf606568afe,00000000000..53f513c732a mode 100644,000000..100644 --- a/reactos/dll/3rdparty/CMakeLists.txt +++ b/reactos/dll/3rdparty/CMakeLists.txt @@@ -1,11 -1,0 +1,12 @@@ + +if(NSWPAT) +add_subdirectory(dxtn) +endif() +add_subdirectory(libjpeg) +add_subdirectory(libpng) +add_subdirectory(libtiff) - add_subdirectory(libxslt) ++ +if(NOT MSVC) - add_subdirectory(mesa32) ++ add_subdirectory(libxslt) ++ add_subdirectory(mesa32) +endif() diff --cc reactos/dll/directx/CMakeLists.txt index 5a92a036a35,00000000000..0f8f70ab3f6 mode 100644,000000..100644 --- a/reactos/dll/directx/CMakeLists.txt +++ b/reactos/dll/directx/CMakeLists.txt @@@ -1,26 -1,0 +1,28 @@@ + +if (NOT MSVC) +add_subdirectory(amstream) +add_subdirectory(d3d8thk) +endif() +#add_subdirectory(bdaplgin) #disabled in trunk +#add_subdirectory(d3d8) #disabled in trunk +#add_subdirectory(d3d9) #disabled in trunk +#add_subdirectory(ddraw) #disabled in trunk +add_subdirectory(devenum) +add_subdirectory(dinput) +add_subdirectory(dinput8) +add_subdirectory(dmusic) +add_subdirectory(dplay) +add_subdirectory(dplayx) +add_subdirectory(dsound) +#add_subdirectory(dsound_new) #disabled in trunk +add_subdirectory(dxdiagn) - add_subdirectory(ksproxy) ++if(NOT MSVC) ++ add_subdirectory(ksproxy) #FIXME: fix msvc build ++endif() +add_subdirectory(ksuser) +add_subdirectory(msdmo) +#add_subdirectory(msdvbnp) #disabled in trunk +#add_subdirectory(msvidctl) #disabled in trunk +add_subdirectory(qedit) +add_subdirectory(quartz) +add_subdirectory(wine) diff --cc reactos/dll/directx/wine/d3d8/CMakeLists.txt index fa6842fb891,00000000000..5586bd68c78 mode 100644,000000..100644 --- a/reactos/dll/directx/wine/d3d8/CMakeLists.txt +++ b/reactos/dll/directx/wine/d3d8/CMakeLists.txt @@@ -1,50 -1,0 +1,46 @@@ + +set_unicode() + +add_definitions( + -D__WINESRC__ + -DUSE_WIN32_OPENGL) + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) + - if(MSVC) - add_definitions(-FImsvchelper.h) - endif() - +set_rc_compiler() + +spec2def(d3d8.dll d3d8.spec) + +list(APPEND SOURCE + buffer.c + cubetexture.c + d3d8_main.c + device.c + directx.c + shader.c + surface.c + swapchain.c + texture.c + vertexdeclaration.c + volume.c + volumetexture.c + version.rc + ${CMAKE_CURRENT_BINARY_DIR}/d3d8.def) + +add_library(d3d8 SHARED ${SOURCE}) + +set_module_type(d3d8 win32dll) + +target_link_libraries(d3d8 uuid wine) + +add_importlibs(d3d8 + user32 + gdi32 + advapi32 + wined3d + msvcrt + kernel32 + ntdll) + +add_dependencies(d3d8 wineheaders) +add_cd_file(TARGET d3d8 DESTINATION reactos/system32 FOR all) diff --cc reactos/dll/directx/wine/d3d9/CMakeLists.txt index bf2dd4068f2,00000000000..642815dc02b mode 100644,000000..100644 --- a/reactos/dll/directx/wine/d3d9/CMakeLists.txt +++ b/reactos/dll/directx/wine/d3d9/CMakeLists.txt @@@ -1,54 -1,0 +1,50 @@@ + +set_unicode() + +add_definitions( + -D__WINESRC__ + -DUSE_WIN32_OPENGL) + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) + - if(MSVC) - add_definitions(-FImsvchelper.h) - endif() - +set_rc_compiler() + +spec2def(d3d9.dll d3d9.spec) + +list(APPEND SOURCE + buffer.c + cubetexture.c + d3d9_main.c + device.c + directx.c + query.c + shader.c + stateblock.c + surface.c + swapchain.c + texture.c + vertexdeclaration.c + volume.c + volumetexture.c + version.rc + ${CMAKE_CURRENT_BINARY_DIR}/d3d9_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/d3d9.def) + +add_library(d3d9 SHARED ${SOURCE}) + +set_module_type(d3d9 win32dll) + +target_link_libraries(d3d9 uuid wine) + +add_importlibs(d3d9 + user32 + gdi32 + advapi32 + wined3d + msvcrt + kernel32 + ntdll) + +add_dependencies(d3d9 wineheaders) +add_cd_file(TARGET d3d9 DESTINATION reactos/system32 FOR all) +add_importlib_target(d3d9.spec) diff --cc reactos/dll/directx/wine/wined3d/state.c index a2c197bbfe0,00000000000..1db1d67cc93 mode 100644,000000..100644 --- a/reactos/dll/directx/wine/wined3d/state.c +++ b/reactos/dll/directx/wine/wined3d/state.c @@@ -1,5900 -1,0 +1,5900 @@@ +/* + * Direct3D state management + * + * Copyright 2002 Lionel Ulmer + * Copyright 2002-2005 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira + * Copyright 2004 Christian Costa + * Copyright 2005 Oliver Stieber + * Copyright 2006 Henri Verbeet + * Copyright 2006-2008 Stefan Dösinger for CodeWeavers + * Copyright 2009-2011 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include +#ifdef HAVE_FLOAT_H +# include +#endif +#include "wined3d_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); + +/* GL locking for state handlers is done by the caller. */ + +static void state_blendop(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context); + +static void state_undefined(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + ERR("Undefined state.\n"); +} + +static void state_nop(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state)); +} + +static void state_fillmode(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WINED3DFILLMODE Value = stateblock->state.render_states[WINED3DRS_FILLMODE]; + + switch(Value) { + case WINED3DFILL_POINT: + glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)"); + break; + case WINED3DFILL_WIREFRAME: + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)"); + break; + case WINED3DFILL_SOLID: + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)"); + break; + default: + FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value); + } +} + +static void state_lighting(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /* Lighting is not enabled if transformed vertices are drawn + * but lighting does not affect the stream sources, so it is not grouped for performance reasons. + * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The + * vertex declaration applying function calls this function for updating + */ + + if(isStateDirty(context, STATE_VDECL)) { + return; + } + + if (stateblock->state.render_states[WINED3DRS_LIGHTING] + && !stateblock->device->strided_streams.position_transformed) + { + glEnable(GL_LIGHTING); + checkGLcall("glEnable GL_LIGHTING"); + } else { + glDisable(GL_LIGHTING); + checkGLcall("glDisable GL_LIGHTING"); + } +} + +static void state_zenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /* No z test without depth stencil buffers */ + if (!stateblock->device->fb.depth_stencil) + { + TRACE("No Z buffer - disabling depth test\n"); + glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */ + checkGLcall("glDisable GL_DEPTH_TEST"); + return; + } + + switch (stateblock->state.render_states[WINED3DRS_ZENABLE]) + { + case WINED3DZB_FALSE: + glDisable(GL_DEPTH_TEST); + checkGLcall("glDisable GL_DEPTH_TEST"); + break; + case WINED3DZB_TRUE: + glEnable(GL_DEPTH_TEST); + checkGLcall("glEnable GL_DEPTH_TEST"); + break; + case WINED3DZB_USEW: + glEnable(GL_DEPTH_TEST); + checkGLcall("glEnable GL_DEPTH_TEST"); + FIXME("W buffer is not well handled\n"); + break; + default: + FIXME("Unrecognized D3DZBUFFERTYPE value %#x.\n", + stateblock->state.render_states[WINED3DRS_ZENABLE]); + } +} + +static void state_cullmode(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /* glFrontFace() is set in context.c at context init and on an + * offscreen / onscreen rendering switch. */ + switch (stateblock->state.render_states[WINED3DRS_CULLMODE]) + { + case WINED3DCULL_NONE: + glDisable(GL_CULL_FACE); + checkGLcall("glDisable GL_CULL_FACE"); + break; + case WINED3DCULL_CW: + glEnable(GL_CULL_FACE); + checkGLcall("glEnable GL_CULL_FACE"); + glCullFace(GL_FRONT); + checkGLcall("glCullFace(GL_FRONT)"); + break; + case WINED3DCULL_CCW: + glEnable(GL_CULL_FACE); + checkGLcall("glEnable GL_CULL_FACE"); + glCullFace(GL_BACK); + checkGLcall("glCullFace(GL_BACK)"); + break; + default: + FIXME("Unrecognized/Unhandled WINED3DCULL value %#x.\n", + stateblock->state.render_states[WINED3DRS_CULLMODE]); + } +} + +static void state_shademode(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + switch (stateblock->state.render_states[WINED3DRS_SHADEMODE]) + { + case WINED3DSHADE_FLAT: + glShadeModel(GL_FLAT); + checkGLcall("glShadeModel(GL_FLAT)"); + break; + case WINED3DSHADE_GOURAUD: + glShadeModel(GL_SMOOTH); + checkGLcall("glShadeModel(GL_SMOOTH)"); + break; + case WINED3DSHADE_PHONG: + FIXME("WINED3DSHADE_PHONG isn't supported\n"); + break; + default: + FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %#x.\n", + stateblock->state.render_states[WINED3DRS_SHADEMODE]); + } +} + +static void state_ditherenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_DITHERENABLE]) + { + glEnable(GL_DITHER); + checkGLcall("glEnable GL_DITHER"); + } + else + { + glDisable(GL_DITHER); + checkGLcall("glDisable GL_DITHER"); + } +} + +static void state_zwritenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. + * If yes, this has to be merged with ZENABLE and ZFUNC. */ + if (stateblock->state.render_states[WINED3DRS_ZWRITEENABLE]) + { + glDepthMask(1); + checkGLcall("glDepthMask(1)"); + } + else + { + glDepthMask(0); + checkGLcall("glDepthMask(0)"); + } +} + +static void state_zfunc(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + GLenum depth_func = CompareFunc(stateblock->state.render_states[WINED3DRS_ZFUNC]); + + if (!depth_func) return; + + if (depth_func == GL_EQUAL || depth_func == GL_NOTEQUAL) + { + static BOOL once; + /* There are a few issues with this: First, our inability to + * select a proper Z depth, most of the time we're stuck with + * D24S8, even if the app selects D32 or D16. There seem to be + * some other precision problems which have to be debugged to + * make NOTEQUAL and EQUAL work properly. */ + if (!once) + { + once = TRUE; + FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet.\n"); + } + } + + glDepthFunc(depth_func); + checkGLcall("glDepthFunc"); +} + +static void state_ambient(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + float col[4]; + D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_AMBIENT], col); + + TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col); + checkGLcall("glLightModel for MODEL_AMBIENT"); +} + +static GLenum gl_blend_factor(WINED3DBLEND factor, const struct wined3d_format *dst_format) +{ + switch (factor) + { + case WINED3DBLEND_ZERO: + return GL_ZERO; + case WINED3DBLEND_ONE: + return GL_ONE; + case WINED3DBLEND_SRCCOLOR: + return GL_SRC_COLOR; + case WINED3DBLEND_INVSRCCOLOR: + return GL_ONE_MINUS_SRC_COLOR; + case WINED3DBLEND_SRCALPHA: + return GL_SRC_ALPHA; + case WINED3DBLEND_INVSRCALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case WINED3DBLEND_DESTCOLOR: + return GL_DST_COLOR; + case WINED3DBLEND_INVDESTCOLOR: + return GL_ONE_MINUS_DST_COLOR; + /* To compensate for the lack of format switching with backbuffer + * offscreen rendering, and with onscreen rendering, we modify the + * alpha test parameters for (INV)DESTALPHA if the render target + * doesn't support alpha blending. A nonexistent alpha channel + * returns 1.0, so WINED3DBLEND_DESTALPHA becomes GL_ONE, and + * WINED3DBLEND_INVDESTALPHA becomes GL_ZERO. */ + case WINED3DBLEND_DESTALPHA: + return dst_format->alpha_mask ? GL_DST_ALPHA : GL_ONE; + case WINED3DBLEND_INVDESTALPHA: + return dst_format->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO; + case WINED3DBLEND_SRCALPHASAT: + return GL_SRC_ALPHA_SATURATE; + case WINED3DBLEND_BLENDFACTOR: + return GL_CONSTANT_COLOR_EXT; + case WINED3DBLEND_INVBLENDFACTOR: + return GL_ONE_MINUS_CONSTANT_COLOR_EXT; + default: + FIXME("Unhandled blend factor %#x.\n", factor); + return GL_NONE; + } +} + +static void state_blend(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + struct wined3d_surface *target = stateblock->device->fb.render_targets[0]; + const struct wined3d_gl_info *gl_info = context->gl_info; + GLenum srcBlend, dstBlend; + WINED3DBLEND d3d_blend; + + /* According to the red book, GL_LINE_SMOOTH needs GL_BLEND with specific + * blending parameters to work. */ + if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE] + || stateblock->state.render_states[WINED3DRS_EDGEANTIALIAS] + || stateblock->state.render_states[WINED3DRS_ANTIALIASEDLINEENABLE]) + { + /* Disable blending in all cases even without pixelshaders. + * With blending on we could face a big performance penalty. + * The d3d9 visual test confirms the behavior. */ + if (context->render_offscreen + && !(target->resource.format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)) + { + glDisable(GL_BLEND); + checkGLcall("glDisable GL_BLEND"); + return; + } else { + glEnable(GL_BLEND); + checkGLcall("glEnable GL_BLEND"); + } + } else { + glDisable(GL_BLEND); + checkGLcall("glDisable GL_BLEND"); + /* Nothing more to do - get out */ + return; + }; + + /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy + * source blending values which are still valid up to d3d9. They should + * not occur as dest blend values. */ + d3d_blend = stateblock->state.render_states[WINED3DRS_SRCBLEND]; + if (d3d_blend == WINED3DBLEND_BOTHSRCALPHA) + { + srcBlend = GL_SRC_ALPHA; + dstBlend = GL_ONE_MINUS_SRC_ALPHA; + } + else if (d3d_blend == WINED3DBLEND_BOTHINVSRCALPHA) + { + srcBlend = GL_ONE_MINUS_SRC_ALPHA; + dstBlend = GL_SRC_ALPHA; + } + else + { + srcBlend = gl_blend_factor(d3d_blend, target->resource.format); + dstBlend = gl_blend_factor(stateblock->state.render_states[WINED3DRS_DESTBLEND], + target->resource.format); + } + + if (stateblock->state.render_states[WINED3DRS_EDGEANTIALIAS] + || stateblock->state.render_states[WINED3DRS_ANTIALIASEDLINEENABLE]) + { + glEnable(GL_LINE_SMOOTH); + checkGLcall("glEnable(GL_LINE_SMOOTH)"); + if(srcBlend != GL_SRC_ALPHA) { + WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n"); + } + if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) { + WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n"); + } + } else { + glDisable(GL_LINE_SMOOTH); + checkGLcall("glDisable(GL_LINE_SMOOTH)"); + } + + /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */ + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) { + state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context); + } + + if (stateblock->state.render_states[WINED3DRS_SEPARATEALPHABLENDENABLE]) + { + GLenum srcBlendAlpha, dstBlendAlpha; + + /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */ + if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE]) + { + WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n"); + return; + } + + /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy + * source blending values which are still valid up to d3d9. They should + * not occur as dest blend values. */ + d3d_blend = stateblock->state.render_states[WINED3DRS_SRCBLENDALPHA]; + if (d3d_blend == WINED3DBLEND_BOTHSRCALPHA) + { + srcBlendAlpha = GL_SRC_ALPHA; + dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + } + else if (d3d_blend == WINED3DBLEND_BOTHINVSRCALPHA) + { + srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA; + dstBlendAlpha = GL_SRC_ALPHA; + } + else + { + srcBlendAlpha = gl_blend_factor(d3d_blend, target->resource.format); + dstBlendAlpha = gl_blend_factor(stateblock->state.render_states[WINED3DRS_DESTBLENDALPHA], + target->resource.format); + } + + GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha)); + checkGLcall("glBlendFuncSeparateEXT"); + } else { + TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend); + glBlendFunc(srcBlend, dstBlend); + checkGLcall("glBlendFunc"); + } + + /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state, + so it may need updating */ + if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE]) + stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); +} + +static void state_blendfactor_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n"); +} + +static void state_blendfactor(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + float col[4]; + + TRACE("Setting blend factor to %#x.\n", stateblock->state.render_states[WINED3DRS_BLENDFACTOR]); + D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_BLENDFACTOR], col); + GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3])); + checkGLcall("glBlendColor"); +} + +static void state_alpha(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + int glParm = 0; + float ref; + BOOL enable_ckey = FALSE; + + TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); + + /* Find out if the texture on the first stage has a ckey set + * The alpha state func reads the texture settings, even though alpha and texture are not grouped + * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly + * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha + * in case it finds some texture+colorkeyenable combination which needs extra care. + */ + if (stateblock->state.textures[0]) + { + struct wined3d_texture *texture = stateblock->state.textures[0]; + GLenum texture_dimensions = texture->target; + + if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) + { + struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]); + + if (surf->CKeyFlags & WINEDDSD_CKSRCBLT) + { + /* The surface conversion does not do color keying conversion for surfaces that have an alpha + * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the + * surface has alpha bits */ + if (!surf->resource.format->alpha_mask) enable_ckey = TRUE; + } + } + } + + if (enable_ckey || context->last_was_ckey) + stateblock_apply_state(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context); + context->last_was_ckey = enable_ckey; + + if (stateblock->state.render_states[WINED3DRS_ALPHATESTENABLE] + || (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && enable_ckey)) + { + glEnable(GL_ALPHA_TEST); + checkGLcall("glEnable GL_ALPHA_TEST"); + } else { + glDisable(GL_ALPHA_TEST); + checkGLcall("glDisable GL_ALPHA_TEST"); + /* Alpha test is disabled, don't bother setting the params - it will happen on the next + * enable call + */ + return; + } + + if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && enable_ckey) + { + glParm = GL_NOTEQUAL; + ref = 0.0f; + } else { + ref = ((float)stateblock->state.render_states[WINED3DRS_ALPHAREF]) / 255.0f; + glParm = CompareFunc(stateblock->state.render_states[WINED3DRS_ALPHAFUNC]); + } + if(glParm) { + glAlphaFunc(glParm, ref); + checkGLcall("glAlphaFunc"); + } +} + +static void state_clipping(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + DWORD enable = 0xFFFFFFFF; + DWORD disable = 0x00000000; + + if (!stateblock->device->vs_clipping && use_vs(state)) + { + /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't, + * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some + * conditions I got sick of tracking down. The shader state handler disables all clip planes because + * of that - don't do anything here and keep them disabled + */ + if (state->render_states[WINED3DRS_CLIPPLANEENABLE]) + { + static BOOL warned = FALSE; + if(!warned) { + FIXME("Clipping not supported with vertex shaders\n"); + warned = TRUE; + } + } + return; + } + + /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting + * of already set values + */ + + /* If enabling / disabling all + * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum? + */ + if (state->render_states[WINED3DRS_CLIPPING]) + { + enable = state->render_states[WINED3DRS_CLIPPLANEENABLE]; + disable = ~state->render_states[WINED3DRS_CLIPPLANEENABLE]; + if (gl_info->supported[ARB_DEPTH_CLAMP]) + { + glDisable(GL_DEPTH_CLAMP); + checkGLcall("glDisable(GL_DEPTH_CLAMP)"); + } + } else { + disable = 0xffffffff; + enable = 0x00; + if (gl_info->supported[ARB_DEPTH_CLAMP]) + { + glEnable(GL_DEPTH_CLAMP); + checkGLcall("glEnable(GL_DEPTH_CLAMP)"); + } + else + { + FIXME("Clipping disabled, but ARB_depth_clamp isn't supported.\n"); + } + } + + if (enable & WINED3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); } + if (enable & WINED3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); } + if (enable & WINED3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); } + if (enable & WINED3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); } + if (enable & WINED3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); } + if (enable & WINED3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); } + + if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); } + if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); } + if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); } + if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); } + if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); } + if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); } + + /** update clipping status */ + if (enable) + { + stateblock->state.clip_status.ClipUnion = 0; + stateblock->state.clip_status.ClipIntersection = 0xFFFFFFFF; + } + else + { + stateblock->state.clip_status.ClipUnion = 0; + stateblock->state.clip_status.ClipIntersection = 0; + } +} + +static void state_blendop_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WARN("Unsupported in local OpenGL implementation: glBlendEquation\n"); +} + +static GLenum gl_blend_op(WINED3DBLENDOP op) +{ + switch (op) + { + case WINED3DBLENDOP_ADD: + return GL_FUNC_ADD_EXT; + case WINED3DBLENDOP_SUBTRACT: + return GL_FUNC_SUBTRACT_EXT; + case WINED3DBLENDOP_REVSUBTRACT: + return GL_FUNC_REVERSE_SUBTRACT_EXT; + case WINED3DBLENDOP_MIN: + return GL_MIN_EXT; + case WINED3DBLENDOP_MAX: + return GL_MAX_EXT; + default: + FIXME("Unhandled blend op %#x.\n", op); + return GL_NONE; + } +} + +static void state_blendop(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + int blendEquation = GL_FUNC_ADD_EXT; + int blendEquationAlpha = GL_FUNC_ADD_EXT; + + /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */ + if (stateblock->state.render_states[WINED3DRS_BLENDOPALPHA] + && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE]) + { + WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n"); + return; + } + + blendEquation = gl_blend_op(stateblock->state.render_states[WINED3DRS_BLENDOP]); + blendEquationAlpha = gl_blend_op(stateblock->state.render_states[WINED3DRS_BLENDOPALPHA]); + + if (stateblock->state.render_states[WINED3DRS_SEPARATEALPHABLENDENABLE]) + { + TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha); + GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha)); + checkGLcall("glBlendEquationSeparateEXT"); + } else { + TRACE("glBlendEquation(%x)\n", blendEquation); + GL_EXTCALL(glBlendEquationEXT(blendEquation)); + checkGLcall("glBlendEquation"); + } +} + +static void state_specularenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR) + * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled + * specular color. This is wrong: + * Separate specular color means the specular colour is maintained separately, whereas + * single color means it is merged in. However in both cases they are being used to + * some extent. + * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT + * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are + * running 1.4 yet! + * + * + * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect. + * Instead, we need to setup the FinalCombiner properly. + * + * The default setup for the FinalCombiner is: + * + * + * GL_VARIABLE_A_NV GL_FOG, GL_UNSIGNED_IDENTITY_NV GL_ALPHA + * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV GL_UNSIGNED_IDENTITY_NV GL_RGB + * GL_VARIABLE_C_NV GL_FOG GL_UNSIGNED_IDENTITY_NV GL_RGB + * GL_VARIABLE_D_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB + * GL_VARIABLE_E_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB + * GL_VARIABLE_F_NV GL_ZERO GL_UNSIGNED_IDENTITY_NV GL_RGB + * GL_VARIABLE_G_NV GL_SPARE0_NV GL_UNSIGNED_IDENTITY_NV GL_ALPHA + * + * That's pretty much fine as it is, except for variable B, which needs to take + * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on + * whether WINED3DRS_SPECULARENABLE is enabled or not. + */ + + TRACE("Setting specular enable state and materials\n"); + if (stateblock->state.render_states[WINED3DRS_SPECULARENABLE]) + { + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&stateblock->state.material.Specular); + checkGLcall("glMaterialfv"); + + if (stateblock->state.material.Power > gl_info->limits.shininess) + { + /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0 + * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent + * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the + * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp + * them, it should be safe to do so without major visual distortions. + */ + WARN("Material power = %f, limit %f\n", stateblock->state.material.Power, gl_info->limits.shininess); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess); + } + else + { + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->state.material.Power); + } + checkGLcall("glMaterialf(GL_SHININESS)"); + + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + glEnable(GL_COLOR_SUM_EXT); + } + else + { + TRACE("Specular colors cannot be enabled in this version of opengl\n"); + } + checkGLcall("glEnable(GL_COLOR_SUM)"); + + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB)); + checkGLcall("glFinalCombinerInputNV()"); + } + } else { + static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* for the case of enabled lighting: */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]); + checkGLcall("glMaterialfv"); + + /* for the case of disabled lighting: */ + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + glDisable(GL_COLOR_SUM_EXT); + } + else + { + TRACE("Specular colors cannot be disabled in this version of opengl\n"); + } + checkGLcall("glDisable(GL_COLOR_SUM)"); + + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB)); + checkGLcall("glFinalCombinerInputNV()"); + } + } + + TRACE("(%p) : Diffuse {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device, + stateblock->state.material.Diffuse.r, stateblock->state.material.Diffuse.g, + stateblock->state.material.Diffuse.b, stateblock->state.material.Diffuse.a); + TRACE("(%p) : Ambient {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device, + stateblock->state.material.Ambient.r, stateblock->state.material.Ambient.g, + stateblock->state.material.Ambient.b, stateblock->state.material.Ambient.a); + TRACE("(%p) : Specular {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device, + stateblock->state.material.Specular.r, stateblock->state.material.Specular.g, + stateblock->state.material.Specular.b, stateblock->state.material.Specular.a); + TRACE("(%p) : Emissive {%.8e, %.8e, %.8e, %.8e}\n", stateblock->device, + stateblock->state.material.Emissive.r, stateblock->state.material.Emissive.g, + stateblock->state.material.Emissive.b, stateblock->state.material.Emissive.a); + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&stateblock->state.material.Ambient); + checkGLcall("glMaterialfv(GL_AMBIENT)"); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&stateblock->state.material.Diffuse); + checkGLcall("glMaterialfv(GL_DIFFUSE)"); + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&stateblock->state.material.Emissive); + checkGLcall("glMaterialfv(GL_EMISSION)"); +} + +static void state_texfactor(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int i; + + /* Note the texture color applies to all textures whereas + * GL_TEXTURE_ENV_COLOR applies to active only + */ + float col[4]; + D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_TEXTUREFACTOR], col); + + /* And now the default texture color as well */ + for (i = 0; i < gl_info->limits.texture_stages; ++i) + { + /* Note the WINED3DRS value applies to all textures, but GL has one + * per texture, so apply it now ready to be used! + */ + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i)); + checkGLcall("glActiveTextureARB"); + + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]); + checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);"); + } +} + +static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face, + GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); + checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); + GL_EXTCALL(glActiveStencilFaceEXT(face)); + checkGLcall("glActiveStencilFaceEXT(...)"); + glStencilFunc(func, ref, mask); + checkGLcall("glStencilFunc(...)"); + glStencilOp(stencilFail, depthFail, stencilPass); + checkGLcall("glStencilOp(...)"); +} + +static void state_stencil(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + DWORD onesided_enable = FALSE; + DWORD twosided_enable = FALSE; + GLint func = GL_ALWAYS; + GLint func_ccw = GL_ALWAYS; + GLint ref = 0; + GLuint mask = 0; + GLint stencilFail = GL_KEEP; + GLint depthFail = GL_KEEP; + GLint stencilPass = GL_KEEP; + GLint stencilFail_ccw = GL_KEEP; + GLint depthFail_ccw = GL_KEEP; + GLint stencilPass_ccw = GL_KEEP; + + /* No stencil test without a stencil buffer. */ + if (!stateblock->device->fb.depth_stencil) + { + glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable GL_STENCIL_TEST"); + return; + } + + onesided_enable = stateblock->state.render_states[WINED3DRS_STENCILENABLE]; + twosided_enable = stateblock->state.render_states[WINED3DRS_TWOSIDEDSTENCILMODE]; + if (!(func = CompareFunc(stateblock->state.render_states[WINED3DRS_STENCILFUNC]))) + func = GL_ALWAYS; + if (!(func_ccw = CompareFunc(stateblock->state.render_states[WINED3DRS_CCW_STENCILFUNC]))) + func_ccw = GL_ALWAYS; + ref = stateblock->state.render_states[WINED3DRS_STENCILREF]; + mask = stateblock->state.render_states[WINED3DRS_STENCILMASK]; + stencilFail = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILFAIL]); + depthFail = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILZFAIL]); + stencilPass = StencilOp(stateblock->state.render_states[WINED3DRS_STENCILPASS]); + stencilFail_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILFAIL]); + depthFail_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILZFAIL]); + stencilPass_ccw = StencilOp(stateblock->state.render_states[WINED3DRS_CCW_STENCILPASS]); + + TRACE("(onesided %d, twosided %d, ref %x, mask %x, " + "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x " + "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n", + onesided_enable, twosided_enable, ref, mask, + func, stencilFail, depthFail, stencilPass, + func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw); + + if (twosided_enable && onesided_enable) { + glEnable(GL_STENCIL_TEST); + checkGLcall("glEnable GL_STENCIL_TEST"); + + if (gl_info->supported[EXT_STENCIL_TWO_SIDE]) + { + /* Apply back first, then front. This function calls glActiveStencilFaceEXT, + * which has an effect on the code below too. If we apply the front face + * afterwards, we are sure that the active stencil face is set to front, + * and other stencil functions which do not use two sided stencil do not have + * to set it back + */ + renderstate_stencil_twosided(context, GL_BACK, + func_ccw, ref, mask, stencilFail_ccw, depthFail_ccw, stencilPass_ccw); + renderstate_stencil_twosided(context, GL_FRONT, + func, ref, mask, stencilFail, depthFail, stencilPass); + } + else if (gl_info->supported[ATI_SEPARATE_STENCIL]) + { + GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask)); + checkGLcall("glStencilFuncSeparateATI(...)"); + GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass)); + checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)"); + GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw)); + checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)"); + } else { + ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n"); + } + } + else if(onesided_enable) + { + if (gl_info->supported[EXT_STENCIL_TWO_SIDE]) + { + glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); + checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)"); + } + + /* This code disables the ATI extension as well, since the standard stencil functions are equal + * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter + */ + glEnable(GL_STENCIL_TEST); + checkGLcall("glEnable GL_STENCIL_TEST"); + glStencilFunc(func, ref, mask); + checkGLcall("glStencilFunc(...)"); + glStencilOp(stencilFail, depthFail, stencilPass); + checkGLcall("glStencilOp(...)"); + } else { + glDisable(GL_STENCIL_TEST); + checkGLcall("glDisable GL_STENCIL_TEST"); + } +} + +static void state_stencilwrite2s(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD mask = stateblock->device->fb.depth_stencil ? stateblock->state.render_states[WINED3DRS_STENCILWRITEMASK] : 0; + const struct wined3d_gl_info *gl_info = context->gl_info; + + GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK)); + checkGLcall("glActiveStencilFaceEXT(GL_BACK)"); + glStencilMask(mask); + checkGLcall("glStencilMask"); + GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT)); + checkGLcall("glActiveStencilFaceEXT(GL_FRONT)"); + glStencilMask(mask); +} + +static void state_stencilwrite(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD mask = stateblock->device->fb.depth_stencil ? stateblock->state.render_states[WINED3DRS_STENCILWRITEMASK] : 0; + + glStencilMask(mask); + checkGLcall("glStencilMask"); +} + +static void state_fog_vertexpart(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + + TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); + + if (!stateblock->state.render_states[WINED3DRS_FOGENABLE]) return; + + /* Table fog on: Never use fog coords, and use per-fragment fog */ + if (stateblock->state.render_states[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) + { + glHint(GL_FOG_HINT, GL_NICEST); + if(context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); + context->fog_coord = FALSE; + } + return; + } + + /* Otherwise use per-vertex fog in any case */ + glHint(GL_FOG_HINT, GL_FASTEST); + + if (stateblock->state.render_states[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) + { + /* No fog at all, or transformed vertices: Use fog coord */ + if(!context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)"); + context->fog_coord = TRUE; + } + } else { + /* Otherwise, use the fragment depth */ + if(context->fog_coord) { + glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); + checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)"); + context->fog_coord = FALSE; + } + } +} + +void state_fogstartend(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + float fogstart, fogend; + union { + DWORD d; + float f; + } tmpvalue; + + switch(context->fog_source) { + case FOGSOURCE_VS: + fogstart = 1.0f; + fogend = 0.0f; + break; + + case FOGSOURCE_COORD: + fogstart = 255.0f; + fogend = 0.0f; + break; + + case FOGSOURCE_FFP: + tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGSTART]; + fogstart = tmpvalue.f; + tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGEND]; + fogend = tmpvalue.f; + /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/ + if(fogstart == fogend) { - fogstart = -1.0f / 0.0f; ++ fogstart = -1.0f * INFINITY; + fogend = 0.0f; + } + break; + + default: + /* This should not happen.context->fog_source is set in wined3d, not the app. + * Still this is needed to make the compiler happy + */ + ERR("Unexpected fog coordinate source\n"); + fogstart = 0.0f; + fogend = 0.0f; + } + + glFogf(GL_FOG_START, fogstart); + checkGLcall("glFogf(GL_FOG_START, fogstart)"); + TRACE("Fog Start == %f\n", fogstart); + + glFogf(GL_FOG_END, fogend); + checkGLcall("glFogf(GL_FOG_END, fogend)"); + TRACE("Fog End == %f\n", fogend); +} + +void state_fog_fragpart(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_state *state = &stateblock->state; + enum fogsource new_source; + + TRACE("state_id %#x, stateblock %p, context %p\n", state_id, stateblock, context); + + if (!state->render_states[WINED3DRS_FOGENABLE]) + { + /* No fog? Disable it, and we're done :-) */ + glDisableWINE(GL_FOG); + checkGLcall("glDisable GL_FOG"); + return; + } + + /* Fog Rules: + * + * With fixed function vertex processing, Direct3D knows 2 different fog input sources. + * It can use the Z value of the vertex, or the alpha component of the specular color. + * This depends on the fog vertex, fog table and the vertex declaration. If the Z value + * is used, fogstart, fogend and the equation type are used, otherwise linear fog with + * start = 255, end = 0 is used. Obviously the msdn is not very clear on that. + * + * FOGTABLEMODE != NONE: + * The Z value is used, with the equation specified, no matter what vertex type. + * + * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed: + * Per vertex fog is calculated using the specified fog equation and the parameters + * + * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR + * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed: + * Linear fog with start = 255.0, end = 0.0, input comes from the specular color + * + * + * Rules for vertex fog with shaders: + * + * When mixing fixed function functionality with the programmable pipeline, D3D expects + * the fog computation to happen during transformation while openGL expects it to happen + * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after + * the pixel shader while openGL always expects the pixel shader to handle the blending. + * To solve this problem, WineD3D does: + * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel + * shader, + * and 2) disables the fog computation (in either the fixed function or programmable + * rasterizer) if using a vertex program. + * + * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with + * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear + * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in + * the specular color, a vertex shader counts as pretransformed geometry in this case. + * There are some GL differences between specular fog coords and vertex shaders though. + * + * With table fog the vertex shader fog coordinate is ignored. + * + * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or + * without shaders). + */ + + /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes, + * the system will apply only pixel(=table) fog effects." + */ + if (state->render_states[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) + { + if (use_vs(state)) + { + glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); + new_source = FOGSOURCE_VS; + } + else + { + switch (state->render_states[WINED3DRS_FOGVERTEXMODE]) + { + /* If processed vertices are used, fall through to the NONE case */ + case WINED3DFOG_EXP: + if(!context->last_was_rhw) { + glFogi(GL_FOG_MODE, GL_EXP); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); + new_source = FOGSOURCE_FFP; + break; + } + /* drop through */ + + case WINED3DFOG_EXP2: + if(!context->last_was_rhw) { + glFogi(GL_FOG_MODE, GL_EXP2); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); + new_source = FOGSOURCE_FFP; + break; + } + /* drop through */ + + case WINED3DFOG_LINEAR: + if(!context->last_was_rhw) { + glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); + new_source = FOGSOURCE_FFP; + break; + } + /* drop through */ + + case WINED3DFOG_NONE: + /* Both are none? According to msdn the alpha channel of the specular + * color contains a fog factor. Set it in drawStridedSlow. + * Same happens with Vertexfog on transformed vertices + */ + new_source = FOGSOURCE_COORD; + glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); + break; + + default: + FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %#x.\n", + state->render_states[WINED3DRS_FOGVERTEXMODE]); + new_source = FOGSOURCE_FFP; /* Make the compiler happy */ + } + } + } else { + new_source = FOGSOURCE_FFP; + + switch (state->render_states[WINED3DRS_FOGTABLEMODE]) + { + case WINED3DFOG_EXP: + glFogi(GL_FOG_MODE, GL_EXP); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)"); + break; + + case WINED3DFOG_EXP2: + glFogi(GL_FOG_MODE, GL_EXP2); + checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)"); + break; + + case WINED3DFOG_LINEAR: + glFogi(GL_FOG_MODE, GL_LINEAR); + checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)"); + break; + + case WINED3DFOG_NONE: /* Won't happen */ + default: + FIXME("Unexpected WINED3DRS_FOGTABLEMODE %#x.\n", + state->render_states[WINED3DRS_FOGTABLEMODE]); + } + } + + glEnableWINE(GL_FOG); + checkGLcall("glEnable GL_FOG"); + if(new_source != context->fog_source) { + context->fog_source = new_source; + state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context); + } +} + +static void state_rangefog_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_RANGEFOGENABLE]) + WARN("Range fog enabled, but not supported by this opengl implementation\n"); +} + +static void state_rangefog(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_RANGEFOGENABLE]) + { + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV); + checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)"); + } else { + glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV); + checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)"); + } +} + +void state_fogcolor(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + float col[4]; + D3DCOLORTOGLFLOAT4(stateblock->state.render_states[WINED3DRS_FOGCOLOR], col); + glFogfv(GL_FOG_COLOR, &col[0]); + checkGLcall("glFog GL_FOG_COLOR"); +} + +void state_fogdensity(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + union { + DWORD d; + float f; + } tmpvalue; + tmpvalue.d = stateblock->state.render_states[WINED3DRS_FOGDENSITY]; + glFogfv(GL_FOG_DENSITY, &tmpvalue.f); + checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)"); +} + +static void state_colormat(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_state *state = &stateblock->state; + struct wined3d_device *device = stateblock->device; + GLenum Parm = 0; + + /* Depends on the decoded vertex declaration to read the existence of diffuse data. + * The vertex declaration will call this function if the fixed function pipeline is used. + */ + + if(isStateDirty(context, STATE_VDECL)) { + return; + } + + context->num_untracked_materials = 0; + if ((device->strided_streams.use_map & (1 << WINED3D_FFP_DIFFUSE)) + && state->render_states[WINED3DRS_COLORVERTEX]) + { + TRACE("diff %d, amb %d, emis %d, spec %d\n", + state->render_states[WINED3DRS_DIFFUSEMATERIALSOURCE], + state->render_states[WINED3DRS_AMBIENTMATERIALSOURCE], + state->render_states[WINED3DRS_EMISSIVEMATERIALSOURCE], + state->render_states[WINED3DRS_SPECULARMATERIALSOURCE]); + + if (state->render_states[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + if (state->render_states[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) + Parm = GL_AMBIENT_AND_DIFFUSE; + else + Parm = GL_DIFFUSE; + if (state->render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + context->untracked_materials[context->num_untracked_materials] = GL_EMISSION; + context->num_untracked_materials++; + } + if (state->render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR; + context->num_untracked_materials++; + } + } + else if (state->render_states[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + Parm = GL_AMBIENT; + if (state->render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + context->untracked_materials[context->num_untracked_materials] = GL_EMISSION; + context->num_untracked_materials++; + } + if (state->render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR; + context->num_untracked_materials++; + } + } + else if (state->render_states[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + Parm = GL_EMISSION; + if (state->render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR; + context->num_untracked_materials++; + } + } + else if (state->render_states[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) + { + Parm = GL_SPECULAR; + } + } + + /* Nothing changed, return. */ + if (Parm == context->tracking_parm) return; + + if(!Parm) { + glDisable(GL_COLOR_MATERIAL); + checkGLcall("glDisable GL_COLOR_MATERIAL"); + } else { + glColorMaterial(GL_FRONT_AND_BACK, Parm); + checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)"); + glEnable(GL_COLOR_MATERIAL); + checkGLcall("glEnable(GL_COLOR_MATERIAL)"); + } + + /* Apparently calls to glMaterialfv are ignored for properties we're + * tracking with glColorMaterial, so apply those here. */ + switch (context->tracking_parm) { + case GL_AMBIENT_AND_DIFFUSE: + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.Ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.Diffuse); + checkGLcall("glMaterialfv"); + break; + + case GL_DIFFUSE: + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.Diffuse); + checkGLcall("glMaterialfv"); + break; + + case GL_AMBIENT: + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.Ambient); + checkGLcall("glMaterialfv"); + break; + + case GL_EMISSION: + glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.Emissive); + checkGLcall("glMaterialfv"); + break; + + case GL_SPECULAR: + /* Only change material color if specular is enabled, otherwise it is set to black */ + if (state->render_states[WINED3DRS_SPECULARENABLE]) + { + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.Specular); + checkGLcall("glMaterialfv"); + } else { + static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]); + checkGLcall("glMaterialfv"); + } + break; + } + + context->tracking_parm = Parm; +} + +static void state_linepattern(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + union { + DWORD d; + WINED3DLINEPATTERN lp; + } tmppattern; + tmppattern.d = stateblock->state.render_states[WINED3DRS_LINEPATTERN]; + + TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern); + + if (tmppattern.lp.wRepeatFactor) { + glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern); + checkGLcall("glLineStipple(repeat, linepattern)"); + glEnable(GL_LINE_STIPPLE); + checkGLcall("glEnable(GL_LINE_STIPPLE);"); + } else { + glDisable(GL_LINE_STIPPLE); + checkGLcall("glDisable(GL_LINE_STIPPLE);"); + } +} + +static void state_normalize(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if(isStateDirty(context, STATE_VDECL)) { + return; + } + /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor + * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division + * by zero and is not properly defined in opengl, so avoid it + */ + if (stateblock->state.render_states[WINED3DRS_NORMALIZENORMALS] + && (stateblock->device->strided_streams.use_map & (1 << WINED3D_FFP_NORMAL))) + { + glEnable(GL_NORMALIZE); + checkGLcall("glEnable(GL_NORMALIZE);"); + } else { + glDisable(GL_NORMALIZE); + checkGLcall("glDisable(GL_NORMALIZE);"); + } +} + +static void state_psizemin_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + union { + DWORD d; + float f; + } tmpvalue; + + tmpvalue.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN]; + if (tmpvalue.f != 1.0f) + { + FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f); + } + tmpvalue.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX]; + if (tmpvalue.f != 64.0f) + { + FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f); + } + +} + +static void state_psizemin_ext(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + union + { + DWORD d; + float f; + } min, max; + + min.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN]; + max.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX]; + + /* Max point size trumps min point size */ + if(min.f > max.f) { + min.f = max.f; + } + + GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f); + checkGLcall("glPointParameterfEXT(...)"); + GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f); + checkGLcall("glPointParameterfEXT(...)"); +} + +static void state_psizemin_arb(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + union + { + DWORD d; + float f; + } min, max; + + min.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MIN]; + max.d = stateblock->state.render_states[WINED3DRS_POINTSIZE_MAX]; + + /* Max point size trumps min point size */ + if(min.f > max.f) { + min.f = max.f; + } + + GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f); + checkGLcall("glPointParameterfARB(...)"); + GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f); + checkGLcall("glPointParameterfARB(...)"); +} + +static void state_pscale(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + /* TODO: Group this with the viewport */ + /* + * POINTSCALEENABLE controls how point size value is treated. If set to + * true, the point size is scaled with respect to height of viewport. + * When set to false point size is in pixels. + */ + + /* Default values */ + GLfloat att[3] = {1.0f, 0.0f, 0.0f}; + union { + DWORD d; + float f; + } pointSize, A, B, C; + + pointSize.d = stateblock->state.render_states[WINED3DRS_POINTSIZE]; + A.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_A]; + B.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_B]; + C.d = stateblock->state.render_states[WINED3DRS_POINTSCALE_C]; + + if (stateblock->state.render_states[WINED3DRS_POINTSCALEENABLE]) + { + GLfloat scaleFactor; + DWORD h = stateblock->state.viewport.Height; + + if (pointSize.f < gl_info->limits.pointsize_min) + { + /* Minimum valid point size for OpenGL is driver specific. For Direct3D it is + * 0.0f. This means that OpenGL will clamp really small point sizes to the + * driver minimum. To correct for this we need to multiply by the scale factor when sizes + * are less than 1.0f. scale_factor = 1.0f / point_size. + */ + scaleFactor = pointSize.f / gl_info->limits.pointsize_min; + /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size + * is 1.0, but then accepts points below that and draws too small points + */ + pointSize.f = gl_info->limits.pointsize_min; + } + else if(pointSize.f > gl_info->limits.pointsize_max) + { + /* gl already scales the input to glPointSize, + * d3d scales the result after the point size scale. + * If the point size is bigger than the max size, use the + * scaling to scale it bigger, and set the gl point size to max + */ + scaleFactor = pointSize.f / gl_info->limits.pointsize_max; + TRACE("scale: %f\n", scaleFactor); + pointSize.f = gl_info->limits.pointsize_max; + } else { + scaleFactor = 1.0f; + } + scaleFactor = powf(h * scaleFactor, 2); + + att[0] = A.f / scaleFactor; + att[1] = B.f / scaleFactor; + att[2] = C.f / scaleFactor; + } + + if (gl_info->supported[ARB_POINT_PARAMETERS]) + { + GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att); + checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)"); + } + else if (gl_info->supported[EXT_POINT_PARAMETERS]) + { + GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att); + checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)"); + } + else if(stateblock->state.render_states[WINED3DRS_POINTSCALEENABLE]) + { + WARN("POINT_PARAMETERS not supported in this version of opengl\n"); + } + + glPointSize(pointSize.f); + checkGLcall("glPointSize(...);"); +} + +static void state_debug_monitor(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WARN("token: %#x\n", stateblock->state.render_states[WINED3DRS_DEBUGMONITORTOKEN]); +} + +static void state_colorwrite(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD mask0 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE]; + DWORD mask1 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE1]; + DWORD mask2 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE2]; + DWORD mask3 = stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE3]; + + TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n", + mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0, + mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0); + glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, + mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE); + checkGLcall("glColorMask(...)"); + + if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0) + || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf))) + { + FIXME("WINED3DRS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n", + mask0, mask1, mask2, mask3); + FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n"); + } +} + +static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask) +{ + GL_EXTCALL(glColorMaskIndexedEXT(index, + mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE, + mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE)); +} + +static void state_colorwrite0(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 0, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE]); +} + +static void state_colorwrite1(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 1, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE1]); +} + +static void state_colorwrite2(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 2, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE2]); +} + +static void state_colorwrite3(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + set_color_mask(context->gl_info, 3, stateblock->state.render_states[WINED3DRS_COLORWRITEENABLE3]); +} + +static void state_localviewer(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_LOCALVIEWER]) + { + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)"); + } else { + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0); + checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)"); + } +} + +static void state_lastpixel(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_LASTPIXEL]) + { + TRACE("Last Pixel Drawing Enabled\n"); + } else { + static BOOL warned; + if (!warned) { + FIXME("Last Pixel Drawing Disabled, not handled yet\n"); + warned = TRUE; + } else { + TRACE("Last Pixel Drawing Disabled, not handled yet\n"); + } + } +} + +static void state_pointsprite_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + static BOOL warned; + + /* TODO: NV_POINT_SPRITE */ + if (!warned && stateblock->state.render_states[WINED3DRS_POINTSPRITEENABLE]) + { + /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */ + FIXME("Point sprites not supported\n"); + warned = TRUE; + } +} + +static void state_pointsprite(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + + if (state->render_states[WINED3DRS_POINTSPRITEENABLE]) + { + static BOOL warned; + + if (gl_info->limits.point_sprite_units < gl_info->limits.textures && !warned) + { + if (use_ps(state) || state->lowest_disabled_stage > gl_info->limits.point_sprite_units) + { + FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n"); + warned = TRUE; + } + } + + glEnable(GL_POINT_SPRITE_ARB); + checkGLcall("glEnable(GL_POINT_SPRITE_ARB)"); + } else { + glDisable(GL_POINT_SPRITE_ARB); + checkGLcall("glDisable(GL_POINT_SPRITE_ARB)"); + } +} + +static void state_wrap(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /** + http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/ + http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp + Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem. + http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248 + + so far as I can tell, wrapping and texture-coordinate generate go hand in hand, + */ + if (stateblock->state.render_states[WINED3DRS_WRAP0] + || stateblock->state.render_states[WINED3DRS_WRAP1] + || stateblock->state.render_states[WINED3DRS_WRAP2] + || stateblock->state.render_states[WINED3DRS_WRAP3] + || stateblock->state.render_states[WINED3DRS_WRAP4] + || stateblock->state.render_states[WINED3DRS_WRAP5] + || stateblock->state.render_states[WINED3DRS_WRAP6] + || stateblock->state.render_states[WINED3DRS_WRAP7] + || stateblock->state.render_states[WINED3DRS_WRAP8] + || stateblock->state.render_states[WINED3DRS_WRAP9] + || stateblock->state.render_states[WINED3DRS_WRAP10] + || stateblock->state.render_states[WINED3DRS_WRAP11] + || stateblock->state.render_states[WINED3DRS_WRAP12] + || stateblock->state.render_states[WINED3DRS_WRAP13] + || stateblock->state.render_states[WINED3DRS_WRAP14] + || stateblock->state.render_states[WINED3DRS_WRAP15]) + { + FIXME("(WINED3DRS_WRAP0) Texture wrapping not yet supported.\n"); + } +} + +static void state_msaa_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEANTIALIAS]) + WARN("Multisample antialiasing not supported by gl\n"); +} + +static void state_msaa(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEANTIALIAS]) + { + glEnable(GL_MULTISAMPLE_ARB); + checkGLcall("glEnable(GL_MULTISAMPLE_ARB)"); + } else { + glDisable(GL_MULTISAMPLE_ARB); + checkGLcall("glDisable(GL_MULTISAMPLE_ARB)"); + } +} + +static void state_scissor(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_SCISSORTESTENABLE]) + { + glEnable(GL_SCISSOR_TEST); + checkGLcall("glEnable(GL_SCISSOR_TEST)"); + } else { + glDisable(GL_SCISSOR_TEST); + checkGLcall("glDisable(GL_SCISSOR_TEST)"); + } +} + +/* The Direct3D depth bias is specified in normalized depth coordinates. In + * OpenGL the bias is specified in units of "the smallest value that is + * guaranteed to produce a resolvable offset for a given implementation". To + * convert from D3D to GL we need to divide the D3D depth bias by that value. + * There's no practical way to retrieve that value from a given GL + * implementation, but the D3D application has essentially the same problem, + * which makes a guess of the depth buffer format's highest possible value a + * reasonable guess. Note that SLOPESCALEDEPTHBIAS is a scaling factor for the + * depth slope, and doesn't need to be scaled. */ +static void state_depthbias(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_SLOPESCALEDEPTHBIAS] + || stateblock->state.render_states[WINED3DRS_DEPTHBIAS]) + { + struct wined3d_surface *depth = stateblock->device->fb.depth_stencil; + float scale; + + union + { + DWORD d; + float f; + } scale_bias, const_bias; + + scale_bias.d = stateblock->state.render_states[WINED3DRS_SLOPESCALEDEPTHBIAS]; + const_bias.d = stateblock->state.render_states[WINED3DRS_DEPTHBIAS]; + + glEnable(GL_POLYGON_OFFSET_FILL); + checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)"); + + if (depth) + { + const struct wined3d_format *fmt = depth->resource.format; + scale = powf(2, fmt->depth_size) - 1; + TRACE("Depth format %s, using depthbias scale of %f\n", + debug_d3dformat(fmt->id), scale); + } + else + { + /* The context manager will reapply this state on a depth stencil change */ + TRACE("No depth stencil, using depthbias scale of 0.0\n"); + scale = 0; + } + + glPolygonOffset(scale_bias.f, const_bias.f * scale); + checkGLcall("glPolygonOffset(...)"); + } else { + glDisable(GL_POLYGON_OFFSET_FILL); + checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)"); + } +} + +static void state_zvisible(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_ZVISIBLE]) + FIXME("WINED3DRS_ZVISIBLE not implemented.\n"); +} + +static void state_perspective(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_TEXTUREPERSPECTIVE]) + { + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)"); + } else { + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)"); + } +} + +static void state_stippledalpha(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_STIPPLEDALPHA]) + FIXME(" Stippled Alpha not supported yet.\n"); +} + +static void state_antialias(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_ANTIALIAS]) + FIXME("Antialias not supported yet.\n"); +} + +static void state_multisampmask(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_MULTISAMPLEMASK] != 0xffffffff) + FIXME("WINED3DRS_MULTISAMPLEMASK %#x not yet implemented.\n", + stateblock->state.render_states[WINED3DRS_MULTISAMPLEMASK]); +} + +static void state_patchedgestyle(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE) + FIXME("WINED3DRS_PATCHEDGESTYLE %#x not yet implemented.\n", + stateblock->state.render_states[WINED3DRS_PATCHEDGESTYLE]); +} + +static void state_patchsegments(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + union { + DWORD d; + float f; + } tmpvalue; + tmpvalue.f = 1.0f; + + if (stateblock->state.render_states[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d) + { + static BOOL displayed = FALSE; + + tmpvalue.d = stateblock->state.render_states[WINED3DRS_PATCHSEGMENTS]; + if(!displayed) + FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f); + + displayed = TRUE; + } +} + +static void state_positiondegree(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC) + FIXME("WINED3DRS_POSITIONDEGREE %#x not yet implemented.\n", + stateblock->state.render_states[WINED3DRS_POSITIONDEGREE]); +} + +static void state_normaldegree(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR) + FIXME("WINED3DRS_NORMALDEGREE %#x not yet implemented.\n", + stateblock->state.render_states[WINED3DRS_NORMALDEGREE]); +} + +static void state_tessellation(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_ENABLEADAPTIVETESSELLATION]) + FIXME("WINED3DRS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n", + stateblock->state.render_states[WINED3DRS_ENABLEADAPTIVETESSELLATION]); +} + +static void state_nvdb(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + union { + DWORD d; + float f; + } zmin, zmax; + + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_X] == WINED3DFMT_NVDB) + { + zmin.d = stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_Z]; + zmax.d = stateblock->state.render_states[WINED3DRS_ADAPTIVETESS_W]; + + /* If zmin is larger than zmax INVALID_VALUE error is generated. + * In d3d9 test is not performed in this case*/ + if (zmin.f <= zmax.f) + { + glEnable(GL_DEPTH_BOUNDS_TEST_EXT); + checkGLcall("glEnable(GL_DEPTH_BOUNDS_TEST_EXT)"); + GL_EXTCALL(glDepthBoundsEXT(zmin.f, zmax.f)); + checkGLcall("glDepthBoundsEXT(...)"); + } + else { + glDisable(GL_DEPTH_BOUNDS_TEST_EXT); + checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)"); + } + } + else { + glDisable(GL_DEPTH_BOUNDS_TEST_EXT); + checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)"); + } + + state_tessellation(state, stateblock, context); +} + +static void state_wrapu(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_WRAPU]) + FIXME("Render state WINED3DRS_WRAPU not implemented yet.\n"); +} + +static void state_wrapv(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_WRAPV]) + FIXME("Render state WINED3DRS_WRAPV not implemented yet.\n"); +} + +static void state_monoenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_MONOENABLE]) + FIXME("Render state WINED3DRS_MONOENABLE not implemented yet.\n"); +} + +static void state_rop2(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_ROP2]) + FIXME("Render state WINED3DRS_ROP2 not implemented yet.\n"); +} + +static void state_planemask(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_PLANEMASK]) + FIXME("Render state WINED3DRS_PLANEMASK not implemented yet.\n"); +} + +static void state_subpixel(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_SUBPIXEL]) + FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet.\n"); +} + +static void state_subpixelx(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_SUBPIXELX]) + FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet.\n"); +} + +static void state_stippleenable(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_STIPPLEENABLE]) + FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet.\n"); +} + +static void state_mipmaplodbias(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_MIPMAPLODBIAS]) + FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet.\n"); +} + +static void state_anisotropy(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_ANISOTROPY]) + FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet.\n"); +} + +static void state_flushbatch(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_FLUSHBATCH]) + FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet.\n"); +} + +static void state_translucentsi(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) + FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n"); +} + +static void state_extents(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_EXTENTS]) + FIXME("Render state WINED3DRS_EXTENTS not implemented yet.\n"); +} + +static void state_ckeyblend(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_COLORKEYBLENDENABLE]) + FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet.\n"); +} + +static void state_swvp(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (stateblock->state.render_states[WINED3DRS_SOFTWAREVERTEXPROCESSING]) + FIXME("Software vertex processing not implemented.\n"); +} + +/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/ +#if defined (GL_VERSION_1_3) +# define useext(A) A +#elif defined (GL_EXT_texture_env_combine) +# define useext(A) A##_EXT +#elif defined (GL_ARB_texture_env_combine) +# define useext(A) A##_ARB +#endif + +static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) { + /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the + * input should be used for all input components. The WINED3DTA_COMPLEMENT + * flag specifies the complement of the input should be used. */ + BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE; + BOOL complement = arg & WINED3DTA_COMPLEMENT; + + /* Calculate the operand */ + if (complement) { + if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA; + else *operand = GL_ONE_MINUS_SRC_COLOR; + } else { + if (from_alpha) *operand = GL_SRC_ALPHA; + else *operand = GL_SRC_COLOR; + } + + /* Calculate the source */ + switch (arg & WINED3DTA_SELECTMASK) { + case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break; + case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break; + case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break; + case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break; + case WINED3DTA_SPECULAR: + /* + * According to the GL_ARB_texture_env_combine specs, SPECULAR is + * 'Secondary color' and isn't supported until base GL supports it + * There is no concept of temp registers as far as I can tell + */ + FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n"); + *source = GL_TEXTURE; + break; + default: + FIXME("Unrecognized texture arg %#x\n", arg); + *source = GL_TEXTURE; + break; + } +} + +/* Setup the texture operations texture stage states */ +static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state, + BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) +{ + GLenum src1, src2, src3; + GLenum opr1, opr2, opr3; + GLenum comb_target; + GLenum src0_target, src1_target, src2_target; + GLenum opr0_target, opr1_target, opr2_target; + GLenum scal_target; + GLenum opr=0, invopr, src3_target, opr3_target; + BOOL Handled = FALSE; + + TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3); + + /* This is called by a state handler which has the gl lock held and a context for the thread */ + + /* Note: Operations usually involve two ars, src0 and src1 and are operations of + the form (a1 a2). However, some of the more complex operations + take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added + in a third parameter called a0. Therefore these are operations of the form + a0 a1 a2, i.e., the new parameter goes to the front. + + However, below we treat the new (a0) parameter as src2/opr2, so in the actual + functions below, expect their syntax to differ slightly to those listed in the + manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2 + This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */ + + if (isAlpha) { + comb_target = useext(GL_COMBINE_ALPHA); + src0_target = useext(GL_SOURCE0_ALPHA); + src1_target = useext(GL_SOURCE1_ALPHA); + src2_target = useext(GL_SOURCE2_ALPHA); + opr0_target = useext(GL_OPERAND0_ALPHA); + opr1_target = useext(GL_OPERAND1_ALPHA); + opr2_target = useext(GL_OPERAND2_ALPHA); + scal_target = GL_ALPHA_SCALE; + } + else { + comb_target = useext(GL_COMBINE_RGB); + src0_target = useext(GL_SOURCE0_RGB); + src1_target = useext(GL_SOURCE1_RGB); + src2_target = useext(GL_SOURCE2_RGB); + opr0_target = useext(GL_OPERAND0_RGB); + opr1_target = useext(GL_OPERAND1_RGB); + opr2_target = useext(GL_OPERAND2_RGB); + scal_target = useext(GL_RGB_SCALE); + } + + /* If a texture stage references an invalid texture unit the stage just + * passes through the result from the previous stage */ + if (is_invalid_op(state, Stage, op, arg1, arg2, arg3)) + { + arg1 = WINED3DTA_CURRENT; + op = WINED3DTOP_SELECTARG1; + } + + if (isAlpha && !state->textures[Stage] && arg1 == WINED3DTA_TEXTURE) + { + get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1); + } else { + get_src_and_opr(arg1, isAlpha, &src1, &opr1); + } + get_src_and_opr(arg2, isAlpha, &src2, &opr2); + get_src_and_opr(arg3, isAlpha, &src3, &opr3); + + TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3); + + Handled = TRUE; /* Assume will be handled */ + + /* Other texture operations require special extensions: */ + if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4]) + { + if (isAlpha) { + opr = GL_SRC_ALPHA; + invopr = GL_ONE_MINUS_SRC_ALPHA; + src3_target = GL_SOURCE3_ALPHA_NV; + opr3_target = GL_OPERAND3_ALPHA_NV; + } else { + opr = GL_SRC_COLOR; + invopr = GL_ONE_MINUS_SRC_COLOR; + src3_target = GL_SOURCE3_RGB_NV; + opr3_target = GL_OPERAND3_RGB_NV; + } + switch (op) { + case WINED3DTOP_DISABLE: /* Only for alpha */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + break; + case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */ + case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + if (op == WINED3DTOP_SELECTARG1) { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + } else { + glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); + } + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + break; + + case WINED3DTOP_MODULATE: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_MODULATE4X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); + checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); + break; + + case WINED3DTOP_ADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_ADDSIGNED: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_ADDSIGNED2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + + case WINED3DTOP_ADDSMOOTH: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_BLENDDIFFUSEALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDFACTORALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHAPM: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */ + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */ + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */ + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */ + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */ + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src1); + checkGLcall("GL_TEXTURE_ENV, src3_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MULTIPLYADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src3); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO); + checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src1); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src3_target, src2); + checkGLcall("GL_TEXTURE_ENV, src3_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + + case WINED3DTOP_BUMPENVMAP: + { + } + + case WINED3DTOP_BUMPENVMAPLUMINANCE: + FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n"); + + default: + Handled = FALSE; + } + if (Handled) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV); + checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV"); + + return; + } + } /* GL_NV_texture_env_combine4 */ + + Handled = TRUE; /* Again, assume handled */ + switch (op) { + case WINED3DTOP_DISABLE: /* Only for alpha */ + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT); + checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_SELECTARG1: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_SELECTARG2: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src2); + checkGLcall("GL_TEXTURE_ENV, src0_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_MODULATE2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_MODULATE4X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 4); + checkGLcall("GL_TEXTURE_ENV, scal_target, 4"); + break; + case WINED3DTOP_ADD: + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSIGNED: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSIGNED2X: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 2); + checkGLcall("GL_TEXTURE_ENV, scal_target, 2"); + break; + case WINED3DTOP_SUBTRACT: + if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else { + FIXME("This version of opengl does not support GL_SUBTRACT\n"); + } + break; + + case WINED3DTOP_BLENDDIFFUSEALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDTEXTUREALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDFACTORALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_BLENDCURRENTALPHA: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS)); + checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_DOTPRODUCT3: + if (gl_info->supported[ARB_TEXTURE_ENV_DOT3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB"); + } + else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT"); + } else { + FIXME("This version of opengl does not support GL_DOT3\n"); + } + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_LERP: + glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)); + checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src2); + checkGLcall("GL_TEXTURE_ENV, src1_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src3); + checkGLcall("GL_TEXTURE_ENV, src2_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + break; + case WINED3DTOP_ADDSMOOTH: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_BLENDTEXTUREALPHAPM: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE); + checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA); + checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break; + case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src1); + checkGLcall("GL_TEXTURE_ENV, src1_target, src1"); + switch (opr1) { + case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break; + case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break; + } + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_MULTIPLYADD: + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]) + { + glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI); + checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI"); + glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); + checkGLcall("GL_TEXTURE_ENV, src0_target, src1"); + glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1); + checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); + glTexEnvi(GL_TEXTURE_ENV, src1_target, src3); + checkGLcall("GL_TEXTURE_ENV, src1_target, src3"); + glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3); + checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3"); + glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); + checkGLcall("GL_TEXTURE_ENV, src2_target, src2"); + glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2); + checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); + glTexEnvi(GL_TEXTURE_ENV, scal_target, 1); + checkGLcall("GL_TEXTURE_ENV, scal_target, 1"); + } else + Handled = FALSE; + break; + case WINED3DTOP_BUMPENVMAPLUMINANCE: + case WINED3DTOP_BUMPENVMAP: + if (gl_info->supported[NV_TEXTURE_SHADER2]) + { + /* Technically texture shader support without register combiners is possible, but not expected to occur + * on real world cards, so for now a fixme should be enough + */ + FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n"); + } + default: + Handled = FALSE; + } + + if (Handled) { + BOOL combineOK = TRUE; + if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4]) + { + DWORD op2; + + if (isAlpha) + op2 = state->texture_states[Stage][WINED3DTSS_COLOROP]; + else + op2 = state->texture_states[Stage][WINED3DTSS_ALPHAOP]; + + /* Note: If COMBINE4 in effect can't go back to combine! */ + switch (op2) { + case WINED3DTOP_ADDSMOOTH: + case WINED3DTOP_BLENDTEXTUREALPHAPM: + case WINED3DTOP_MODULATEALPHA_ADDCOLOR: + case WINED3DTOP_MODULATECOLOR_ADDALPHA: + case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR: + case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA: + case WINED3DTOP_MULTIPLYADD: + /* Ignore those implemented in both cases */ + switch (op) { + case WINED3DTOP_SELECTARG1: + case WINED3DTOP_SELECTARG2: + combineOK = FALSE; + Handled = FALSE; + break; + default: + FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha); + return; + } + } + } + + if (combineOK) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)); + checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)"); + + return; + } + } + + /* After all the extensions, if still unhandled, report fixme */ + FIXME("Unhandled texture operation %s\n", debug_d3dtop(op)); +} + + +static void tex_colorop(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage); + DWORD mapped_stage = stateblock->device->texUnitMap[stage]; + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + + TRACE("Setting color op for stage %d\n", stage); + + /* Using a pixel shader? Don't care for anything here, the shader applying does it */ + if (use_ps(state)) return; + + if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage); + + if (mapped_stage != WINED3D_UNMAPPED_STAGE) + { + if (tex_used && mapped_stage >= gl_info->limits.textures) + { + FIXME("Attempt to enable unsupported stage!\n"); + return; + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + } + + if (stage >= state->lowest_disabled_stage) + { + TRACE("Stage disabled\n"); + if (mapped_stage != WINED3D_UNMAPPED_STAGE) + { + /* Disable everything here */ + glDisable(GL_TEXTURE_2D); + checkGLcall("glDisable(GL_TEXTURE_2D)"); + glDisable(GL_TEXTURE_3D); + checkGLcall("glDisable(GL_TEXTURE_3D)"); + if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) + { + glDisable(GL_TEXTURE_CUBE_MAP_ARB); + checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)"); + } + if (gl_info->supported[ARB_TEXTURE_RECTANGLE]) + { + glDisable(GL_TEXTURE_RECTANGLE_ARB); + checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)"); + } + } + /* All done */ + return; + } + + /* The sampler will also activate the correct texture dimensions, so no + * need to do it here if the sampler for this stage is dirty. */ + if (!isStateDirty(context, STATE_SAMPLER(stage)) && tex_used) + texture_activate_dimensions(state->textures[stage], gl_info); + + set_tex_op(gl_info, state, FALSE, stage, + state->texture_states[stage][WINED3DTSS_COLOROP], + state->texture_states[stage][WINED3DTSS_COLORARG1], + state->texture_states[stage][WINED3DTSS_COLORARG2], + state->texture_states[stage][WINED3DTSS_COLORARG0]); +} + +void tex_alphaop(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + BOOL tex_used = stateblock->device->fixed_function_usage_map & (1 << stage); + DWORD mapped_stage = stateblock->device->texUnitMap[stage]; + const struct wined3d_gl_info *gl_info = context->gl_info; + DWORD op, arg1, arg2, arg0; + + TRACE("Setting alpha op for stage %d\n", stage); + /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */ + if (mapped_stage != WINED3D_UNMAPPED_STAGE) + { + if (tex_used && mapped_stage >= gl_info->limits.textures) + { + FIXME("Attempt to enable unsupported stage!\n"); + return; + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + } + + op = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAOP]; + arg1 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG1]; + arg2 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG2]; + arg0 = stateblock->state.texture_states[stage][WINED3DTSS_ALPHAARG0]; + + if (stateblock->state.render_states[WINED3DRS_COLORKEYENABLE] && !stage && stateblock->state.textures[0]) + { + struct wined3d_texture *texture = stateblock->state.textures[0]; + GLenum texture_dimensions = texture->target; + + if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB) + { + struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]); + + if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_mask) + { + /* Color keying needs to pass alpha values from the texture through to have the alpha test work + * properly. On the other hand applications can still use texture combiners apparently. This code + * takes care that apps cannot remove the texture's alpha channel entirely. + * + * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires + * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures + * and alpha component of diffuse color to draw things like translucent text and perform other + * blending effects. + * + * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To + * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be + * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to + * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the + * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of + * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels + * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha + * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be + * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture + * alpha. + * + * What to do with multitexturing? So far no app has been found that uses color keying with + * multitexturing */ + if (op == WINED3DTOP_DISABLE) + { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_SELECTARG1; + } + else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE) + { + if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE]) + { + arg2 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg1 = WINED3DTA_TEXTURE; + } + else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE) + { + if (stateblock->state.render_states[WINED3DRS_ALPHABLENDENABLE]) + { + arg1 = WINED3DTA_TEXTURE; + op = WINED3DTOP_MODULATE; + } + else arg2 = WINED3DTA_TEXTURE; + } + } + } + } + + /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to + * this if block here, and the other code(color keying, texture unit selection) are the same + */ + TRACE("Setting alpha op for stage %d\n", stage); + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + set_tex_op_nvrc(gl_info, &stateblock->state, TRUE, stage, op, arg1, arg2, arg0, + mapped_stage, stateblock->state.texture_states[stage][WINED3DTSS_RESULTARG]); + } + else + { + set_tex_op(gl_info, &stateblock->state, TRUE, stage, op, arg1, arg2, arg0); + } +} + +static void transform_texture(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD texUnit = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + DWORD mapped_stage = stateblock->device->texUnitMap[texUnit]; + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + BOOL generated; + int coordIdx; + + /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */ + if (use_vs(state) || isStateDirty(context, STATE_VDECL)) + { + TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n"); + return; + } + + if (mapped_stage == WINED3D_UNMAPPED_STAGE) return; + if (mapped_stage >= gl_info->limits.textures) return; + + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + generated = (state->texture_states[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000) != WINED3DTSS_TCI_PASSTHRU; + coordIdx = min(state->texture_states[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000ffff], MAX_TEXTURES - 1); + + set_texture_matrix(&state->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0], + state->texture_states[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], + generated, context->last_was_rhw, + stateblock->device->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)) + ? stateblock->device->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id + : WINED3DFMT_UNKNOWN, + stateblock->device->frag_pipe->ffp_proj_control); + + /* The sampler applying function calls us if this changes */ + if ((context->lastWasPow2Texture & (1 << texUnit)) && state->textures[texUnit]) + { + if(generated) { + FIXME("Non-power2 texture being used with generated texture coords\n"); + } + /* NP2 texcoord fixup is implemented for pixelshaders so only enable the + fixed-function-pipeline fixup via pow2Matrix when no PS is used. */ + if (!use_ps(state)) + { + TRACE("Non power two matrix multiply fixup\n"); + glMultMatrixf(state->textures[texUnit]->pow2_matrix); + } + } +} + +static void unloadTexCoords(const struct wined3d_gl_info *gl_info) +{ + unsigned int texture_idx; + + for (texture_idx = 0; texture_idx < gl_info->limits.texture_stages; ++texture_idx) + { + GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx)); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } +} + +static void loadTexCoords(const struct wined3d_gl_info *gl_info, struct wined3d_stateblock *stateblock, + const struct wined3d_stream_info *si, GLuint *curVBO) +{ + unsigned int mapped_stage = 0; + unsigned int textureNo = 0; + + for (textureNo = 0; textureNo < gl_info->limits.texture_stages; ++textureNo) + { + int coordIdx = stateblock->state.texture_states[textureNo][WINED3DTSS_TEXCOORDINDEX]; + + mapped_stage = stateblock->device->texUnitMap[textureNo]; + if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue; + + if (coordIdx < MAX_TEXTURES && (si->use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx)))) + { + const struct wined3d_stream_info_element *e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx]; + const struct wined3d_stream_state *stream = &stateblock->state.streams[e->stream_idx]; + + TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n", + textureNo, mapped_stage, coordIdx, e->data); + + if (*curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + *curVBO = e->buffer_object; + } + + GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glClientActiveTextureARB"); + + /* The coords to supply depend completely on the fvf / vertex shader */ + glTexCoordPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } else { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1)); + } + } + if (gl_info->supported[NV_REGISTER_COMBINERS]) + { + /* The number of the mapped stages increases monotonically, so it's fine to use the last used one. */ + for (textureNo = mapped_stage + 1; textureNo < gl_info->limits.textures; ++textureNo) + { + GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1)); + } + } + + checkGLcall("loadTexCoords"); +} + +static void tex_coordindex(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + DWORD mapped_stage = stateblock->device->texUnitMap[stage]; + static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f }; + static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f }; + static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f }; + static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (mapped_stage == WINED3D_UNMAPPED_STAGE) + { + TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage); + return; + } + + if (mapped_stage >= gl_info->limits.fragment_samplers) + { + WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage); + return; + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + + /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive + * + * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode. + * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 ); + * means use the vertex position (camera-space) as the input texture coordinates + * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render + * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up + * to the TEXCOORDINDEX value + */ + switch (stateblock->state.texture_states[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000) + { + case WINED3DTSS_TCI_PASSTHRU: + /* Use the specified texture coordinates contained within the + * vertex format. This value resolves to zero. */ + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); + checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen."); + break; + + case WINED3DTSS_TCI_CAMERASPACEPOSITION: + /* CameraSpacePosition means use the vertex position, transformed to camera space, + * as the input texture coordinates for this stage's texture transformation. This + * equates roughly to EYE_LINEAR */ + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTexGenfv(GL_S, GL_EYE_PLANE, s_plane); + glTexGenfv(GL_T, GL_EYE_PLANE, t_plane); + glTexGenfv(GL_R, GL_EYE_PLANE, r_plane); + glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane); + glPopMatrix(); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane."); + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode."); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen."); + + break; + + case WINED3DTSS_TCI_CAMERASPACENORMAL: + /* Note that NV_TEXGEN_REFLECTION support is implied when + * ARB_TEXTURE_CUBE_MAP is supported */ + if (!gl_info->supported[NV_TEXGEN_REFLECTION]) + { + FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n"); + break; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTexGenfv(GL_S, GL_EYE_PLANE, s_plane); + glTexGenfv(GL_T, GL_EYE_PLANE, t_plane); + glTexGenfv(GL_R, GL_EYE_PLANE, r_plane); + glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane); + glPopMatrix(); + checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane."); + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV); + checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode."); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen."); + + break; + + case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: + /* Note that NV_TEXGEN_REFLECTION support is implied when + * ARB_TEXTURE_CUBE_MAP is supported */ + if (!gl_info->supported[NV_TEXGEN_REFLECTION]) + { + FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n"); + break; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTexGenfv(GL_S, GL_EYE_PLANE, s_plane); + glTexGenfv(GL_T, GL_EYE_PLANE, t_plane); + glTexGenfv(GL_R, GL_EYE_PLANE, r_plane); + glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane); + glPopMatrix(); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane."); + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode."); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen."); + + break; + + case WINED3DTSS_TCI_SPHEREMAP: + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode."); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen."); + + break; + + default: + FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x.\n", + stateblock->state.texture_states[stage][WINED3DTSS_TEXCOORDINDEX]); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); + checkGLcall("Disable texgen."); + + break; + } + + /* Update the texture matrix */ + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) { + transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); + } + + if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) { + /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input + * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration + * and do all the things linked to it + * TODO: Tidy that up to reload only the arrays of the changed unit + */ + GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; + + unloadTexCoords(gl_info); + loadTexCoords(gl_info, stateblock, &stateblock->device->strided_streams, &curVBO); + } +} + +static void shaderconstant(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_state *state = &stateblock->state; + struct wined3d_device *device = stateblock->device; + + /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them + * has an update pending + */ + if(isStateDirty(context, STATE_VDECL) || + isStateDirty(context, STATE_PIXELSHADER)) { + return; + } + + device->shader_backend->shader_load_constants(context, use_ps(state), use_vs(state)); +} + +static void tex_bumpenvlscale(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + const struct wined3d_shader *ps = stateblock->state.pixel_shader; + + if (ps && stage && (ps->reg_maps.luminanceparams & (1 << stage))) + { + /* The pixel shader has to know the luminance scale. Do a constants update if it + * isn't scheduled anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && + !isStateDirty(context, STATE_PIXELSHADER)) { + shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } +} + +static void sampler_texmatrix(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const DWORD sampler = state - STATE_SAMPLER(0); + struct wined3d_texture *texture = stateblock->state.textures[sampler]; + + TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context); + + if(!texture) return; + /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates + * wined3d_texture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the + * scaling is reapplied or removed, the texture matrix has to be reapplied + * + * The mapped stage is already active because the sampler() function below, which is part of the + * misc pipeline + */ + if (sampler < MAX_TEXTURES) + { + const BOOL texIsPow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT); + + if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler))) + { + if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler; + else context->lastWasPow2Texture &= ~(1 << sampler); + transform_texture(STATE_TEXTURESTAGE(stateblock->device->texUnitMap[sampler], + WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); + } + } +} + +static void sampler(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD sampler = state_id - STATE_SAMPLER(0); + struct wined3d_device *device = stateblock->device; + DWORD mapped_stage = device->texUnitMap[sampler]; + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + union { + float f; + DWORD d; + } tmpvalue; + + TRACE("Sampler: %d\n", sampler); + /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function + * only has to bind textures and set the per texture states + */ + + if (mapped_stage == WINED3D_UNMAPPED_STAGE) + { + TRACE("No sampler mapped to stage %d. Returning.\n", sampler); + return; + } + + if (mapped_stage >= gl_info->limits.combined_samplers) + { + return; + } + GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage)); + checkGLcall("glActiveTextureARB"); + + if (state->textures[sampler]) + { + struct wined3d_texture *texture = state->textures[sampler]; + BOOL srgb = state->sampler_states[sampler][WINED3DSAMP_SRGBTEXTURE]; + + texture->texture_ops->texture_bind(texture, gl_info, srgb); + wined3d_texture_apply_state_changes(texture, state->sampler_states[sampler], gl_info); + + if (gl_info->supported[EXT_TEXTURE_LOD_BIAS]) + { + tmpvalue.d = state->sampler_states[sampler][WINED3DSAMP_MIPMAPLODBIAS]; + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, + GL_TEXTURE_LOD_BIAS_EXT, + tmpvalue.f); + checkGLcall("glTexEnvf(GL_TEXTURE_LOD_BIAS_EXT, ...)"); + } + + if (!use_ps(state) && sampler < state->lowest_disabled_stage) + { + if (state->render_states[WINED3DRS_COLORKEYENABLE] && !sampler) + { + /* If color keying is enabled update the alpha test, it depends on the existence + * of a color key in stage 0 + */ + state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context); + } + } + + /* Trigger shader constant reloading (for NP2 texcoord fixup) */ + if (!(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT)) + device->shader_backend->shader_load_np2fixup_constants(device->shader_priv, gl_info, state); + } + else if (mapped_stage < gl_info->limits.textures) + { + if (sampler < state->lowest_disabled_stage) + { + /* TODO: What should I do with pixel shaders here ??? */ + if (state->render_states[WINED3DRS_COLORKEYENABLE] && !sampler) + { + /* If color keying is enabled update the alpha test, it depends on the existence + * of a color key in stage 0 + */ + state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context); + } + } /* Otherwise tex_colorop disables the stage */ + glBindTexture(GL_TEXTURE_2D, device->dummyTextureName[sampler]); + checkGLcall("glBindTexture(GL_TEXTURE_2D, device->dummyTextureName[sampler])"); + } +} + +void apply_pixelshader(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_state *state = &stateblock->state; + struct wined3d_device *device = stateblock->device; + BOOL use_vshader = use_vs(state); + BOOL use_pshader = use_ps(state); + unsigned int i; + + if (use_pshader) { + if(!context->last_was_pshader) { + /* Former draw without a pixel shader, some samplers + * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE + * make sure to enable them + */ + for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) { + if(!isStateDirty(context, STATE_SAMPLER(i))) { + sampler(STATE_SAMPLER(i), stateblock, context); + } + } + context->last_was_pshader = TRUE; + } else { + /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler() + * if a different texture was bound. I don't have to do anything. + */ + } + } else { + /* Disabled the pixel shader - color ops weren't applied + * while it was enabled, so re-apply them. */ + for (i = 0; i < context->gl_info->limits.texture_stages; ++i) + { + if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) + stateblock_apply_state(STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context); + } + context->last_was_pshader = FALSE; + } + + if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) { + device->shader_backend->shader_select(context, use_pshader, use_vshader); + + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) { + shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); + } + } +} + +static void shader_bumpenvmat(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1); + const struct wined3d_shader *ps = stateblock->state.pixel_shader; + + if (ps && stage && (ps->reg_maps.bumpmat & (1 << stage))) + { + /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled + * anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && + !isStateDirty(context, STATE_PIXELSHADER)) { + shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } +} + +static void transform_world(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + /* This function is called by transform_view below if the view matrix was changed too + * + * Deliberately no check if the vertex declaration is dirty because the vdecl state + * does not always update the world matrix, only on a switch between transformed + * and untransformed draws. It *may* happen that the world matrix is set 2 times during one + * draw, but that should be rather rare and cheaper in total. + */ + glMatrixMode(GL_MODELVIEW); + checkGLcall("glMatrixMode"); + + if(context->last_was_rhw) { + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + } else { + /* In the general case, the view matrix is the identity matrix */ + if (stateblock->device->view_ident) + { + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); + checkGLcall("glLoadMatrixf"); + } + else + { + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]); + checkGLcall("glLoadMatrixf"); + glMultMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]); + checkGLcall("glMultMatrixf"); + } + } +} + +static void clipplane(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_state *state = &stateblock->state; + UINT index = state_id - STATE_CLIPPLANE(0); + + if (isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= context->gl_info->limits.clipplanes) + { + return; + } + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */ + if (!use_vs(state)) + glLoadMatrixf(&state->transforms[WINED3DTS_VIEW].u.m[0][0]); + else + /* with vertex shaders, clip planes are not transformed in direct3d, + * in OpenGL they are still transformed by the model view. + */ + glLoadIdentity(); + + TRACE("Clipplane [%.8e, %.8e, %.8e, %.8e]\n", + state->clip_planes[index][0], + state->clip_planes[index][1], + state->clip_planes[index][2], + state->clip_planes[index][3]); + glClipPlane(GL_CLIP_PLANE0 + index, state->clip_planes[index]); + checkGLcall("glClipPlane"); + + glPopMatrix(); +} + +static void transform_worldex(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)); + GLenum glMat; + TRACE("Setting world matrix %d\n", matrix); + + if (matrix >= context->gl_info->limits.blends) + { + WARN("Unsupported blend matrix set\n"); + return; + } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) { + return; + } + + /* GL_MODELVIEW0_ARB: 0x1700 + * GL_MODELVIEW1_ARB: 0x850a + * GL_MODELVIEW2_ARB: 0x8722 + * GL_MODELVIEW3_ARB: 0x8723 + * etc + * GL_MODELVIEW31_ARB: 0x873F + */ + if(matrix == 1) glMat = GL_MODELVIEW1_ARB; + else glMat = GL_MODELVIEW2_ARB - 2 + matrix; + + glMatrixMode(glMat); + checkGLcall("glMatrixMode(glMat)"); + + /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid + * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix + */ + if (stateblock->device->view_ident) + { + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]); + checkGLcall("glLoadMatrixf"); + } + else + { + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]); + checkGLcall("glLoadMatrixf"); + glMultMatrixf(&stateblock->state.transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]); + checkGLcall("glMultMatrixf"); + } +} + +static void state_vertexblend_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WINED3DVERTEXBLENDFLAGS f = stateblock->state.render_states[WINED3DRS_VERTEXBLEND]; + static unsigned int once; + + if (f == WINED3DVBF_DISABLE) return; + + if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f); + else WARN("Vertex blend flags %#x not supported.\n", f); +} + +static void state_vertexblend(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + WINED3DVERTEXBLENDFLAGS val = stateblock->state.render_states[WINED3DRS_VERTEXBLEND]; + const struct wined3d_gl_info *gl_info = context->gl_info; + static unsigned int once; + + switch(val) { + case WINED3DVBF_1WEIGHTS: + case WINED3DVBF_2WEIGHTS: + case WINED3DVBF_3WEIGHTS: + glEnable(GL_VERTEX_BLEND_ARB); + checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)"); + + /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context + * creation with enabling GL_WEIGHT_SUM_UNITY_ARB. + */ + GL_EXTCALL(glVertexBlendARB(stateblock->state.render_states[WINED3DRS_VERTEXBLEND] + 1)); + + if (!stateblock->device->vertexBlendUsed) + { + unsigned int i; + for (i = 1; i < gl_info->limits.blends; ++i) + { + if (!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) + { + transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context); + } + } + stateblock->device->vertexBlendUsed = TRUE; + } + break; + + case WINED3DVBF_TWEENING: + case WINED3DVBF_0WEIGHTS: /* Indexed vertex blending, not supported. */ + if (!once++) FIXME("Vertex blend flags %#x not supported.\n", val); + else WARN("Vertex blend flags %#x not supported.\n", val); + /* Fall through. */ + case WINED3DVBF_DISABLE: + glDisable(GL_VERTEX_BLEND_ARB); + checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)"); + break; + } +} + +static void transform_view(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_light_info *light = NULL; + unsigned int k; + + /* If we are changing the View matrix, reset the light and clipping planes to the new view + * NOTE: We have to reset the positions even if the light/plane is not currently + * enabled, since the call to enable it will not reset the position. + * NOTE2: Apparently texture transforms do NOT need reapplying + */ + + glMatrixMode(GL_MODELVIEW); + checkGLcall("glMatrixMode(GL_MODELVIEW)"); + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]); + checkGLcall("glLoadMatrixf(...)"); + + /* Reset lights. TODO: Call light apply func */ + for (k = 0; k < gl_info->limits.lights; ++k) + { + light = stateblock->state.lights[k]; + if(!light) continue; + glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn); + checkGLcall("glLightfv posn"); + glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn); + checkGLcall("glLightfv dirn"); + } + + /* Reset Clipping Planes */ + for (k = 0; k < gl_info->limits.clipplanes; ++k) + { + if(!isStateDirty(context, STATE_CLIPPLANE(k))) { + clipplane(STATE_CLIPPLANE(k), stateblock, context); + } + } + + if(context->last_was_rhw) { + glLoadIdentity(); + checkGLcall("glLoadIdentity()"); + /* No need to update the world matrix, the identity is fine */ + return; + } + + /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix + * No need to do it here if the state is scheduled for update. + */ + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) { + transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context); + } + + /* Avoid looping over a number of matrices if the app never used the functionality */ + if (stateblock->device->vertexBlendUsed) + { + for (k = 1; k < gl_info->limits.blends; ++k) + { + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) { + transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context); + } + } + } +} + +static void transform_projection(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + glMatrixMode(GL_PROJECTION); + checkGLcall("glMatrixMode(GL_PROJECTION)"); + glLoadIdentity(); + checkGLcall("glLoadIdentity"); + + if (context->last_was_rhw) + { + double x = stateblock->state.viewport.X; + double y = stateblock->state.viewport.Y; + double w = stateblock->state.viewport.Width; + double h = stateblock->state.viewport.Height; + + TRACE("Calling glOrtho with x %.8e, y %.8e, w %.8e, h %.8e.\n", x, y, w, h); + if (context->render_offscreen) + glOrtho(x, x + w, -y, -y - h, 0.0, -1.0); + else + glOrtho(x, x + w, y + h, y, 0.0, -1.0); + checkGLcall("glOrtho"); + + /* D3D texture coordinates are flipped compared to OpenGL ones, so + * render everything upside down when rendering offscreen. */ + if (context->render_offscreen) + { + glScalef(1.0f, -1.0f, 1.0f); + checkGLcall("glScalef"); + } + + /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */ + glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f); + checkGLcall("glTranslatef(63.0f / 128.0f, 63.0f / 128.0f, 0.0f)"); + } + else + { + /* The rule is that the window coordinate 0 does not correspond to the + beginning of the first pixel, but the center of the first pixel. + As a consequence if you want to correctly draw one line exactly from + the left to the right end of the viewport (with all matrices set to + be identity), the x coords of both ends of the line would be not + -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width) + instead. + + 1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we + divide by the Width/Height, so we need the half range(1.0) to translate by + half a pixel. + + The other fun is that d3d's output z range after the transformation is [0;1], + but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl + scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot + of Z buffer precision and the clear values do not match in the z test. Thus scale + [0;1] to [-1;1], so when gl undoes that we utilize the full z range + */ + + /* + * Careful with the order of operations here, we're essentially working backwards: + * x = x + 1/w; + * y = (y - 1/h) * flip; + * z = z * 2 - 1; + * + * Becomes: + * glTranslatef(0.0, 0.0, -1.0); + * glScalef(1.0, 1.0, 2.0); + * + * glScalef(1.0, flip, 1.0); + * glTranslatef(1/w, -1/h, 0.0); + * + * This is equivalent to: + * glTranslatef(1/w, -flip/h, -1.0) + * glScalef(1.0, flip, 2.0); + */ + + /* Translate by slightly less than a half pixel to force a top-left + * filling convention. We want the difference to be large enough that + * it doesn't get lost due to rounding inside the driver, but small + * enough to prevent it from interfering with any anti-aliasing. */ + GLfloat xoffset = (63.0f / 64.0f) / stateblock->state.viewport.Width; + GLfloat yoffset = -(63.0f / 64.0f) / stateblock->state.viewport.Height; + + if (context->render_offscreen) + { + /* D3D texture coordinates are flipped compared to OpenGL ones, so + * render everything upside down when rendering offscreen. */ + glTranslatef(xoffset, -yoffset, -1.0f); + checkGLcall("glTranslatef(xoffset, -yoffset, -1.0f)"); + glScalef(1.0f, -1.0f, 2.0f); + } else { + glTranslatef(xoffset, yoffset, -1.0f); + checkGLcall("glTranslatef(xoffset, yoffset, -1.0f)"); + glScalef(1.0f, 1.0f, 2.0f); + } + checkGLcall("glScalef"); + + glMultMatrixf(&stateblock->state.transforms[WINED3DTS_PROJECTION].u.m[0][0]); + checkGLcall("glLoadMatrixf"); + } +} + +/* This should match any arrays loaded in loadVertexData. + * TODO: Only load / unload arrays if we have to. + */ +static inline void unloadVertexData(const struct wined3d_gl_info *gl_info) +{ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + } + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + glDisableClientState(GL_WEIGHT_ARRAY_ARB); + } + unloadTexCoords(gl_info); +} + +static inline void unload_numbered_array(struct wined3d_context *context, int i) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + GL_EXTCALL(glDisableVertexAttribArrayARB(i)); + checkGLcall("glDisableVertexAttribArrayARB(reg)"); + + context->numbered_array_mask &= ~(1 << i); +} + +/* This should match any arrays loaded in loadNumberedArrays + * TODO: Only load / unload arrays if we have to. + */ +static inline void unloadNumberedArrays(struct wined3d_context *context) +{ + /* disable any attribs (this is the same for both GLSL and ARB modes) */ + GLint maxAttribs = 16; + int i; + + /* Leave all the attribs disabled */ + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs); + /* MESA does not support it right not */ + if (glGetError() != GL_NO_ERROR) + maxAttribs = 16; + for (i = 0; i < maxAttribs; ++i) { + unload_numbered_array(context, i); + } +} + +static void loadNumberedArrays(struct wined3d_stateblock *stateblock, + const struct wined3d_stream_info *stream_info, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; + int i; + struct wined3d_buffer *vb; + + /* Default to no instancing */ + stateblock->device->instancedDraw = FALSE; + + for (i = 0; i < MAX_ATTRIBS; i++) + { + const struct wined3d_stream_state *stream; + + if (!(stream_info->use_map & (1 << i))) + { + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); + continue; + } + + stream = &stateblock->state.streams[stream_info->elements[i].stream_idx]; + + /* Do not load instance data. It will be specified using glTexCoord by drawprim */ + if (stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) + { + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); + stateblock->device->instancedDraw = TRUE; + continue; + } + + TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object); + + if (stream_info->elements[i].stride) + { + if (curVBO != stream_info->elements[i].buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = stream_info->elements[i].buffer_object; + } + /* Use the VBO to find out if a vertex buffer exists, not the vb + * pointer. vb can point to a user pointer data blob. In that case + * curVBO will be 0. If there is a vertex buffer but no vbo we + * won't be load converted attributes anyway. */ + vb = stream->buffer; + GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format->gl_vtx_format, + stream_info->elements[i].format->gl_vtx_type, + stream_info->elements[i].format->gl_normalized, + stream_info->elements[i].stride, stream_info->elements[i].data + + stateblock->state.load_base_vertex_index * stream_info->elements[i].stride + + stream->offset)); + + if (!(context->numbered_array_mask & (1 << i))) + { + GL_EXTCALL(glEnableVertexAttribArrayARB(i)); + context->numbered_array_mask |= (1 << i); + } + } + else + { + /* Stride = 0 means always the same values. + * glVertexAttribPointerARB doesn't do that. Instead disable the + * pointer and set up the attribute statically. But we have to + * figure out the system memory address. */ + const BYTE *ptr = stream_info->elements[i].data + stream->offset; + if (stream_info->elements[i].buffer_object) + { + vb = stream->buffer; + ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info); + } + + if (context->numbered_array_mask & (1 << i)) unload_numbered_array(context, i); + + switch (stream_info->elements[i].format->id) + { + case WINED3DFMT_R32_FLOAT: + GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32_FLOAT: + GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32_FLOAT: + GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr)); + break; + case WINED3DFMT_R32G32B32A32_FLOAT: + GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr)); + break; + + case WINED3DFMT_R8G8B8A8_UINT: + GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr)); + break; + case WINED3DFMT_B8G8R8A8_UNORM: + if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA]) + { + const DWORD *src = (const DWORD *)ptr; + DWORD c = *src & 0xff00ff00; + c |= (*src & 0xff0000) >> 16; + c |= (*src & 0xff) << 16; + GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c)); + break; + } + /* else fallthrough */ + case WINED3DFMT_R8G8B8A8_UNORM: + GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr)); + break; + + case WINED3DFMT_R16G16_SINT: + GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_SINT: + GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr)); + break; + + case WINED3DFMT_R16G16_SNORM: + { + const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4NsvARB(i, s)); + break; + } + case WINED3DFMT_R16G16_UNORM: + { + const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1}; + GL_EXTCALL(glVertexAttrib4NusvARB(i, s)); + break; + } + case WINED3DFMT_R16G16B16A16_SNORM: + GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr)); + break; + case WINED3DFMT_R16G16B16A16_UNORM: + GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr)); + break; + + case WINED3DFMT_R10G10B10A2_UINT: + FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n"); + /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */ + break; + case WINED3DFMT_R10G10B10A2_SNORM: + FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n"); + /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */ + break; + + case WINED3DFMT_R16G16_FLOAT: + /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4 + * byte float according to the IEEE standard + */ + FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n"); + break; + case WINED3DFMT_R16G16B16A16_FLOAT: + FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n"); + break; + + default: + ERR("Unexpected declaration in stride 0 attributes\n"); + break; + + } + } + } + checkGLcall("Loading numbered arrays"); +} + +/* Used from 2 different functions, and too big to justify making it inlined */ +static void loadVertexData(const struct wined3d_context *context, struct wined3d_stateblock *stateblock, + const struct wined3d_stream_info *si) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0; + const struct wined3d_stream_info_element *e; + const struct wined3d_stream_state *stream; + + TRACE("Using fast vertex array code\n"); + + /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */ + stateblock->device->instancedDraw = FALSE; + + /* Blend Data ---------------------------------------------- */ + if ((si->use_map & (1 << WINED3D_FFP_BLENDWEIGHT)) + || si->use_map & (1 << WINED3D_FFP_BLENDINDICES)) + { + e = &si->elements[WINED3D_FFP_BLENDWEIGHT]; + stream = &stateblock->state.streams[e->stream_idx]; + + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + TRACE("Blend %u %p %u\n", e->format->component_count, + e->data + stateblock->state.load_base_vertex_index * e->stride, e->stride + stream->offset); + + glEnableClientState(GL_WEIGHT_ARRAY_ARB); + checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)"); + + GL_EXTCALL(glVertexBlendARB(e->format->component_count + 1)); + + if (curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = e->buffer_object; + } + + TRACE("glWeightPointerARB(%#x, %#x, %#x, %p);\n", + e->format->gl_vtx_format, + e->format->gl_vtx_type, + e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + GL_EXTCALL(glWeightPointerARB(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset)); + + checkGLcall("glWeightPointerARB"); + + if (si->use_map & (1 << WINED3D_FFP_BLENDINDICES)) + { + static BOOL warned; + if (!warned) + { + FIXME("blendMatrixIndices support\n"); + warned = TRUE; + } + } + } else { + /* TODO: support blends in drawStridedSlow + * No need to write a FIXME here, this is done after the general vertex decl decoding + */ + WARN("unsupported blending in openGl\n"); + } + } + else + { + if (gl_info->supported[ARB_VERTEX_BLEND]) + { + static const GLbyte one = 1; + GL_EXTCALL(glWeightbvARB(1, &one)); + checkGLcall("glWeightbvARB(gl_info->max_blends, weights)"); + } + } + + /* Point Size ----------------------------------------------*/ + if (si->use_map & (1 << WINED3D_FFP_PSIZE)) + { + /* no such functionality in the fixed function GL pipeline */ + TRACE("Cannot change ptSize here in openGl\n"); + /* TODO: Implement this function in using shaders if they are available */ + } + + /* Vertex Pointers -----------------------------------------*/ + if (si->use_map & (1 << WINED3D_FFP_POSITION)) + { + e = &si->elements[WINED3D_FFP_POSITION]; + stream = &stateblock->state.streams[e->stream_idx]; + + if (curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = e->buffer_object; + } + + /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord + handling for rhw mode should not impact screen position whereas in GL it does. + This may result in very slightly distorted textures in rhw mode. + There's always the other option of fixing the view matrix to + prevent w from having any effect. + + This only applies to user pointer sources, in VBOs the vertices are fixed up + */ + if (!e->buffer_object) + { + TRACE("glVertexPointer(3, %#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + glVertexPointer(3 /* min(e->format->gl_vtx_format, 3) */, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + } + else + { + TRACE("glVertexPointer(%#x, %#x, %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + glVertexPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + } + checkGLcall("glVertexPointer(...)"); + glEnableClientState(GL_VERTEX_ARRAY); + checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)"); + } + + /* Normals -------------------------------------------------*/ + if (si->use_map & (1 << WINED3D_FFP_NORMAL)) + { + e = &si->elements[WINED3D_FFP_NORMAL]; + stream = &stateblock->state.streams[e->stream_idx]; + + if (curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = e->buffer_object; + } + + TRACE("glNormalPointer(%#x, %#x, %p);\n", e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + glNormalPointer(e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + checkGLcall("glNormalPointer(...)"); + glEnableClientState(GL_NORMAL_ARRAY); + checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)"); + + } else { + glNormal3f(0, 0, 0); + checkGLcall("glNormal3f(0, 0, 0)"); + } + + /* Diffuse Colour --------------------------------------------*/ + /* WARNING: Data here MUST be in RGBA format, so cannot */ + /* go directly into fast mode from app pgm, because */ + /* directx requires data in BGRA format. */ + /* currently fixupVertices swizzles the format, but this isn't*/ + /* very practical when using VBOs */ + /* NOTE: Unless we write a vertex shader to swizzle the colour*/ + /* , or the user doesn't care and wants the speed advantage */ + + if (si->use_map & (1 << WINED3D_FFP_DIFFUSE)) + { + e = &si->elements[WINED3D_FFP_DIFFUSE]; + stream = &stateblock->state.streams[e->stream_idx]; + + if (curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = e->buffer_object; + } + + TRACE("glColorPointer(%#x, %#x %#x, %p);\n", + e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + glColorPointer(e->format->gl_vtx_format, e->format->gl_vtx_type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)"); + glEnableClientState(GL_COLOR_ARRAY); + checkGLcall("glEnableClientState(GL_COLOR_ARRAY)"); + + } else { + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + checkGLcall("glColor4f(1, 1, 1, 1)"); + } + + /* Specular Colour ------------------------------------------*/ + if (si->use_map & (1 << WINED3D_FFP_SPECULAR)) + { + TRACE("setting specular colour\n"); + + e = &si->elements[WINED3D_FFP_SPECULAR]; + stream = &stateblock->state.streams[e->stream_idx]; + + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GLenum type = e->format->gl_vtx_type; + GLint format = e->format->gl_vtx_format; + + if (curVBO != e->buffer_object) + { + GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object)); + checkGLcall("glBindBufferARB"); + curVBO = e->buffer_object; + } + + if (format != 4 || (gl_info->quirks & WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA)) + { + /* Usually specular colors only allow 3 components, since they have no alpha. In D3D, the specular alpha + * contains the fog coordinate, which is passed to GL with GL_EXT_fog_coord. However, the fixed function + * vertex pipeline can pass the specular alpha through, and pixel shaders can read it. So it GL accepts + * 4 component secondary colors use it + */ + TRACE("glSecondaryColorPointer(%#x, %#x, %#x, %p);\n", format, type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + GL_EXTCALL(glSecondaryColorPointerEXT(format, type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset)); + checkGLcall("glSecondaryColorPointerEXT(format, type, ...)"); + } + else + { + switch(type) + { + case GL_UNSIGNED_BYTE: + TRACE("glSecondaryColorPointer(3, GL_UNSIGNED_BYTE, %#x, %p);\n", e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + GL_EXTCALL(glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset)); + checkGLcall("glSecondaryColorPointerEXT(3, GL_UNSIGNED_BYTE, ...)"); + break; + + default: + FIXME("Add 4 component specular color pointers for type %x\n", type); + /* Make sure that the right color component is dropped */ + TRACE("glSecondaryColorPointer(3, %#x, %#x, %p);\n", type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset); + GL_EXTCALL(glSecondaryColorPointerEXT(3, type, e->stride, + e->data + stateblock->state.load_base_vertex_index * e->stride + stream->offset)); + checkGLcall("glSecondaryColorPointerEXT(3, type, ...)"); + } + } + glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT); + checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + else + { + if (gl_info->supported[EXT_SECONDARY_COLOR]) + { + GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0); + checkGLcall("glSecondaryColor3fEXT(0, 0, 0)"); + } + else + { + WARN("Specular colour is not supported in this GL implementation.\n"); + } + } + + /* Texture coords -------------------------------------------*/ + loadTexCoords(gl_info, stateblock, si, &curVBO); +} + +static void streamsrc(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + struct wined3d_device *device = stateblock->device; + BOOL load_numbered = use_vs(&stateblock->state) && !device->useDrawStridedSlow; + BOOL load_named = !use_vs(&stateblock->state) && !device->useDrawStridedSlow; + + if (context->numberedArraysLoaded && !load_numbered) + { + unloadNumberedArrays(context); + context->numberedArraysLoaded = FALSE; + context->numbered_array_mask = 0; + } + else if (context->namedArraysLoaded) + { + unloadVertexData(context->gl_info); + context->namedArraysLoaded = FALSE; + } + + if (load_numbered) + { + TRACE("Loading numbered arrays\n"); + loadNumberedArrays(stateblock, &device->strided_streams, context); + context->numberedArraysLoaded = TRUE; + } + else if (load_named) + { + TRACE("Loading vertex data\n"); + loadVertexData(context, stateblock, &device->strided_streams); + context->namedArraysLoaded = TRUE; + } +} + +static void vertexdeclaration(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_state *state = &stateblock->state; + struct wined3d_device *device = stateblock->device; + BOOL useVertexShaderFunction = use_vs(state); + BOOL usePixelShaderFunction = use_ps(state); + BOOL updateFog = FALSE; + BOOL transformed; + BOOL wasrhw = context->last_was_rhw; + unsigned int i; + + transformed = device->strided_streams.position_transformed; + if (transformed != context->last_was_rhw && !useVertexShaderFunction) + updateFog = TRUE; + + if (transformed) { + context->last_was_rhw = TRUE; + } else { + + /* Untransformed, so relies on the view and projection matrices */ + context->last_was_rhw = FALSE; + /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/ + device->untransformed = TRUE; + } + + /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned + * off this function will be called again anyway to make sure they're properly set + */ + if(!useVertexShaderFunction) { + /* TODO: Move this mainly to the viewport state and only apply when the vp has changed + * or transformed / untransformed was switched + */ + if(wasrhw != context->last_was_rhw && + !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) && + !isStateDirty(context, STATE_VIEWPORT)) { + transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); + } + /* World matrix needs reapplication here only if we're switching between rhw and non-rhw + * mode. + * + * If a vertex shader is used, the world matrix changed and then vertex shader unbound + * this check will fail and the matrix not applied again. This is OK because a simple + * world matrix change reapplies the matrix - These checks here are only to satisfy the + * needs of the vertex declaration. + * + * World and view matrix go into the same gl matrix, so only apply them when neither is + * dirty + */ + if(transformed != wasrhw && + !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) && + !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) { + transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context); + } + + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) { + state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context); + } + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) { + state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context); + } + + if(context->last_was_vshader) { + updateFog = TRUE; + if(!device->vs_clipping && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) { + state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context); + } + for (i = 0; i < gl_info->limits.clipplanes; ++i) + { + clipplane(STATE_CLIPPLANE(i), stateblock, context); + } + } + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) { + state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context); + } + } else { + if(!context->last_was_vshader) { + static BOOL warned = FALSE; + if(!device->vs_clipping) { + /* Disable all clip planes to get defined results on all drivers. See comment in the + * state_clipping state handler + */ + for (i = 0; i < gl_info->limits.clipplanes; ++i) + { + glDisable(GL_CLIP_PLANE0 + i); + checkGLcall("glDisable(GL_CLIP_PLANE0 + i)"); + } + + if (!warned && stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE]) + { + FIXME("Clipping not supported with vertex shaders\n"); + warned = TRUE; + } + } + if(wasrhw) { + /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex + * shaders themselves do not need it, but the matrices are not reapplied automatically when + * switching back from vertex shaders to fixed function processing. So make sure we leave the + * fixed function vertex processing states back in a sane state before switching to shaders + */ + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) { + transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); + } + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) { + transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context); + } + } + updateFog = TRUE; + + /* Vertex shader clipping ignores the view matrix. Update all clipplanes + * (Note: ARB shaders can read the clip planes for clipping emulation even if + * device->vs_clipping is false. + */ + for (i = 0; i < gl_info->limits.clipplanes; ++i) + { + clipplane(STATE_CLIPPLANE(i), stateblock, context); + } + } + } + + /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the + * application + */ + if (!isStateDirty(context, STATE_PIXELSHADER)) { + device->shader_backend->shader_select(context, usePixelShaderFunction, useVertexShaderFunction); + + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) { + shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); + } + } + + context->last_was_vshader = useVertexShaderFunction; + + if (updateFog) stateblock_apply_state(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context); + + if(!useVertexShaderFunction) { + int i; + for(i = 0; i < MAX_TEXTURES; i++) { + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) { + transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context); + } + } + } +} + +static void viewport_miscpart(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + struct wined3d_surface *target = stateblock->device->fb.render_targets[0]; + UINT width, height; + WINED3DVIEWPORT vp = stateblock->state.viewport; + + if (vp.Width > target->resource.width) + vp.Width = target->resource.width; + if (vp.Height > target->resource.height) + vp.Height = target->resource.height; + + glDepthRange(vp.MinZ, vp.MaxZ); + checkGLcall("glDepthRange"); + /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering + */ + if (context->render_offscreen) + { + glViewport(vp.X, vp.Y, vp.Width, vp.Height); + } else { + target->get_drawable_size(context, &width, &height); + + glViewport(vp.X, + (height - (vp.Y + vp.Height)), + vp.Width, vp.Height); + } + + checkGLcall("glViewport"); +} + +static void viewport_vertexpart(DWORD state_id, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) { + transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); + } + if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) { + state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context); + } + /* Update the position fixup. */ + if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT)) + shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context); +} + +static void light(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + UINT Index = state - STATE_ACTIVELIGHT(0); + const struct wined3d_light_info *lightInfo = stateblock->state.lights[Index]; + + if(!lightInfo) { + glDisable(GL_LIGHT0 + Index); + checkGLcall("glDisable(GL_LIGHT0 + Index)"); + } else { + float quad_att; + float colRGBA[] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(&stateblock->state.transforms[WINED3DTS_VIEW].u.m[0][0]); + + /* Diffuse: */ + colRGBA[0] = lightInfo->OriginalParms.Diffuse.r; + colRGBA[1] = lightInfo->OriginalParms.Diffuse.g; + colRGBA[2] = lightInfo->OriginalParms.Diffuse.b; + colRGBA[3] = lightInfo->OriginalParms.Diffuse.a; + glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA); + checkGLcall("glLightfv"); + + /* Specular */ + colRGBA[0] = lightInfo->OriginalParms.Specular.r; + colRGBA[1] = lightInfo->OriginalParms.Specular.g; + colRGBA[2] = lightInfo->OriginalParms.Specular.b; + colRGBA[3] = lightInfo->OriginalParms.Specular.a; + glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA); + checkGLcall("glLightfv"); + + /* Ambient */ + colRGBA[0] = lightInfo->OriginalParms.Ambient.r; + colRGBA[1] = lightInfo->OriginalParms.Ambient.g; + colRGBA[2] = lightInfo->OriginalParms.Ambient.b; + colRGBA[3] = lightInfo->OriginalParms.Ambient.a; + glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA); + checkGLcall("glLightfv"); + + if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) { + quad_att = 1.4f/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range); + } else { + quad_att = 0.0f; /* 0 or MAX? (0 seems to be ok) */ + } + + /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk, + * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets + * Attenuation0 to NaN and crashes in the gl lib + */ + + switch (lightInfo->OriginalParms.Type) { + case WINED3DLIGHT_POINT: + /* Position */ + glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); + checkGLcall("glLightfv"); + glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff); + checkGLcall("glLightf"); + /* Attenuation - Are these right? guessing... */ + glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0); + checkGLcall("glLightf"); + glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1); + checkGLcall("glLightf"); + if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2; + glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att); + checkGLcall("glLightf"); + /* FIXME: Range */ + break; + + case WINED3DLIGHT_SPOT: + /* Position */ + glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); + checkGLcall("glLightfv"); + /* Direction */ + glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]); + checkGLcall("glLightfv"); + glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent); + checkGLcall("glLightf"); + glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff); + checkGLcall("glLightf"); + /* Attenuation - Are these right? guessing... */ + glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0); + checkGLcall("glLightf"); + glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1); + checkGLcall("glLightf"); + if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2; + glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att); + checkGLcall("glLightf"); + /* FIXME: Range */ + break; + + case WINED3DLIGHT_DIRECTIONAL: + /* Direction */ + glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */ + checkGLcall("glLightfv"); + glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff); + checkGLcall("glLightf"); + glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f); + checkGLcall("glLightf"); + break; + + default: + FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type); + } + + /* Restore the modelview matrix */ + glPopMatrix(); + + glEnable(GL_LIGHT0 + Index); + checkGLcall("glEnable(GL_LIGHT0 + Index)"); + } +} + +static void scissorrect(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + struct wined3d_surface *target = stateblock->device->fb.render_targets[0]; + RECT *pRect = &stateblock->state.scissor_rect; + UINT height; + UINT width; + + target->get_drawable_size(context, &width, &height); + /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply + * Warning2: Even in windowed mode the coords are relative to the window, not the screen + */ + TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->device, pRect->left, pRect->bottom - height, + pRect->right - pRect->left, pRect->bottom - pRect->top); + + if (context->render_offscreen) + { + glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top); + } else { + glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top); + } + checkGLcall("glScissor"); +} + +static void indexbuffer(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + + if (stateblock->state.user_stream || !stateblock->state.index_buffer) + { + GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0)); + } + else + { + struct wined3d_buffer *ib = stateblock->state.index_buffer; + GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object)); + } +} + +static void frontface(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + if (context->render_offscreen) + { + glFrontFace(GL_CCW); + checkGLcall("glFrontFace(GL_CCW)"); + } else { + glFrontFace(GL_CW); + checkGLcall("glFrontFace(GL_CW)"); + } +} + +static void psorigin_w(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + static BOOL warned; + + if (!warned) + { + WARN("Point sprite coordinate origin switching not supported.\n"); + warned = TRUE; + } +} + +static void psorigin(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + GLint origin = context->render_offscreen ? GL_LOWER_LEFT : GL_UPPER_LEFT; + + if (glPointParameteri) + { + glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, origin); + checkGLcall("glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, ...)"); + } + else if (gl_info->supported[NV_POINT_SPRITE]) + { + GL_EXTCALL(glPointParameteriNV(GL_POINT_SPRITE_COORD_ORIGIN, origin)); + checkGLcall("glPointParameteriNV(GL_POINT_SPRITE_COORD_ORIGIN, ...)"); + } +} + +const struct StateEntryTemplate misc_state_template[] = { + { STATE_RENDER(WINED3DRS_SRCBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLEND), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_blend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EDGEANTIALIAS), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRCBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DESTBLENDALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BLENDOPALPHA), { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_STREAMSRC, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_VDECL, { STATE_VDECL, streamsrc }, WINED3D_GL_EXT_NONE }, + { STATE_FRONTFACE, { STATE_FRONTFACE, frontface }, WINED3D_GL_EXT_NONE }, + { STATE_SCISSORRECT, { STATE_SCISSORRECT, scissorrect }, WINED3D_GL_EXT_NONE }, + { STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, psorigin }, WINED3D_GL_VERSION_2_0 }, + { STATE_POINTSPRITECOORDORIGIN, { STATE_POINTSPRITECOORDORIGIN, psorigin_w }, WINED3D_GL_EXT_NONE }, + + /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and + * vshader loadings are untied from each other + */ + { STATE_VERTEXSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, shaderconstant }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADERCONSTANT, { STATE_VERTEXSHADERCONSTANT, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), shader_bumpenvmat }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), tex_bumpenvlscale }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET), { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE), NULL }, WINED3D_GL_EXT_NONE }, + + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_miscpart }, WINED3D_GL_EXT_NONE }, + { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, indexbuffer }, ARB_VERTEX_BUFFER_OBJECT }, + { STATE_INDEXBUFFER, { STATE_INDEXBUFFER, state_nop }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANTIALIAS), { STATE_RENDER(WINED3DRS_ANTIALIAS), state_antialias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE), state_perspective }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZENABLE), { STATE_RENDER(WINED3DRS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAPU), { STATE_RENDER(WINED3DRS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAPV), { STATE_RENDER(WINED3DRS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FILLMODE), { STATE_RENDER(WINED3DRS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SHADEMODE), { STATE_RENDER(WINED3DRS_SHADEMODE), state_shademode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LINEPATTERN), { STATE_RENDER(WINED3DRS_LINEPATTERN), state_linepattern }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MONOENABLE), { STATE_RENDER(WINED3DRS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ROP2), { STATE_RENDER(WINED3DRS_ROP2), state_rop2 }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PLANEMASK), { STATE_RENDER(WINED3DRS_PLANEMASK), state_planemask }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZWRITEENABLE), { STATE_RENDER(WINED3DRS_ZWRITEENABLE), state_zwritenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), state_alpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAREF), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ALPHAFUNC), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORKEYENABLE), { STATE_RENDER(WINED3DRS_ALPHATESTENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LASTPIXEL), { STATE_RENDER(WINED3DRS_LASTPIXEL), state_lastpixel }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CULLMODE), { STATE_RENDER(WINED3DRS_CULLMODE), state_cullmode }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZFUNC), { STATE_RENDER(WINED3DRS_ZFUNC), state_zfunc }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DITHERENABLE), { STATE_RENDER(WINED3DRS_DITHERENABLE), state_ditherenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SUBPIXEL), { STATE_RENDER(WINED3DRS_SUBPIXEL), state_subpixel }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SUBPIXELX), { STATE_RENDER(WINED3DRS_SUBPIXELX), state_subpixelx }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), { STATE_RENDER(WINED3DRS_STIPPLEDALPHA), state_stippledalpha }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STIPPLEENABLE), { STATE_RENDER(WINED3DRS_STIPPLEENABLE), state_stippleenable }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS), state_mipmaplodbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ANISOTROPY), { STATE_RENDER(WINED3DRS_ANISOTROPY), state_anisotropy }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FLUSHBATCH), { STATE_RENDER(WINED3DRS_FLUSHBATCH), state_flushbatch }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILENABLE), { STATE_RENDER(WINED3DRS_STENCILENABLE), state_stencil }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILREF), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILMASK), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE }, + { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), { STATE_RENDER(WINED3DRS_STENCILWRITEMASK), state_stencilwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILPASS), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC), { STATE_RENDER(WINED3DRS_STENCILENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP0), { STATE_RENDER(WINED3DRS_WRAP0), state_wrap }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP1), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP2), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP3), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP4), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP5), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP6), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP7), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP8), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP9), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP10), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP11), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP12), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP13), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP14), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_WRAP15), { STATE_RENDER(WINED3DRS_WRAP0), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EXTENTS), { STATE_RENDER(WINED3DRS_EXTENTS), state_extents }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE), state_ckeyblend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), { STATE_RENDER(WINED3DRS_SOFTWAREVERTEXPROCESSING), state_swvp }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE), state_patchedgestyle}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), { STATE_RENDER(WINED3DRS_PATCHSEGMENTS), state_patchsegments }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POSITIONDEGREE), { STATE_RENDER(WINED3DRS_POSITIONDEGREE), state_positiondegree}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_NORMALDEGREE), { STATE_RENDER(WINED3DRS_NORMALDEGREE), state_normaldegree }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_nvdb }, EXT_DEPTH_BOUNDS_TEST }, + { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa }, ARB_MULTISAMPLE }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS), state_msaa_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK), state_multisampmask }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), { STATE_RENDER(WINED3DRS_DEBUGMONITORTOKEN), state_debug_monitor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite0 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), state_colorwrite }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop }, EXT_BLEND_MINMAX }, + { STATE_RENDER(WINED3DRS_BLENDOP), { STATE_RENDER(WINED3DRS_BLENDOP), state_blendop_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_scissor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), state_colorwrite1 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), state_colorwrite2 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), state_colorwrite3 }, EXT_DRAW_BUFFERS2 }, + { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3), { STATE_RENDER(WINED3DRS_COLORWRITEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor }, EXT_BLEND_COLOR }, + { STATE_RENDER(WINED3DRS_BLENDFACTOR), { STATE_RENDER(WINED3DRS_BLENDFACTOR), state_blendfactor_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DEPTHBIAS), { STATE_RENDER(WINED3DRS_DEPTHBIAS), state_depthbias }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_ZVISIBLE), { STATE_RENDER(WINED3DRS_ZVISIBLE), state_zvisible }, WINED3D_GL_EXT_NONE }, + /* Samplers */ + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(8), { STATE_SAMPLER(8), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(9), { STATE_SAMPLER(9), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(10), { STATE_SAMPLER(10), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(11), { STATE_SAMPLER(11), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(12), { STATE_SAMPLER(12), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(13), { STATE_SAMPLER(13), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(14), { STATE_SAMPLER(14), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(15), { STATE_SAMPLER(15), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(16), /* Vertex sampler 0 */ { STATE_SAMPLER(16), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(17), /* Vertex sampler 1 */ { STATE_SAMPLER(17), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(18), /* Vertex sampler 2 */ { STATE_SAMPLER(18), sampler }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, +}; + +const struct StateEntryTemplate ffp_vertexstate_template[] = { + { STATE_VDECL, { STATE_VDECL, vertexdeclaration }, WINED3D_GL_EXT_NONE }, + { STATE_VSHADER, { STATE_VDECL, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_MATERIAL, { STATE_RENDER(WINED3DRS_SPECULARENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SPECULARENABLE), { STATE_RENDER(WINED3DRS_SPECULARENABLE), state_specularenable}, WINED3D_GL_EXT_NONE }, + /* Clip planes */ + { STATE_CLIPPLANE(0), { STATE_CLIPPLANE(0), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(1), { STATE_CLIPPLANE(1), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(2), { STATE_CLIPPLANE(2), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(3), { STATE_CLIPPLANE(3), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(4), { STATE_CLIPPLANE(4), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(5), { STATE_CLIPPLANE(5), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(6), { STATE_CLIPPLANE(6), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(7), { STATE_CLIPPLANE(7), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(8), { STATE_CLIPPLANE(8), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(9), { STATE_CLIPPLANE(9), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(10), { STATE_CLIPPLANE(10), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(11), { STATE_CLIPPLANE(11), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(12), { STATE_CLIPPLANE(12), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(13), { STATE_CLIPPLANE(13), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(14), { STATE_CLIPPLANE(14), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(15), { STATE_CLIPPLANE(15), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(16), { STATE_CLIPPLANE(16), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(17), { STATE_CLIPPLANE(17), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(18), { STATE_CLIPPLANE(18), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(19), { STATE_CLIPPLANE(19), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(20), { STATE_CLIPPLANE(20), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(21), { STATE_CLIPPLANE(21), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(22), { STATE_CLIPPLANE(22), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(23), { STATE_CLIPPLANE(23), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(24), { STATE_CLIPPLANE(24), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(25), { STATE_CLIPPLANE(25), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(26), { STATE_CLIPPLANE(26), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(27), { STATE_CLIPPLANE(27), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(28), { STATE_CLIPPLANE(28), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(29), { STATE_CLIPPLANE(29), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(30), { STATE_CLIPPLANE(30), clipplane }, WINED3D_GL_EXT_NONE }, + { STATE_CLIPPLANE(31), { STATE_CLIPPLANE(31), clipplane }, WINED3D_GL_EXT_NONE }, + /* Lights */ + { STATE_ACTIVELIGHT(0), { STATE_ACTIVELIGHT(0), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(1), { STATE_ACTIVELIGHT(1), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(2), { STATE_ACTIVELIGHT(2), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(3), { STATE_ACTIVELIGHT(3), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(4), { STATE_ACTIVELIGHT(4), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(5), { STATE_ACTIVELIGHT(5), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(6), { STATE_ACTIVELIGHT(6), light }, WINED3D_GL_EXT_NONE }, + { STATE_ACTIVELIGHT(7), { STATE_ACTIVELIGHT(7), light }, WINED3D_GL_EXT_NONE }, + /* Viewport */ + { STATE_VIEWPORT, { STATE_VIEWPORT, viewport_vertexpart }, WINED3D_GL_EXT_NONE }, + /* Transform states follow */ + { STATE_TRANSFORM(WINED3DTS_VIEW), { STATE_TRANSFORM(WINED3DTS_VIEW), transform_view }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_PROJECTION), { STATE_TRANSFORM(WINED3DTS_PROJECTION), transform_projection}, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE0), { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE1), { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE2), { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE3), { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE4), { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE5), { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE6), { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_TEXTURE7), { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 0)), transform_world }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 1)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 2)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 3)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 4)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 5)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 6)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 7)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 8)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 9)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX), tex_coordindex }, WINED3D_GL_EXT_NONE }, + /* Fog */ + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_vertexpart}, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog }, NV_FOG_DISTANCE }, + { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), { STATE_RENDER(WINED3DRS_RANGEFOGENABLE), state_rangefog_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CLIPPING), { STATE_RENDER(WINED3DRS_CLIPPING), state_clipping }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), { STATE_RENDER(WINED3DRS_CLIPPING), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LIGHTING), { STATE_RENDER(WINED3DRS_LIGHTING), state_lighting }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_AMBIENT), { STATE_RENDER(WINED3DRS_AMBIENT), state_ambient }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_COLORVERTEX), { STATE_RENDER(WINED3DRS_COLORVERTEX), state_colormat }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_LOCALVIEWER), { STATE_RENDER(WINED3DRS_LOCALVIEWER), state_localviewer }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), { STATE_RENDER(WINED3DRS_NORMALIZENORMALS), state_normalize }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE), { STATE_RENDER(WINED3DRS_COLORVERTEX), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend }, ARB_VERTEX_BLEND }, + { STATE_RENDER(WINED3DRS_VERTEXBLEND), { STATE_RENDER(WINED3DRS_VERTEXBLEND), state_vertexblend_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_arb }, ARB_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_ext }, EXT_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), state_psizemin_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite }, ARB_POINT_SPRITE }, + { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE), state_pointsprite_w }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), state_pscale }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_A), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_B), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSCALE_C), { STATE_RENDER(WINED3DRS_POINTSCALEENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, ARB_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, EXT_POINT_PARAMETERS }, + { STATE_RENDER(WINED3DRS_POINTSIZE_MAX), { STATE_RENDER(WINED3DRS_POINTSIZE_MIN), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TWEENFACTOR), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_INDEXEDVERTEXBLENDENABLE), { STATE_RENDER(WINED3DRS_VERTEXBLEND), NULL }, WINED3D_GL_EXT_NONE }, + + /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported, + * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states. + * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix + */ + { STATE_SAMPLER(0), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(0), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(1), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(2), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(3), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(4), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(5), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(6), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { 0, NULL }, ARB_TEXTURE_NON_POWER_OF_TWO }, + { STATE_SAMPLER(7), { 0, NULL }, WINED3D_GL_NORMALIZED_TEXRECT }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texmatrix }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, +}; + +static const struct StateEntryTemplate ffp_fragmentstate_template[] = { + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), tex_colorop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), tex_alphaop }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0), { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG), { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT), { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_PIXELSHADER, { STATE_PIXELSHADER, apply_pixelshader }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), { STATE_RENDER(WINED3DRS_TEXTUREFACTOR), state_texfactor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGCOLOR), { STATE_RENDER(WINED3DRS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGDENSITY), { STATE_RENDER(WINED3DRS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGENABLE), { STATE_RENDER(WINED3DRS_FOGENABLE), state_fog_fragpart }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGTABLEMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGVERTEXMODE), { STATE_RENDER(WINED3DRS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGSTART), { STATE_RENDER(WINED3DRS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, + { STATE_RENDER(WINED3DRS_FOGEND), { STATE_RENDER(WINED3DRS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(0), { STATE_SAMPLER(0), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(1), { STATE_SAMPLER(1), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(2), { STATE_SAMPLER(2), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(3), { STATE_SAMPLER(3), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(4), { STATE_SAMPLER(4), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(5), { STATE_SAMPLER(5), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(6), { STATE_SAMPLER(6), sampler_texdim }, WINED3D_GL_EXT_NONE }, + { STATE_SAMPLER(7), { STATE_SAMPLER(7), sampler_texdim }, WINED3D_GL_EXT_NONE }, + {0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE }, +}; + +/* Context activation and GL locking are done by the caller. */ +static void ffp_enable(BOOL enable) {} + +static void ffp_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps) +{ + caps->PrimitiveMiscCaps = 0; + caps->TextureOpCaps = WINED3DTEXOPCAPS_ADD + | WINED3DTEXOPCAPS_ADDSIGNED + | WINED3DTEXOPCAPS_ADDSIGNED2X + | WINED3DTEXOPCAPS_MODULATE + | WINED3DTEXOPCAPS_MODULATE2X + | WINED3DTEXOPCAPS_MODULATE4X + | WINED3DTEXOPCAPS_SELECTARG1 + | WINED3DTEXOPCAPS_SELECTARG2 + | WINED3DTEXOPCAPS_DISABLE; + + if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE] + || gl_info->supported[EXT_TEXTURE_ENV_COMBINE] + || gl_info->supported[NV_TEXTURE_ENV_COMBINE4]) + { + caps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA + | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA + | WINED3DTEXOPCAPS_BLENDFACTORALPHA + | WINED3DTEXOPCAPS_BLENDCURRENTALPHA + | WINED3DTEXOPCAPS_LERP + | WINED3DTEXOPCAPS_SUBTRACT; + } + if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] + || gl_info->supported[NV_TEXTURE_ENV_COMBINE4]) + { + caps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH + | WINED3DTEXOPCAPS_MULTIPLYADD + | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR + | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA + | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM; + } + if (gl_info->supported[ARB_TEXTURE_ENV_DOT3]) + caps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3; + + caps->MaxTextureBlendStages = gl_info->limits.textures; + caps->MaxSimultaneousTextures = gl_info->limits.textures; +} + +static HRESULT ffp_fragment_alloc(struct wined3d_device *device) { return WINED3D_OK; } +static void ffp_fragment_free(struct wined3d_device *device) {} +static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup) +{ + if (TRACE_ON(d3d)) + { + TRACE("Checking support for fixup:\n"); + dump_color_fixup_desc(fixup); + } + + /* We only support identity conversions. */ + if (is_identity_fixup(fixup)) + { + TRACE("[OK]\n"); + return TRUE; + } + + TRACE("[FAILED]\n"); + return FALSE; +} + +const struct fragment_pipeline ffp_fragment_pipeline = { + ffp_enable, + ffp_fragment_get_caps, + ffp_fragment_alloc, + ffp_fragment_free, + ffp_color_fixup_supported, + ffp_fragmentstate_template, + FALSE /* we cannot disable projected textures. The vertex pipe has to do it */ +}; + +static unsigned int num_handlers(const APPLYSTATEFUNC *funcs) +{ + unsigned int i; + for(i = 0; funcs[i]; i++); + return i; +} + +static void multistate_apply_2(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + stateblock->device->multistate_funcs[state][0](state, stateblock, context); + stateblock->device->multistate_funcs[state][1](state, stateblock, context); +} + +static void multistate_apply_3(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context) +{ + stateblock->device->multistate_funcs[state][0](state, stateblock, context); + stateblock->device->multistate_funcs[state][1](state, stateblock, context); + stateblock->device->multistate_funcs[state][2](state, stateblock, context); +} + +static void prune_invalid_states(struct StateEntry *state_table, const struct wined3d_gl_info *gl_info) +{ + unsigned int start, last, i; + + start = STATE_TEXTURESTAGE(gl_info->limits.texture_stages, 0); + last = STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE); + for (i = start; i <= last; ++i) + { + state_table[i].representative = 0; + state_table[i].apply = state_undefined; + } + + start = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + gl_info->limits.texture_stages); + last = STATE_TRANSFORM(WINED3DTS_TEXTURE0 + MAX_TEXTURES - 1); + for (i = start; i <= last; ++i) + { + state_table[i].representative = 0; + state_table[i].apply = state_undefined; + } + + start = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(gl_info->limits.blends)); + last = STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)); + for (i = start; i <= last; ++i) + { + state_table[i].representative = 0; + state_table[i].apply = state_undefined; + } +} + +static void validate_state_table(struct StateEntry *state_table) +{ + static const struct + { + DWORD first; + DWORD last; + } + rs_holes[] = + { + { 1, 1}, + { 3, 3}, + { 17, 18}, + { 21, 21}, + { 42, 45}, + { 47, 47}, + { 61, 127}, + {149, 150}, + {169, 169}, + {177, 177}, + {196, 197}, + { 0, 0}, + }; + static const DWORD simple_states[] = + { + STATE_MATERIAL, + STATE_VDECL, + STATE_STREAMSRC, + STATE_INDEXBUFFER, + STATE_VERTEXSHADERCONSTANT, + STATE_PIXELSHADERCONSTANT, + STATE_VSHADER, + STATE_PIXELSHADER, + STATE_VIEWPORT, + STATE_SCISSORRECT, + STATE_FRONTFACE, + STATE_POINTSPRITECOORDORIGIN, + }; + unsigned int i, current; + + for (i = STATE_RENDER(1), current = 0; i <= STATE_RENDER(WINEHIGHEST_RENDER_STATE); ++i) + { + if (!rs_holes[current].first || i < STATE_RENDER(rs_holes[current].first)) + { + if (!state_table[i].representative) + ERR("State %s (%#x) should have a representative.\n", debug_d3dstate(i), i); + } + else if (state_table[i].representative) + ERR("State %s (%#x) shouldn't have a representative.\n", debug_d3dstate(i), i); + + if (i == STATE_RENDER(rs_holes[current].last)) ++current; + } + + for (i = 0; i < sizeof(simple_states) / sizeof(*simple_states); ++i) + { + if (!state_table[simple_states[i]].representative) + ERR("State %s (%#x) should have a representative.\n", + debug_d3dstate(simple_states[i]), simple_states[i]); + } + + for (i = 0; i < STATE_HIGHEST + 1; ++i) + { + DWORD rep = state_table[i].representative; + if (rep) + { + if (state_table[rep].representative != rep) + { + ERR("State %s (%#x) has invalid representative %s (%#x).\n", + debug_d3dstate(i), i, debug_d3dstate(rep), rep); + state_table[i].representative = 0; + } + + if (rep != i) + { + if (state_table[i].apply) + ERR("State %s (%#x) has both a handler and representative.\n", debug_d3dstate(i), i); + } + else if (!state_table[i].apply) + { + ERR("Self representing state %s (%#x) has no handler.\n", debug_d3dstate(i), i); + } + } + } +} + +HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, + const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex, + const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) +{ + unsigned int i, type, handlers; + APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3]; + const struct StateEntryTemplate *cur; + BOOL set[STATE_HIGHEST + 1]; + + memset(multistate_funcs, 0, sizeof(multistate_funcs)); + + for(i = 0; i < STATE_HIGHEST + 1; i++) { + StateTable[i].representative = 0; + StateTable[i].apply = state_undefined; + } + + for(type = 0; type < 3; type++) { + /* This switch decides the order in which the states are applied */ + switch(type) { + case 0: cur = misc; break; + case 1: cur = fragment->states; break; + case 2: cur = vertex; break; + default: cur = NULL; /* Stupid compiler */ + } + if(!cur) continue; + + /* GL extension filtering should not prevent multiple handlers being applied from different + * pipeline parts + */ + memset(set, 0, sizeof(set)); + + for(i = 0; cur[i].state; i++) { + APPLYSTATEFUNC *funcs_array; + + /* Only use the first matching state with the available extension from one template. + * e.g. + * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY}, + * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0 } + * + * if GL_XYZ_fancy is supported, ignore the 2nd line + */ + if(set[cur[i].state]) continue; + /* Skip state lines depending on unsupported extensions */ + if (!gl_info->supported[cur[i].extension]) continue; + set[cur[i].state] = TRUE; + /* In some cases having an extension means that nothing has to be + * done for a state, e.g. if GL_ARB_texture_non_power_of_two is + * supported, the texture coordinate fixup can be ignored. If the + * apply function is used, mark the state set(done above) to prevent + * applying later lines, but do not record anything in the state + * table + */ + if (!cur[i].content.representative) continue; + + handlers = num_handlers(multistate_funcs[cur[i].state]); + multistate_funcs[cur[i].state][handlers] = cur[i].content.apply; + switch(handlers) { + case 0: + StateTable[cur[i].state].apply = cur[i].content.apply; + break; + case 1: + StateTable[cur[i].state].apply = multistate_apply_2; + dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(), + 0, + sizeof(**dev_multistate_funcs) * 2); + if (!dev_multistate_funcs[cur[i].state]) { + goto out_of_mem; + } + + dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0]; + dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1]; + break; + case 2: + StateTable[cur[i].state].apply = multistate_apply_3; + funcs_array = HeapReAlloc(GetProcessHeap(), + 0, + dev_multistate_funcs[cur[i].state], + sizeof(**dev_multistate_funcs) * 3); + if (!funcs_array) { + goto out_of_mem; + } + + dev_multistate_funcs[cur[i].state] = funcs_array; + dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2]; + break; + default: + ERR("Unexpected amount of state handlers for state %u: %u\n", + cur[i].state, handlers + 1); + } + + if(StateTable[cur[i].state].representative && + StateTable[cur[i].state].representative != cur[i].content.representative) { + FIXME("State %u has different representatives in different pipeline parts\n", + cur[i].state); + } + StateTable[cur[i].state].representative = cur[i].content.representative; + } + } + + prune_invalid_states(StateTable, gl_info); + validate_state_table(StateTable); + + return WINED3D_OK; + +out_of_mem: + for (i = 0; i <= STATE_HIGHEST; ++i) { + HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]); + } + + memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs)); + + return E_OUTOFMEMORY; +} diff --cc reactos/dll/directx/wine/wined3d/wined3d_private.h index aaf142339d7,00000000000..88c300d7ac1 mode 100644,000000..100644 --- a/reactos/dll/directx/wine/wined3d/wined3d_private.h +++ b/reactos/dll/directx/wine/wined3d/wined3d_private.h @@@ -1,2870 -1,0 +1,2870 @@@ +/* + * Direct3D wine internal private include file + * + * Copyright 2002-2003 The wine-d3d team + * Copyright 2002-2003 Raphael Junqueira + * Copyright 2002-2003, 2004 Jason Edmeades + * Copyright 2005 Oliver Stieber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINED3D_PRIVATE_H +#define __WINE_WINED3D_PRIVATE_H + +#include +#include +#include +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "wingdi.h" +#include "winuser.h" +#include "wine/debug.h" +#include "wine/unicode.h" + +#include "objbase.h" +#include "wine/wined3d.h" +#include "wined3d_gl.h" +#include "wine/list.h" +#include "wine/rbtree.h" + +/* Driver quirks */ +#define WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT 0x00000001 +#define WINED3D_QUIRK_SET_TEXCOORD_W 0x00000002 +#define WINED3D_QUIRK_GLSL_CLIP_VARYING 0x00000004 +#define WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA 0x00000008 +#define WINED3D_QUIRK_NV_CLIP_BROKEN 0x00000010 +#define WINED3D_QUIRK_FBO_TEX_UPDATE 0x00000020 + +/* Texture format fixups */ + +enum fixup_channel_source +{ + CHANNEL_SOURCE_ZERO = 0, + CHANNEL_SOURCE_ONE = 1, + CHANNEL_SOURCE_X = 2, + CHANNEL_SOURCE_Y = 3, + CHANNEL_SOURCE_Z = 4, + CHANNEL_SOURCE_W = 5, + CHANNEL_SOURCE_COMPLEX0 = 6, + CHANNEL_SOURCE_COMPLEX1 = 7, +}; + +enum complex_fixup +{ + COMPLEX_FIXUP_NONE = 0, + COMPLEX_FIXUP_YUY2 = 1, + COMPLEX_FIXUP_UYVY = 2, + COMPLEX_FIXUP_YV12 = 3, + COMPLEX_FIXUP_P8 = 4, +}; + +#include +struct color_fixup_desc +{ + unsigned x_sign_fixup : 1; + unsigned x_source : 3; + unsigned y_sign_fixup : 1; + unsigned y_source : 3; + unsigned z_sign_fixup : 1; + unsigned z_source : 3; + unsigned w_sign_fixup : 1; + unsigned w_source : 3; +}; +#include + +static const struct color_fixup_desc COLOR_FIXUP_IDENTITY = + {0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W}; + +static inline struct color_fixup_desc create_color_fixup_desc( + int sign0, enum fixup_channel_source src0, int sign1, enum fixup_channel_source src1, + int sign2, enum fixup_channel_source src2, int sign3, enum fixup_channel_source src3) +{ + struct color_fixup_desc fixup = + { + sign0, src0, + sign1, src1, + sign2, src2, + sign3, src3, + }; + return fixup; +} + +static inline struct color_fixup_desc create_complex_fixup_desc(enum complex_fixup complex_fixup) +{ + struct color_fixup_desc fixup = + { + 0, complex_fixup & (1 << 0) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0, + 0, complex_fixup & (1 << 1) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0, + 0, complex_fixup & (1 << 2) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0, + 0, complex_fixup & (1 << 3) ? CHANNEL_SOURCE_COMPLEX1 : CHANNEL_SOURCE_COMPLEX0, + }; + return fixup; +} + +static inline BOOL is_identity_fixup(struct color_fixup_desc fixup) +{ + return !memcmp(&fixup, &COLOR_FIXUP_IDENTITY, sizeof(fixup)); +} + +static inline BOOL is_complex_fixup(struct color_fixup_desc fixup) +{ + return fixup.x_source == CHANNEL_SOURCE_COMPLEX0 || fixup.x_source == CHANNEL_SOURCE_COMPLEX1; +} + +static inline enum complex_fixup get_complex_fixup(struct color_fixup_desc fixup) +{ + enum complex_fixup complex_fixup = 0; + if (fixup.x_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 0); + if (fixup.y_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 1); + if (fixup.z_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 2); + if (fixup.w_source == CHANNEL_SOURCE_COMPLEX1) complex_fixup |= (1 << 3); + return complex_fixup; +} + +void *wined3d_rb_alloc(size_t size) DECLSPEC_HIDDEN; +void *wined3d_rb_realloc(void *ptr, size_t size) DECLSPEC_HIDDEN; +void wined3d_rb_free(void *ptr) DECLSPEC_HIDDEN; + +/* Device caps */ +#define MAX_PALETTES 65536 +#define MAX_STREAMS 16 +#define MAX_TEXTURES 8 +#define MAX_FRAGMENT_SAMPLERS 16 +#define MAX_VERTEX_SAMPLERS 4 +#define MAX_COMBINED_SAMPLERS (MAX_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS) +#define MAX_ACTIVE_LIGHTS 8 +#define MAX_CLIPPLANES WINED3DMAXUSERCLIPPLANES + +struct min_lookup +{ + GLenum mip[WINED3DTEXF_LINEAR + 1]; +}; + +extern const struct min_lookup minMipLookup[WINED3DTEXF_LINEAR + 1] DECLSPEC_HIDDEN; +extern const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_LINEAR + 1] DECLSPEC_HIDDEN; +extern const struct min_lookup minMipLookup_noMip[WINED3DTEXF_LINEAR + 1] DECLSPEC_HIDDEN; +extern const GLenum magLookup[WINED3DTEXF_LINEAR + 1] DECLSPEC_HIDDEN; +extern const GLenum magLookup_noFilter[WINED3DTEXF_LINEAR + 1] DECLSPEC_HIDDEN; + +static inline GLenum wined3d_gl_mag_filter(const GLenum mag_lookup[], WINED3DTEXTUREFILTERTYPE mag_filter) +{ + return mag_lookup[mag_filter]; +} + +static inline GLenum wined3d_gl_min_mip_filter(const struct min_lookup min_mip_lookup[], + WINED3DTEXTUREFILTERTYPE min_filter, WINED3DTEXTUREFILTERTYPE mip_filter) +{ + return min_mip_lookup[min_filter].mip[mip_filter]; +} + +/* float_16_to_32() and float_32_to_16() (see implementation in + * surface_base.c) convert 16 bit floats in the FLOAT16 data type + * to standard C floats and vice versa. They do not depend on the encoding + * of the C float, so they are platform independent, but slow. On x86 and + * other IEEE 754 compliant platforms the conversion can be accelerated by + * bit shifting the exponent and mantissa. There are also some SSE-based + * assembly routines out there. + * + * See GL_NV_half_float for a reference of the FLOAT16 / GL_HALF format + */ +static inline float float_16_to_32(const unsigned short *in) { + const unsigned short s = ((*in) & 0x8000); + const unsigned short e = ((*in) & 0x7C00) >> 10; + const unsigned short m = (*in) & 0x3FF; + const float sgn = (s ? -1.0f : 1.0f); + + if(e == 0) { + if(m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * powf(2, -14.0f) * ((float)m / 1024.0f); + } else if(e < 31) { + return sgn * powf(2, (float)e - 15.0f) * (1.0f + ((float)m / 1024.0f)); + } else { - if(m == 0) return sgn / 0.0f; /* +INF / -INF */ - else return 0.0f / 0.0f; /* NAN */ ++ if(m == 0) return sgn * INFINITY; /* +INF / -INF */ ++ else return NAN; + } +} + +static inline float float_24_to_32(DWORD in) +{ + const float sgn = in & 0x800000 ? -1.0f : 1.0f; + const unsigned short e = (in & 0x780000) >> 19; + const unsigned int m = in & 0x7ffff; + + if (e == 0) + { + if (m == 0) return sgn * 0.0f; /* +0.0 or -0.0 */ + else return sgn * powf(2, -6.0f) * ((float)m / 524288.0f); + } + else if (e < 15) + { + return sgn * powf(2, (float)e - 7.0f) * (1.0f + ((float)m / 524288.0f)); + } + else + { - if (m == 0) return sgn / 0.0f; /* +INF / -INF */ - else return 0.0f / 0.0f; /* NAN */ ++ if (m == 0) return sgn * INFINITY; /* +INF / -INF */ ++ else return NAN; + } +} + +/** + * Settings + */ +#define VS_NONE 0 +#define VS_HW 1 + +#define PS_NONE 0 +#define PS_HW 1 + +#define VBO_NONE 0 +#define VBO_HW 1 + +#define ORM_BACKBUFFER 0 +#define ORM_FBO 1 + +#define SHADER_ARB 1 +#define SHADER_GLSL 2 +#define SHADER_ATI 3 +#define SHADER_NONE 4 + +#define RTL_DISABLE -1 +#define RTL_READDRAW 1 +#define RTL_READTEX 2 + +#define PCI_VENDOR_NONE 0xffff /* e.g. 0x8086 for Intel and 0x10de for Nvidia */ +#define PCI_DEVICE_NONE 0xffff /* e.g. 0x14f for a Geforce6200 */ + +/* NOTE: When adding fields to this structure, make sure to update the default + * values in wined3d_main.c as well. */ +struct wined3d_settings +{ + /* vertex and pixel shader modes */ + int vs_mode; + int ps_mode; + /* Ideally, we don't want the user to have to request GLSL. If the + * hardware supports GLSL, we should use it. However, until it's fully + * implemented, we'll leave it as a registry setting for developers. */ + BOOL glslRequested; + int offscreen_rendering_mode; + int rendertargetlock_mode; + unsigned short pci_vendor_id; + unsigned short pci_device_id; + /* Memory tracking and object counting. */ + unsigned int emulated_textureram; + char *logo; + int allow_multisampling; + BOOL strict_draw_ordering; +}; + +extern struct wined3d_settings wined3d_settings DECLSPEC_HIDDEN; + +typedef enum _WINED3DSAMPLER_TEXTURE_TYPE +{ + WINED3DSTT_UNKNOWN = 0, + WINED3DSTT_1D = 1, + WINED3DSTT_2D = 2, + WINED3DSTT_CUBE = 3, + WINED3DSTT_VOLUME = 4, +} WINED3DSAMPLER_TEXTURE_TYPE; + +typedef enum _WINED3DSHADER_PARAM_REGISTER_TYPE +{ + WINED3DSPR_TEMP = 0, + WINED3DSPR_INPUT = 1, + WINED3DSPR_CONST = 2, + WINED3DSPR_ADDR = 3, + WINED3DSPR_TEXTURE = 3, + WINED3DSPR_RASTOUT = 4, + WINED3DSPR_ATTROUT = 5, + WINED3DSPR_TEXCRDOUT = 6, + WINED3DSPR_OUTPUT = 6, + WINED3DSPR_CONSTINT = 7, + WINED3DSPR_COLOROUT = 8, + WINED3DSPR_DEPTHOUT = 9, + WINED3DSPR_SAMPLER = 10, + WINED3DSPR_CONST2 = 11, + WINED3DSPR_CONST3 = 12, + WINED3DSPR_CONST4 = 13, + WINED3DSPR_CONSTBOOL = 14, + WINED3DSPR_LOOP = 15, + WINED3DSPR_TEMPFLOAT16 = 16, + WINED3DSPR_MISCTYPE = 17, + WINED3DSPR_LABEL = 18, + WINED3DSPR_PREDICATE = 19, + WINED3DSPR_IMMCONST, + WINED3DSPR_CONSTBUFFER, + WINED3DSPR_NULL, + WINED3DSPR_RESOURCE, +} WINED3DSHADER_PARAM_REGISTER_TYPE; + +enum wined3d_immconst_type +{ + WINED3D_IMMCONST_SCALAR, + WINED3D_IMMCONST_VEC4, +}; + +#define WINED3DSP_NOSWIZZLE (0 | (1 << 2) | (2 << 4) | (3 << 6)) + +typedef enum _WINED3DSHADER_PARAM_SRCMOD_TYPE +{ + WINED3DSPSM_NONE = 0, + WINED3DSPSM_NEG = 1, + WINED3DSPSM_BIAS = 2, + WINED3DSPSM_BIASNEG = 3, + WINED3DSPSM_SIGN = 4, + WINED3DSPSM_SIGNNEG = 5, + WINED3DSPSM_COMP = 6, + WINED3DSPSM_X2 = 7, + WINED3DSPSM_X2NEG = 8, + WINED3DSPSM_DZ = 9, + WINED3DSPSM_DW = 10, + WINED3DSPSM_ABS = 11, + WINED3DSPSM_ABSNEG = 12, + WINED3DSPSM_NOT = 13, +} WINED3DSHADER_PARAM_SRCMOD_TYPE; + +#define WINED3DSP_WRITEMASK_0 0x1 /* .x r */ +#define WINED3DSP_WRITEMASK_1 0x2 /* .y g */ +#define WINED3DSP_WRITEMASK_2 0x4 /* .z b */ +#define WINED3DSP_WRITEMASK_3 0x8 /* .w a */ +#define WINED3DSP_WRITEMASK_ALL 0xf /* all */ + +typedef enum _WINED3DSHADER_PARAM_DSTMOD_TYPE +{ + WINED3DSPDM_NONE = 0, + WINED3DSPDM_SATURATE = 1, + WINED3DSPDM_PARTIALPRECISION = 2, + WINED3DSPDM_MSAMPCENTROID = 4, +} WINED3DSHADER_PARAM_DSTMOD_TYPE; + +/* Undocumented opcode control to identify projective texture lookups in ps 2.0 and later */ +#define WINED3DSI_TEXLD_PROJECT 1 +#define WINED3DSI_TEXLD_BIAS 2 + +typedef enum COMPARISON_TYPE +{ + COMPARISON_GT = 1, + COMPARISON_EQ = 2, + COMPARISON_GE = 3, + COMPARISON_LT = 4, + COMPARISON_NE = 5, + COMPARISON_LE = 6, +} COMPARISON_TYPE; + +#define WINED3D_SM1_VS 0xfffe +#define WINED3D_SM1_PS 0xffff +#define WINED3D_SM4_PS 0x0000 +#define WINED3D_SM4_VS 0x0001 +#define WINED3D_SM4_GS 0x0002 + +/* Shader version tokens, and shader end tokens */ +#define WINED3DPS_VERSION(major, minor) ((WINED3D_SM1_PS << 16) | ((major) << 8) | (minor)) +#define WINED3DVS_VERSION(major, minor) ((WINED3D_SM1_VS << 16) | ((major) << 8) | (minor)) + +/* Shader backends */ + +/* TODO: Make this dynamic, based on shader limits ? */ +#define MAX_ATTRIBS 16 +#define MAX_REG_ADDR 1 +#define MAX_REG_TEMP 32 +#define MAX_REG_TEXCRD 8 +#define MAX_REG_INPUT 12 +#define MAX_REG_OUTPUT 12 +#define MAX_CONST_I 16 +#define MAX_CONST_B 16 + +/* FIXME: This needs to go up to 2048 for + * Shader model 3 according to msdn (and for software shaders) */ +#define MAX_LABELS 16 + +#define SHADER_PGMSIZE 65535 + +struct wined3d_shader_buffer +{ + char *buffer; + unsigned int bsize; + unsigned int lineNo; + BOOL newline; +}; + +enum WINED3D_SHADER_INSTRUCTION_HANDLER +{ + WINED3DSIH_ABS, + WINED3DSIH_ADD, + WINED3DSIH_AND, + WINED3DSIH_BEM, + WINED3DSIH_BREAK, + WINED3DSIH_BREAKC, + WINED3DSIH_BREAKP, + WINED3DSIH_CALL, + WINED3DSIH_CALLNZ, + WINED3DSIH_CMP, + WINED3DSIH_CND, + WINED3DSIH_CRS, + WINED3DSIH_CUT, + WINED3DSIH_DCL, + WINED3DSIH_DEF, + WINED3DSIH_DEFB, + WINED3DSIH_DEFI, + WINED3DSIH_DIV, + WINED3DSIH_DP2ADD, + WINED3DSIH_DP3, + WINED3DSIH_DP4, + WINED3DSIH_DST, + WINED3DSIH_DSX, + WINED3DSIH_DSY, + WINED3DSIH_ELSE, + WINED3DSIH_EMIT, + WINED3DSIH_ENDIF, + WINED3DSIH_ENDLOOP, + WINED3DSIH_ENDREP, + WINED3DSIH_EXP, + WINED3DSIH_EXPP, + WINED3DSIH_FRC, + WINED3DSIH_FTOI, + WINED3DSIH_IADD, + WINED3DSIH_IEQ, + WINED3DSIH_IF, + WINED3DSIH_IFC, + WINED3DSIH_IGE, + WINED3DSIH_IMUL, + WINED3DSIH_ITOF, + WINED3DSIH_LABEL, + WINED3DSIH_LD, + WINED3DSIH_LIT, + WINED3DSIH_LOG, + WINED3DSIH_LOGP, + WINED3DSIH_LOOP, + WINED3DSIH_LRP, + WINED3DSIH_LT, + WINED3DSIH_M3x2, + WINED3DSIH_M3x3, + WINED3DSIH_M3x4, + WINED3DSIH_M4x3, + WINED3DSIH_M4x4, + WINED3DSIH_MAD, + WINED3DSIH_MAX, + WINED3DSIH_MIN, + WINED3DSIH_MOV, + WINED3DSIH_MOVA, + WINED3DSIH_MOVC, + WINED3DSIH_MUL, + WINED3DSIH_NOP, + WINED3DSIH_NRM, + WINED3DSIH_PHASE, + WINED3DSIH_POW, + WINED3DSIH_RCP, + WINED3DSIH_REP, + WINED3DSIH_RET, + WINED3DSIH_RSQ, + WINED3DSIH_SAMPLE, + WINED3DSIH_SAMPLE_GRAD, + WINED3DSIH_SAMPLE_LOD, + WINED3DSIH_SETP, + WINED3DSIH_SGE, + WINED3DSIH_SGN, + WINED3DSIH_SINCOS, + WINED3DSIH_SLT, + WINED3DSIH_SQRT, + WINED3DSIH_SUB, + WINED3DSIH_TEX, + WINED3DSIH_TEXBEM, + WINED3DSIH_TEXBEML, + WINED3DSIH_TEXCOORD, + WINED3DSIH_TEXDEPTH, + WINED3DSIH_TEXDP3, + WINED3DSIH_TEXDP3TEX, + WINED3DSIH_TEXKILL, + WINED3DSIH_TEXLDD, + WINED3DSIH_TEXLDL, + WINED3DSIH_TEXM3x2DEPTH, + WINED3DSIH_TEXM3x2PAD, + WINED3DSIH_TEXM3x2TEX, + WINED3DSIH_TEXM3x3, + WINED3DSIH_TEXM3x3DIFF, + WINED3DSIH_TEXM3x3PAD, + WINED3DSIH_TEXM3x3SPEC, + WINED3DSIH_TEXM3x3TEX, + WINED3DSIH_TEXM3x3VSPEC, + WINED3DSIH_TEXREG2AR, + WINED3DSIH_TEXREG2GB, + WINED3DSIH_TEXREG2RGB, + WINED3DSIH_UTOF, + WINED3DSIH_TABLE_SIZE +}; + +enum wined3d_shader_type +{ + WINED3D_SHADER_TYPE_PIXEL, + WINED3D_SHADER_TYPE_VERTEX, + WINED3D_SHADER_TYPE_GEOMETRY, +}; + +struct wined3d_shader_version +{ + enum wined3d_shader_type type; + BYTE major; + BYTE minor; +}; + +#define WINED3D_SHADER_VERSION(major, minor) (((major) << 8) | (minor)) + +struct wined3d_shader_reg_maps +{ + struct wined3d_shader_version shader_version; + BYTE texcoord; /* MAX_REG_TEXCRD, 8 */ + BYTE address; /* MAX_REG_ADDR, 1 */ + WORD labels; /* MAX_LABELS, 16 */ + DWORD temporary; /* MAX_REG_TEMP, 32 */ + DWORD *constf; /* pixel, vertex */ + DWORD texcoord_mask[MAX_REG_TEXCRD]; /* vertex < 3.0 */ + WORD input_registers; /* max(MAX_REG_INPUT, MAX_ATTRIBS), 16 */ + WORD output_registers; /* MAX_REG_OUTPUT, 12 */ + WORD integer_constants; /* MAX_CONST_I, 16 */ + WORD boolean_constants; /* MAX_CONST_B, 16 */ + WORD local_int_consts; /* MAX_CONST_I, 16 */ + WORD local_bool_consts; /* MAX_CONST_B, 16 */ + + WINED3DSAMPLER_TEXTURE_TYPE sampler_type[max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS)]; + BYTE bumpmat; /* MAX_TEXTURES, 8 */ + BYTE luminanceparams; /* MAX_TEXTURES, 8 */ + + WORD usesnrm : 1; + WORD vpos : 1; + WORD usesdsx : 1; + WORD usesdsy : 1; + WORD usestexldd : 1; + WORD usesmova : 1; + WORD usesfacing : 1; + WORD usesrelconstF : 1; + WORD fog : 1; + WORD usestexldl : 1; + WORD usesifc : 1; + WORD usescall : 1; + WORD usespow : 1; + WORD padding : 3; + + DWORD rt_mask; /* Used render targets, 32 max. */ + + /* Whether or not loops are used in this shader, and nesting depth */ + unsigned loop_depth; + UINT min_rel_offset, max_rel_offset; +}; + +/* Keeps track of details for TEX_M#x# instructions which need to maintain + * state information between multiple instructions. */ +struct wined3d_shader_tex_mx +{ + unsigned int current_row; + DWORD texcoord_w[2]; +}; + +struct wined3d_shader_loop_state +{ + UINT current_depth; + UINT current_reg; +}; + +struct wined3d_shader_context +{ + struct wined3d_shader *shader; + const struct wined3d_gl_info *gl_info; + const struct wined3d_shader_reg_maps *reg_maps; + struct wined3d_shader_buffer *buffer; + struct wined3d_shader_tex_mx *tex_mx; + struct wined3d_shader_loop_state *loop_state; + void *backend_data; +}; + +struct wined3d_shader_register +{ + WINED3DSHADER_PARAM_REGISTER_TYPE type; + UINT idx; + UINT array_idx; + const struct wined3d_shader_src_param *rel_addr; + enum wined3d_immconst_type immconst_type; + DWORD immconst_data[4]; +}; + +struct wined3d_shader_dst_param +{ + struct wined3d_shader_register reg; + DWORD write_mask; + DWORD modifiers; + DWORD shift; +}; + +struct wined3d_shader_src_param +{ + struct wined3d_shader_register reg; + DWORD swizzle; + DWORD modifiers; +}; + +struct wined3d_shader_instruction +{ + const struct wined3d_shader_context *ctx; + enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx; + DWORD flags; + BOOL coissue; + DWORD predicate; + UINT dst_count; + const struct wined3d_shader_dst_param *dst; + UINT src_count; + const struct wined3d_shader_src_param *src; +}; + +struct wined3d_shader_semantic +{ + WINED3DDECLUSAGE usage; + UINT usage_idx; + WINED3DSAMPLER_TEXTURE_TYPE sampler_type; + struct wined3d_shader_dst_param reg; +}; + +struct wined3d_shader_attribute +{ + WINED3DDECLUSAGE usage; + UINT usage_idx; +}; + +struct wined3d_shader_loop_control +{ + unsigned int count; + unsigned int start; + int step; +}; + +struct wined3d_shader_frontend +{ + void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature); + void (*shader_free)(void *data); + void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version); + void (*shader_read_opcode)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins, UINT *param_size); + void (*shader_read_src_param)(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param, + struct wined3d_shader_src_param *src_rel_addr); + void (*shader_read_dst_param)(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param, + struct wined3d_shader_src_param *dst_rel_addr); + void (*shader_read_semantic)(const DWORD **ptr, struct wined3d_shader_semantic *semantic); + void (*shader_read_comment)(const DWORD **ptr, const char **comment, UINT *comment_size); + BOOL (*shader_is_end)(void *data, const DWORD **ptr); +}; + +extern const struct wined3d_shader_frontend sm1_shader_frontend DECLSPEC_HIDDEN; +extern const struct wined3d_shader_frontend sm4_shader_frontend DECLSPEC_HIDDEN; + +typedef void (*SHADER_HANDLER)(const struct wined3d_shader_instruction *); + +struct shader_caps { + DWORD VertexShaderVersion; + DWORD MaxVertexShaderConst; + + DWORD PixelShaderVersion; + float PixelShader1xMaxValue; + DWORD MaxPixelShaderConst; + + BOOL VSClipping; +}; + +enum tex_types +{ + tex_1d = 0, + tex_2d = 1, + tex_3d = 2, + tex_cube = 3, + tex_rect = 4, + tex_type_count = 5, +}; + +enum vertexprocessing_mode { + fixedfunction, + vertexshader, + pretransformed +}; + +#define WINED3D_CONST_NUM_UNUSED ~0U + +enum fogmode { + FOG_OFF, + FOG_LINEAR, + FOG_EXP, + FOG_EXP2 +}; + +/* Stateblock dependent parameters which have to be hardcoded + * into the shader code + */ + +#define WINED3D_PSARGS_PROJECTED (1 << 3) +#define WINED3D_PSARGS_TEXTRANSFORM_SHIFT 4 +#define WINED3D_PSARGS_TEXTRANSFORM_MASK 0xf + +struct ps_compile_args { + struct color_fixup_desc color_fixup[MAX_FRAGMENT_SAMPLERS]; + enum vertexprocessing_mode vp_mode; + enum fogmode fog; + WORD tex_transform; /* ps 1.0-1.3, 4 textures */ + /* Texture types(2D, Cube, 3D) in ps 1.x */ + WORD srgb_correction; + WORD np2_fixup; + /* Bitmap for NP2 texcoord fixups (16 samplers max currently). + D3D9 has a limit of 16 samplers and the fixup is superfluous + in D3D10 (unconditional NP2 support mandatory). */ + WORD shadow; /* MAX_FRAGMENT_SAMPLERS, 16 */ +}; + +enum fog_src_type { + VS_FOG_Z = 0, + VS_FOG_COORD = 1 +}; + +struct vs_compile_args { + BYTE fog_src; + BYTE clip_enabled; + WORD swizzle_map; /* MAX_ATTRIBS, 16 */ +}; + +struct wined3d_context; +struct wined3d_state; + +struct wined3d_shader_backend_ops +{ + void (*shader_handle_instruction)(const struct wined3d_shader_instruction *); + void (*shader_select)(const struct wined3d_context *context, BOOL usePS, BOOL useVS); + void (*shader_select_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info, + enum tex_types tex_type, const SIZE *ds_mask_size); + void (*shader_deselect_depth_blt)(void *shader_priv, const struct wined3d_gl_info *gl_info); + void (*shader_update_float_vertex_constants)(struct wined3d_device *device, UINT start, UINT count); + void (*shader_update_float_pixel_constants)(struct wined3d_device *device, UINT start, UINT count); + void (*shader_load_constants)(const struct wined3d_context *context, char usePS, char useVS); + void (*shader_load_np2fixup_constants)(void *shader_priv, const struct wined3d_gl_info *gl_info, + const struct wined3d_state *state); + void (*shader_destroy)(struct wined3d_shader *shader); + HRESULT (*shader_alloc_private)(struct wined3d_device *device); + void (*shader_free_private)(struct wined3d_device *device); + BOOL (*shader_dirtifyable_constants)(void); + void (*shader_get_caps)(const struct wined3d_gl_info *gl_info, struct shader_caps *caps); + BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup); +}; + +extern const struct wined3d_shader_backend_ops glsl_shader_backend DECLSPEC_HIDDEN; +extern const struct wined3d_shader_backend_ops arb_program_shader_backend DECLSPEC_HIDDEN; +extern const struct wined3d_shader_backend_ops none_shader_backend DECLSPEC_HIDDEN; + +/* X11 locking */ + +extern void (CDECL *wine_tsx11_lock_ptr)(void) DECLSPEC_HIDDEN; +extern void (CDECL *wine_tsx11_unlock_ptr)(void) DECLSPEC_HIDDEN; + +/* As GLX relies on X, this is needed */ +extern int num_lock DECLSPEC_HIDDEN; + +#if 0 +#define ENTER_GL() ++num_lock; if (num_lock > 1) FIXME("Recursive use of GL lock to: %d\n", num_lock); wine_tsx11_lock_ptr() +#define LEAVE_GL() if (num_lock != 1) FIXME("Recursive use of GL lock: %d\n", num_lock); --num_lock; wine_tsx11_unlock_ptr() +#else +#define ENTER_GL() wine_tsx11_lock_ptr() +#define LEAVE_GL() wine_tsx11_unlock_ptr() +#endif + +/***************************************************************************** + * Defines + */ + +/* GL related defines */ +/* ------------------ */ +#define GL_EXTCALL(f) (gl_info->f) + +#define D3DCOLOR_B_R(dw) (((dw) >> 16) & 0xFF) +#define D3DCOLOR_B_G(dw) (((dw) >> 8) & 0xFF) +#define D3DCOLOR_B_B(dw) (((dw) >> 0) & 0xFF) +#define D3DCOLOR_B_A(dw) (((dw) >> 24) & 0xFF) + +#define D3DCOLOR_R(dw) (((float) (((dw) >> 16) & 0xFF)) / 255.0f) +#define D3DCOLOR_G(dw) (((float) (((dw) >> 8) & 0xFF)) / 255.0f) +#define D3DCOLOR_B(dw) (((float) (((dw) >> 0) & 0xFF)) / 255.0f) +#define D3DCOLOR_A(dw) (((float) (((dw) >> 24) & 0xFF)) / 255.0f) + +#define D3DCOLORTOGLFLOAT4(dw, vec) do { \ + (vec)[0] = D3DCOLOR_R(dw); \ + (vec)[1] = D3DCOLOR_G(dw); \ + (vec)[2] = D3DCOLOR_B(dw); \ + (vec)[3] = D3DCOLOR_A(dw); \ +} while(0) + +#define HIGHEST_TRANSFORMSTATE WINED3DTS_WORLDMATRIX(255) /* Highest value in WINED3DTRANSFORMSTATETYPE */ + +/* Checking of API calls */ +/* --------------------- */ +#ifndef WINE_NO_DEBUG_MSGS +#define checkGLcall(A) \ +do { \ + GLint err; \ + if(!__WINE_IS_DEBUG_ON(_FIXME, __wine_dbch___default)) break; \ + err = glGetError(); \ + if (err == GL_NO_ERROR) { \ + TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \ + \ + } else do { \ + ERR(">>>>>>>>>>>>>>>>> %s (%#x) from %s @ %s / %d\n", \ + debug_glerror(err), err, A, __FILE__, __LINE__); \ + err = glGetError(); \ + } while (err != GL_NO_ERROR); \ +} while(0) +#else +#define checkGLcall(A) do {} while(0) +#endif + +/* Trace routines / diagnostics */ +/* ---------------------------- */ + +/* Dump out a matrix and copy it */ +#define conv_mat(mat,gl_mat) \ +do { \ + TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \ + TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \ + TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \ + TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \ + memcpy(gl_mat, (mat), 16 * sizeof(float)); \ +} while (0) + +/* Trace vector and strided data information */ +#define TRACE_STRIDED(si, name) do { if (si->use_map & (1 << name)) \ + TRACE( #name "=(data:%p, stride:%d, format:%#x, vbo %d, stream %u)\n", \ + si->elements[name].data, si->elements[name].stride, si->elements[name].format->id, \ + si->elements[name].buffer_object, si->elements[name].stream_idx); } while(0) + +/* Global variables */ +extern const float identity[16] DECLSPEC_HIDDEN; + +enum wined3d_ffp_idx +{ + WINED3D_FFP_POSITION = 0, + WINED3D_FFP_BLENDWEIGHT = 1, + WINED3D_FFP_BLENDINDICES = 2, + WINED3D_FFP_NORMAL = 3, + WINED3D_FFP_PSIZE = 4, + WINED3D_FFP_DIFFUSE = 5, + WINED3D_FFP_SPECULAR = 6, + WINED3D_FFP_TEXCOORD0 = 7, + WINED3D_FFP_TEXCOORD1 = 8, + WINED3D_FFP_TEXCOORD2 = 9, + WINED3D_FFP_TEXCOORD3 = 10, + WINED3D_FFP_TEXCOORD4 = 11, + WINED3D_FFP_TEXCOORD5 = 12, + WINED3D_FFP_TEXCOORD6 = 13, + WINED3D_FFP_TEXCOORD7 = 14, +}; + +enum wined3d_ffp_emit_idx +{ + WINED3D_FFP_EMIT_FLOAT1 = 0, + WINED3D_FFP_EMIT_FLOAT2 = 1, + WINED3D_FFP_EMIT_FLOAT3 = 2, + WINED3D_FFP_EMIT_FLOAT4 = 3, + WINED3D_FFP_EMIT_D3DCOLOR = 4, + WINED3D_FFP_EMIT_UBYTE4 = 5, + WINED3D_FFP_EMIT_SHORT2 = 6, + WINED3D_FFP_EMIT_SHORT4 = 7, + WINED3D_FFP_EMIT_UBYTE4N = 8, + WINED3D_FFP_EMIT_SHORT2N = 9, + WINED3D_FFP_EMIT_SHORT4N = 10, + WINED3D_FFP_EMIT_USHORT2N = 11, + WINED3D_FFP_EMIT_USHORT4N = 12, + WINED3D_FFP_EMIT_UDEC3 = 13, + WINED3D_FFP_EMIT_DEC3N = 14, + WINED3D_FFP_EMIT_FLOAT16_2 = 15, + WINED3D_FFP_EMIT_FLOAT16_4 = 16, + WINED3D_FFP_EMIT_COUNT = 17 +}; + +struct wined3d_stream_info_element +{ + const struct wined3d_format *format; + GLsizei stride; + const BYTE *data; + UINT stream_idx; + GLuint buffer_object; +}; + +struct wined3d_stream_info +{ + struct wined3d_stream_info_element elements[MAX_ATTRIBS]; + BOOL position_transformed; + WORD swizzle_map; /* MAX_ATTRIBS, 16 */ + WORD use_map; /* MAX_ATTRIBS, 16 */ +}; + +/***************************************************************************** + * Prototypes + */ + +/* Routine common to the draw primitive and draw indexed primitive routines */ +void drawPrimitive(struct wined3d_device *device, UINT index_count, + UINT start_idx, UINT idxBytes, const void *idxData) DECLSPEC_HIDDEN; +DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) DECLSPEC_HIDDEN; + +typedef void (WINE_GLAPI *glAttribFunc)(const void *data); +typedef void (WINE_GLAPI *glMultiTexCoordFunc)(GLenum unit, const void *data); +extern glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN; +extern glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN; +extern glAttribFunc specular_func_3ubv DECLSPEC_HIDDEN; +extern glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN; +extern glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN; +extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC_HIDDEN; + +#define eps 1e-8 + +#define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \ + (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1) + +/* Routines and structures related to state management */ + +#define STATE_RENDER(a) (a) +#define STATE_IS_RENDER(a) ((a) >= STATE_RENDER(1) && (a) <= STATE_RENDER(WINEHIGHEST_RENDER_STATE)) + +#define STATE_TEXTURESTAGE(stage, num) (STATE_RENDER(WINEHIGHEST_RENDER_STATE) + 1 + (stage) * (WINED3D_HIGHEST_TEXTURE_STATE + 1) + (num)) +#define STATE_IS_TEXTURESTAGE(a) ((a) >= STATE_TEXTURESTAGE(0, 1) && (a) <= STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE)) + +/* + 1 because samplers start with 0 */ +#define STATE_SAMPLER(num) (STATE_TEXTURESTAGE(MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE) + 1 + (num)) +#define STATE_IS_SAMPLER(num) ((num) >= STATE_SAMPLER(0) && (num) <= STATE_SAMPLER(MAX_COMBINED_SAMPLERS - 1)) + +#define STATE_PIXELSHADER (STATE_SAMPLER(MAX_COMBINED_SAMPLERS - 1) + 1) +#define STATE_IS_PIXELSHADER(a) ((a) == STATE_PIXELSHADER) + +#define STATE_TRANSFORM(a) (STATE_PIXELSHADER + (a)) +#define STATE_IS_TRANSFORM(a) ((a) >= STATE_TRANSFORM(1) && (a) <= STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255))) + +#define STATE_STREAMSRC (STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)) + 1) +#define STATE_IS_STREAMSRC(a) ((a) == STATE_STREAMSRC) +#define STATE_INDEXBUFFER (STATE_STREAMSRC + 1) +#define STATE_IS_INDEXBUFFER(a) ((a) == STATE_INDEXBUFFER) + +#define STATE_VDECL (STATE_INDEXBUFFER + 1) +#define STATE_IS_VDECL(a) ((a) == STATE_VDECL) + +#define STATE_VSHADER (STATE_VDECL + 1) +#define STATE_IS_VSHADER(a) ((a) == STATE_VSHADER) + +#define STATE_VIEWPORT (STATE_VSHADER + 1) +#define STATE_IS_VIEWPORT(a) ((a) == STATE_VIEWPORT) + +#define STATE_VERTEXSHADERCONSTANT (STATE_VIEWPORT + 1) +#define STATE_PIXELSHADERCONSTANT (STATE_VERTEXSHADERCONSTANT + 1) +#define STATE_IS_VERTEXSHADERCONSTANT(a) ((a) == STATE_VERTEXSHADERCONSTANT) +#define STATE_IS_PIXELSHADERCONSTANT(a) ((a) == STATE_PIXELSHADERCONSTANT) + +#define STATE_ACTIVELIGHT(a) (STATE_PIXELSHADERCONSTANT + (a) + 1) +#define STATE_IS_ACTIVELIGHT(a) ((a) >= STATE_ACTIVELIGHT(0) && (a) < STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS)) + +#define STATE_SCISSORRECT (STATE_ACTIVELIGHT(MAX_ACTIVE_LIGHTS - 1) + 1) +#define STATE_IS_SCISSORRECT(a) ((a) == STATE_SCISSORRECT) + +#define STATE_CLIPPLANE(a) (STATE_SCISSORRECT + 1 + (a)) +#define STATE_IS_CLIPPLANE(a) ((a) >= STATE_CLIPPLANE(0) && (a) <= STATE_CLIPPLANE(MAX_CLIPPLANES - 1)) + +#define STATE_MATERIAL (STATE_CLIPPLANE(MAX_CLIPPLANES)) +#define STATE_IS_MATERIAL(a) ((a) == STATE_MATERIAL) + +#define STATE_FRONTFACE (STATE_MATERIAL + 1) +#define STATE_IS_FRONTFACE(a) ((a) == STATE_FRONTFACE) + +#define STATE_POINTSPRITECOORDORIGIN (STATE_FRONTFACE + 1) +#define STATE_IS_POINTSPRITECOORDORIGIN(a) ((a) == STATE_POINTSPRITECOORDORIGIN) + +#define STATE_HIGHEST (STATE_POINTSPRITECOORDORIGIN) + +enum fogsource { + FOGSOURCE_FFP, + FOGSOURCE_VS, + FOGSOURCE_COORD, +}; + +#define WINED3D_MAX_FBO_ENTRIES 64 + +struct wined3d_occlusion_query +{ + struct list entry; + GLuint id; + struct wined3d_context *context; +}; + +union wined3d_gl_query_object +{ + GLuint id; + GLsync sync; +}; + +struct wined3d_event_query +{ + struct list entry; + union wined3d_gl_query_object object; + struct wined3d_context *context; +}; + +enum wined3d_event_query_result +{ + WINED3D_EVENT_QUERY_OK, + WINED3D_EVENT_QUERY_WAITING, + WINED3D_EVENT_QUERY_NOT_STARTED, + WINED3D_EVENT_QUERY_WRONG_THREAD, + WINED3D_EVENT_QUERY_ERROR +}; + +void wined3d_event_query_destroy(struct wined3d_event_query *query) DECLSPEC_HIDDEN; +enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, + struct wined3d_device *device) DECLSPEC_HIDDEN; +void wined3d_event_query_issue(struct wined3d_event_query *query, struct wined3d_device *device) DECLSPEC_HIDDEN; +BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; + +struct wined3d_context +{ + const struct wined3d_gl_info *gl_info; + /* State dirtification + * dirtyArray is an array that contains markers for dirty states. numDirtyEntries states are dirty, their numbers are in indices + * 0...numDirtyEntries - 1. isStateDirty is a redundant copy of the dirtyArray. Technically only one of them would be needed, + * but with the help of both it is easy to find out if a state is dirty(just check the array index), and for applying dirty states + * only numDirtyEntries array elements have to be checked, not STATE_HIGHEST states. + */ + DWORD dirtyArray[STATE_HIGHEST + 1]; /* Won't get bigger than that, a state is never marked dirty 2 times */ + DWORD numDirtyEntries; + DWORD isStateDirty[STATE_HIGHEST / (sizeof(DWORD) * CHAR_BIT) + 1]; /* Bitmap to find out quickly if a state is dirty */ + + struct wined3d_swapchain *swapchain; + struct wined3d_surface *current_rt; + DWORD tid; /* Thread ID which owns this context at the moment */ + + /* Stores some information about the context state for optimization */ + WORD render_offscreen : 1; + WORD draw_buffer_dirty : 1; + WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */ + WORD last_was_pshader : 1; + WORD last_was_vshader : 1; + WORD namedArraysLoaded : 1; + WORD numberedArraysLoaded : 1; + WORD last_was_blit : 1; + WORD last_was_ckey : 1; + WORD fog_coord : 1; + WORD fog_enabled : 1; + WORD num_untracked_materials : 2; /* Max value 2 */ + WORD current : 1; + WORD destroyed : 1; + WORD valid : 1; + BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */ + BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */ + DWORD numbered_array_mask; + GLenum tracking_parm; /* Which source is tracking current colour */ + GLenum untracked_materials[2]; + UINT blit_w, blit_h; + enum fogsource fog_source; + + char *vshader_const_dirty, *pshader_const_dirty; + + /* The actual opengl context */ + UINT level; + HGLRC restore_ctx; + HDC restore_dc; + HGLRC glCtx; + HWND win_handle; + HDC hdc; + int pixel_format; + GLint aux_buffers; + + /* FBOs */ + UINT fbo_entry_count; + struct list fbo_list; + struct list fbo_destroy_list; + struct fbo_entry *current_fbo; + GLuint dst_fbo; + GLuint fbo_read_binding; + GLuint fbo_draw_binding; + BOOL rebind_fbo; + struct wined3d_surface **blit_targets; + GLenum *draw_buffers; + + /* Queries */ + GLuint *free_occlusion_queries; + UINT free_occlusion_query_size; + UINT free_occlusion_query_count; + struct list occlusion_queries; + + union wined3d_gl_query_object *free_event_queries; + UINT free_event_query_size; + UINT free_event_query_count; + struct list event_queries; + + /* Extension emulation */ + GLint gl_fog_source; + GLfloat fog_coord_value; + GLfloat color[4], fogstart, fogend, fogcolor[4]; + GLuint dummy_arbfp_prog; +}; + +typedef void (*APPLYSTATEFUNC)(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *ctx); + +struct StateEntry +{ + DWORD representative; + APPLYSTATEFUNC apply; +}; + +struct StateEntryTemplate +{ + DWORD state; + struct StateEntry content; + GL_SupportedExt extension; +}; + +struct fragment_caps +{ + DWORD PrimitiveMiscCaps; + DWORD TextureOpCaps; + DWORD MaxTextureBlendStages; + DWORD MaxSimultaneousTextures; +}; + +struct fragment_pipeline +{ + void (*enable_extension)(BOOL enable); + void (*get_caps)(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps); + HRESULT (*alloc_private)(struct wined3d_device *device); + void (*free_private)(struct wined3d_device *device); + BOOL (*color_fixup_supported)(struct color_fixup_desc fixup); + const struct StateEntryTemplate *states; + BOOL ffp_proj_control; +}; + +extern const struct StateEntryTemplate misc_state_template[] DECLSPEC_HIDDEN; +extern const struct StateEntryTemplate ffp_vertexstate_template[] DECLSPEC_HIDDEN; +extern const struct fragment_pipeline ffp_fragment_pipeline DECLSPEC_HIDDEN; +extern const struct fragment_pipeline atifs_fragment_pipeline DECLSPEC_HIDDEN; +extern const struct fragment_pipeline arbfp_fragment_pipeline DECLSPEC_HIDDEN; +extern const struct fragment_pipeline nvts_fragment_pipeline DECLSPEC_HIDDEN; +extern const struct fragment_pipeline nvrc_fragment_pipeline DECLSPEC_HIDDEN; + +/* "Base" state table */ +HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs, + const struct wined3d_gl_info *gl_info, const struct StateEntryTemplate *vertex, + const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc) DECLSPEC_HIDDEN; + +enum wined3d_blit_op +{ + WINED3D_BLIT_OP_COLOR_BLIT, + WINED3D_BLIT_OP_COLOR_FILL, + WINED3D_BLIT_OP_DEPTH_FILL, + WINED3D_BLIT_OP_DEPTH_BLIT, +}; + +/* Shaders for color conversions in blits. Do not do blit operations while + * already under the GL lock. */ +struct blit_shader +{ + HRESULT (*alloc_private)(struct wined3d_device *device); + void (*free_private)(struct wined3d_device *device); + HRESULT (*set_shader)(void *blit_priv, const struct wined3d_gl_info *gl_info, struct wined3d_surface *surface); + void (*unset_shader)(const struct wined3d_gl_info *gl_info); + BOOL (*blit_supported)(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, const struct wined3d_format *src_format, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, const struct wined3d_format *dst_format); + HRESULT (*color_fill)(struct wined3d_device *device, struct wined3d_surface *dst_surface, + const RECT *dst_rect, const WINED3DCOLORVALUE *color); + HRESULT (*depth_fill)(struct wined3d_device *device, + struct wined3d_surface *surface, const RECT *rect, float depth); +}; + +extern const struct blit_shader ffp_blit DECLSPEC_HIDDEN; +extern const struct blit_shader arbfp_blit DECLSPEC_HIDDEN; +extern const struct blit_shader cpu_blit DECLSPEC_HIDDEN; + +const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op, + const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool, const struct wined3d_format *src_format, + const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool, const struct wined3d_format *dst_format) + DECLSPEC_HIDDEN; + +/* Temporary blit_shader helper functions */ +HRESULT arbfp_blit_surface(struct wined3d_device *device, struct wined3d_surface *src_surface, + const RECT *src_rect, struct wined3d_surface *dst_surface, const RECT *dst_rect_in, + enum wined3d_blit_op blit_op, DWORD Filter) DECLSPEC_HIDDEN; + +struct wined3d_context *context_acquire(struct wined3d_device *device, struct wined3d_surface *target) DECLSPEC_HIDDEN; +void context_alloc_event_query(struct wined3d_context *context, + struct wined3d_event_query *query) DECLSPEC_HIDDEN; +void context_alloc_occlusion_query(struct wined3d_context *context, + struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; +void context_apply_blit_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN; +BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_device *device, + UINT rt_count, struct wined3d_surface **rts, struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; +BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device) DECLSPEC_HIDDEN; +void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target, + struct wined3d_surface *render_target, struct wined3d_surface *depth_stencil, DWORD location) DECLSPEC_HIDDEN; +void context_attach_depth_stencil_fbo(struct wined3d_context *context, + GLenum fbo_target, struct wined3d_surface *depth_stencil, BOOL use_render_buffer) DECLSPEC_HIDDEN; +void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo) DECLSPEC_HIDDEN; +void context_check_fbo_status(struct wined3d_context *context, GLenum target) DECLSPEC_HIDDEN; +struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, struct wined3d_surface *target, + const struct wined3d_format *ds_format) DECLSPEC_HIDDEN; +void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN; +void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; +struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; +DWORD context_get_tls_idx(void) DECLSPEC_HIDDEN; +void context_release(struct wined3d_context *context) DECLSPEC_HIDDEN; +void context_resource_released(struct wined3d_device *device, + struct wined3d_resource *resource, WINED3DRESOURCETYPE type) DECLSPEC_HIDDEN; +void context_resource_unloaded(struct wined3d_device *device, + struct wined3d_resource *resource, WINED3DRESOURCETYPE type) DECLSPEC_HIDDEN; +BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN; +void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN; +void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN; +void context_surface_update(struct wined3d_context *context, struct wined3d_surface *surface) DECLSPEC_HIDDEN; + +/* Macros for doing basic GPU detection based on opengl capabilities */ +#define WINE_D3D6_CAPABLE(gl_info) (gl_info->supported[ARB_MULTITEXTURE]) +#define WINE_D3D7_CAPABLE(gl_info) (gl_info->supported[ARB_TEXTURE_COMPRESSION] && gl_info->supported[ARB_TEXTURE_CUBE_MAP] && gl_info->supported[ARB_TEXTURE_ENV_DOT3]) +#define WINE_D3D8_CAPABLE(gl_info) WINE_D3D7_CAPABLE(gl_info) && (gl_info->supported[ARB_MULTISAMPLE] && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP]) +#define WINE_D3D9_CAPABLE(gl_info) WINE_D3D8_CAPABLE(gl_info) && (gl_info->supported[ARB_FRAGMENT_PROGRAM] && gl_info->supported[ARB_VERTEX_SHADER]) +#define WINE_D3D10_CAPABLE(gl_info) WINE_D3D9_CAPABLE(gl_info) && (gl_info->supported[EXT_GPU_SHADER4]) + +/***************************************************************************** + * Internal representation of a light + */ +struct wined3d_light_info +{ + WINED3DLIGHT OriginalParms; /* Note D3D8LIGHT == D3D9LIGHT */ + DWORD OriginalIndex; + LONG glIndex; + BOOL enabled; + + /* Converted parms to speed up swapping lights */ + float lightPosn[4]; + float lightDirn[4]; + float exponent; + float cutoff; + + struct list entry; +}; + +/* The default light parameters */ +extern const WINED3DLIGHT WINED3D_default_light DECLSPEC_HIDDEN; + +struct wined3d_pixel_format +{ + int iPixelFormat; /* WGL pixel format */ + int iPixelType; /* WGL pixel type e.g. WGL_TYPE_RGBA_ARB, WGL_TYPE_RGBA_FLOAT_ARB or WGL_TYPE_COLORINDEX_ARB */ + int redSize, greenSize, blueSize, alphaSize, colorSize; + int depthSize, stencilSize; + BOOL windowDrawable; + BOOL doubleBuffer; + int auxBuffers; + int numSamples; +}; + +/* The driver names reflect the lowest GPU supported + * by a certain driver, so DRIVER_AMD_R300 supports + * R3xx, R4xx and R5xx GPUs. */ +enum wined3d_display_driver +{ + DRIVER_AMD_RAGE_128PRO, + DRIVER_AMD_R100, + DRIVER_AMD_R300, + DRIVER_AMD_R600, + DRIVER_INTEL_GMA800, + DRIVER_INTEL_GMA900, + DRIVER_INTEL_GMA950, + DRIVER_INTEL_GMA3000, + DRIVER_NVIDIA_TNT, + DRIVER_NVIDIA_GEFORCE2MX, + DRIVER_NVIDIA_GEFORCEFX, + DRIVER_NVIDIA_GEFORCE6, + DRIVER_UNKNOWN +}; + +enum wined3d_driver_model +{ + DRIVER_MODEL_WIN9X, + DRIVER_MODEL_NT40, + DRIVER_MODEL_NT5X, + DRIVER_MODEL_NT6X +}; + +enum wined3d_gl_vendor +{ + GL_VENDOR_UNKNOWN, + GL_VENDOR_APPLE, + GL_VENDOR_FGLRX, + GL_VENDOR_INTEL, + GL_VENDOR_MESA, + GL_VENDOR_NVIDIA, +}; + + +enum wined3d_pci_vendor +{ + HW_VENDOR_SOFTWARE = 0x0000, + HW_VENDOR_AMD = 0x1002, + HW_VENDOR_NVIDIA = 0x10de, + HW_VENDOR_INTEL = 0x8086, +}; + +enum wined3d_pci_device +{ + CARD_WINE = 0x0000, + + CARD_AMD_RAGE_128PRO = 0x5246, + CARD_AMD_RADEON_7200 = 0x5144, + CARD_AMD_RADEON_8500 = 0x514c, + CARD_AMD_RADEON_9500 = 0x4144, + CARD_AMD_RADEON_XPRESS_200M = 0x5955, + CARD_AMD_RADEON_X700 = 0x5e4c, + CARD_AMD_RADEON_X1600 = 0x71c2, + CARD_AMD_RADEON_HD2350 = 0x94c7, + CARD_AMD_RADEON_HD2600 = 0x9581, + CARD_AMD_RADEON_HD2900 = 0x9400, + CARD_AMD_RADEON_HD3200 = 0x9620, + CARD_AMD_RADEON_HD4350 = 0x954f, + CARD_AMD_RADEON_HD4550 = 0x9540, + CARD_AMD_RADEON_HD4600 = 0x9495, + CARD_AMD_RADEON_HD4650 = 0x9498, + CARD_AMD_RADEON_HD4670 = 0x9490, + CARD_AMD_RADEON_HD4700 = 0x944e, + CARD_AMD_RADEON_HD4770 = 0x94b3, + CARD_AMD_RADEON_HD4800 = 0x944c, /* Picked one value between 9440, 944c, 9442, 9460 */ + CARD_AMD_RADEON_HD4830 = 0x944c, + CARD_AMD_RADEON_HD4850 = 0x9442, + CARD_AMD_RADEON_HD4870 = 0x9440, + CARD_AMD_RADEON_HD4890 = 0x9460, + CARD_AMD_RADEON_HD5400 = 0x68f9, + CARD_AMD_RADEON_HD5600 = 0x68d8, + CARD_AMD_RADEON_HD5700 = 0x68BE, /* Picked HD5750 */ + CARD_AMD_RADEON_HD5750 = 0x68BE, + CARD_AMD_RADEON_HD5770 = 0x68B8, + CARD_AMD_RADEON_HD5800 = 0x6898, /* Picked HD5850 */ + CARD_AMD_RADEON_HD5850 = 0x6898, + CARD_AMD_RADEON_HD5870 = 0x6899, + CARD_AMD_RADEON_HD5900 = 0x689c, + CARD_AMD_RADEON_HD6310 = 0x9803, + CARD_AMD_RADEON_HD6800 = 0x6739, + CARD_AMD_RADEON_HD6900 = 0x6719, + + CARD_NVIDIA_RIVA_128 = 0x0018, + CARD_NVIDIA_RIVA_TNT = 0x0020, + CARD_NVIDIA_RIVA_TNT2 = 0x0028, + CARD_NVIDIA_GEFORCE = 0x0100, + CARD_NVIDIA_GEFORCE2_MX = 0x0110, + CARD_NVIDIA_GEFORCE2 = 0x0150, + CARD_NVIDIA_GEFORCE3 = 0x0200, + CARD_NVIDIA_GEFORCE4_MX = 0x0170, + CARD_NVIDIA_GEFORCE4_TI4200 = 0x0253, + CARD_NVIDIA_GEFORCEFX_5200 = 0x0320, + CARD_NVIDIA_GEFORCEFX_5600 = 0x0312, + CARD_NVIDIA_GEFORCEFX_5800 = 0x0302, + CARD_NVIDIA_GEFORCE_6200 = 0x014f, + CARD_NVIDIA_GEFORCE_6600GT = 0x0140, + CARD_NVIDIA_GEFORCE_6800 = 0x0041, + CARD_NVIDIA_GEFORCE_7400 = 0x01d8, + CARD_NVIDIA_GEFORCE_7300 = 0x01d7, /* GeForce Go 7300 */ + CARD_NVIDIA_GEFORCE_7600 = 0x0391, + CARD_NVIDIA_GEFORCE_7800GT = 0x0092, + CARD_NVIDIA_GEFORCE_8100 = 0x084F, + CARD_NVIDIA_GEFORCE_8200 = 0x0849, /* Other PCI ID 0x084B */ + CARD_NVIDIA_GEFORCE_8300GS = 0x0423, + CARD_NVIDIA_GEFORCE_8400GS = 0x0404, + CARD_NVIDIA_GEFORCE_8500GT = 0x0421, + CARD_NVIDIA_GEFORCE_8600GT = 0x0402, + CARD_NVIDIA_GEFORCE_8600MGT = 0x0407, + CARD_NVIDIA_GEFORCE_8800GTS = 0x0193, + CARD_NVIDIA_GEFORCE_8800GTX = 0x0191, + CARD_NVIDIA_GEFORCE_9200 = 0x086d, + CARD_NVIDIA_GEFORCE_9400GT = 0x042c, + CARD_NVIDIA_GEFORCE_9500GT = 0x0640, + CARD_NVIDIA_GEFORCE_9600GT = 0x0622, + CARD_NVIDIA_GEFORCE_9800GT = 0x0614, + CARD_NVIDIA_GEFORCE_210 = 0x0a23, + CARD_NVIDIA_GEFORCE_GT220 = 0x0a20, + CARD_NVIDIA_GEFORCE_GT240 = 0x0ca3, + CARD_NVIDIA_GEFORCE_GTX260 = 0x05e2, + CARD_NVIDIA_GEFORCE_GTX275 = 0x05e6, + CARD_NVIDIA_GEFORCE_GTX280 = 0x05e1, + CARD_NVIDIA_GEFORCE_GT320M = 0x0a2d, + CARD_NVIDIA_GEFORCE_GT325M = 0x0a35, + CARD_NVIDIA_GEFORCE_GT330 = 0x0ca0, + CARD_NVIDIA_GEFORCE_GTS350M = 0x0cb0, + CARD_NVIDIA_GEFORCE_GT420 = 0x0de2, + CARD_NVIDIA_GEFORCE_GT430 = 0x0de1, + CARD_NVIDIA_GEFORCE_GT440 = 0x0de0, + CARD_NVIDIA_GEFORCE_GTS450 = 0x0dc4, + CARD_NVIDIA_GEFORCE_GTX460 = 0x0e22, + CARD_NVIDIA_GEFORCE_GTX465 = 0x06c4, + CARD_NVIDIA_GEFORCE_GTX470 = 0x06cd, + CARD_NVIDIA_GEFORCE_GTX480 = 0x06c0, + CARD_NVIDIA_GEFORCE_GTX560 = 0x1200, + CARD_NVIDIA_GEFORCE_GTX570 = 0x1081, + CARD_NVIDIA_GEFORCE_GTX580 = 0x1080, + + CARD_INTEL_845G = 0x2562, + CARD_INTEL_I830G = 0x3577, + CARD_INTEL_I855G = 0x3582, + CARD_INTEL_I865G = 0x2572, + CARD_INTEL_I915G = 0x2582, + CARD_INTEL_I915GM = 0x2592, + CARD_INTEL_I945GM = 0x27a2, /* Same as GMA 950? */ + CARD_INTEL_X3100 = 0x2a02, /* Found in Macs. Same as GM965/GL960 */ + CARD_INTEL_GM45 = 0x2a42, +}; + +struct wined3d_fbo_ops +{ + PGLFNGLISRENDERBUFFERPROC glIsRenderbuffer; + PGLFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; + PGLFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; + PGLFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; + PGLFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; + PGLFNRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; + PGLFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; + PGLFNGLISFRAMEBUFFERPROC glIsFramebuffer; + PGLFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; + PGLFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; + PGLFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; + PGLFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; + PGLFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; + PGLFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; + PGLFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; + PGLFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; + PGLFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; + PGLFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; + PGLFNGLGENERATEMIPMAPPROC glGenerateMipmap; +}; + +struct wined3d_gl_limits +{ + UINT buffers; + UINT lights; + UINT textures; + UINT texture_stages; + UINT fragment_samplers; + UINT vertex_samplers; + UINT combined_samplers; + UINT general_combiners; + UINT sampler_stages; + UINT clipplanes; + UINT texture_size; + UINT texture3d_size; + float pointsize_max; + float pointsize_min; + UINT point_sprite_units; + UINT blends; + UINT anisotropy; + float shininess; + + UINT glsl_varyings; + UINT glsl_vs_float_constants; + UINT glsl_ps_float_constants; + + UINT arb_vs_float_constants; + UINT arb_vs_native_constants; + UINT arb_vs_instructions; + UINT arb_vs_temps; + UINT arb_ps_float_constants; + UINT arb_ps_local_constants; + UINT arb_ps_native_constants; + UINT arb_ps_instructions; + UINT arb_ps_temps; +}; + +struct wined3d_gl_info +{ + DWORD glsl_version; + struct wined3d_gl_limits limits; + DWORD reserved_glsl_constants; + DWORD quirks; + BOOL supported[WINED3D_GL_EXT_COUNT]; + GLint wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP + 1]; + + struct wined3d_fbo_ops fbo_ops; +#define USE_GL_FUNC(type, pfn, ext, replace) type pfn; + /* GL function pointers */ + GL_EXT_FUNCS_GEN + /* WGL function pointers */ + WGL_EXT_FUNCS_GEN +#undef USE_GL_FUNC + + struct wined3d_format *formats; +}; + +struct wined3d_driver_info +{ + enum wined3d_pci_vendor vendor; + enum wined3d_pci_device device; + const char *name; + const char *description; + unsigned int vidmem; + DWORD version_high; + DWORD version_low; +}; + +/* The adapter structure */ +struct wined3d_adapter +{ + UINT ordinal; + BOOL opengl; + POINT monitorPoint; + struct wined3d_gl_info gl_info; + struct wined3d_driver_info driver_info; + WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ + int nCfgs; + struct wined3d_pixel_format *cfgs; + BOOL brokenStencil; /* Set on cards which only offer mixed depth+stencil */ + unsigned int TextureRam; /* Amount of texture memory both video ram + AGP/TurboCache/HyperMemory/.. */ + unsigned int UsedTextureRam; + LUID luid; + + const struct fragment_pipeline *fragment_pipe; + const struct wined3d_shader_backend_ops *shader_backend; + const struct blit_shader *blitter; +}; + +BOOL initPixelFormats(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor) DECLSPEC_HIDDEN; +BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; +extern unsigned int WineD3DAdapterChangeGLRam(struct wined3d_device *device, int glram) DECLSPEC_HIDDEN; +extern void add_gl_compat_wrappers(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; + +/***************************************************************************** + * High order patch management + */ +struct WineD3DRectPatch +{ + UINT Handle; + float *mem; + WineDirect3DVertexStridedData strided; + WINED3DRECTPATCH_INFO RectPatchInfo; + float numSegs[4]; + char has_normals, has_texcoords; + struct list entry; +}; + +HRESULT tesselate_rectpatch(struct wined3d_device *device, struct WineD3DRectPatch *patch) DECLSPEC_HIDDEN; + +enum projection_types +{ + proj_none = 0, + proj_count3 = 1, + proj_count4 = 2 +}; + +enum dst_arg +{ + resultreg = 0, + tempreg = 1 +}; + +/***************************************************************************** + * Fixed function pipeline replacements + */ +#define ARG_UNUSED 0xff +struct texture_stage_op +{ + unsigned cop : 8; + unsigned carg1 : 8; + unsigned carg2 : 8; + unsigned carg0 : 8; + + unsigned aop : 8; + unsigned aarg1 : 8; + unsigned aarg2 : 8; + unsigned aarg0 : 8; + + struct color_fixup_desc color_fixup; + unsigned tex_type : 3; + unsigned dst : 1; + unsigned projected : 2; + unsigned padding : 10; +}; + +struct ffp_frag_settings { + struct texture_stage_op op[MAX_TEXTURES]; + enum fogmode fog; + /* Use shorts instead of chars to get dword alignment */ + unsigned short sRGB_write; + unsigned short emul_clipplanes; +}; + +struct ffp_frag_desc +{ + struct wine_rb_entry entry; + struct ffp_frag_settings settings; +}; + +extern const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions DECLSPEC_HIDDEN; +extern const struct wined3d_parent_ops wined3d_null_parent_ops DECLSPEC_HIDDEN; + +void gen_ffp_frag_op(struct wined3d_stateblock *stateblock, struct ffp_frag_settings *settings, + BOOL ignore_textype) DECLSPEC_HIDDEN; +const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders, + const struct ffp_frag_settings *settings) DECLSPEC_HIDDEN; +void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc) DECLSPEC_HIDDEN; + +struct wined3d +{ + LONG ref; + void *parent; + UINT dxVersion; + UINT adapter_count; + struct wined3d_adapter adapters[1]; +}; + +HRESULT wined3d_init(struct wined3d *wined3d, UINT version, void *parent) DECLSPEC_HIDDEN; +BOOL wined3d_register_window(HWND window, struct wined3d_device *device) DECLSPEC_HIDDEN; +void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN; + +/***************************************************************************** + * IWineD3DDevice implementation structure + */ +#define WINED3D_UNMAPPED_STAGE ~0U + +/* Multithreaded flag. Removed from the public header to signal that IWineD3D::CreateDevice ignores it */ +#define WINED3DCREATE_MULTITHREADED 0x00000004 + +struct wined3d_fb_state +{ + struct wined3d_surface **render_targets; + struct wined3d_surface *depth_stencil; +}; + +struct wined3d_device +{ + LONG ref; + + /* WineD3D Information */ + struct wined3d_device_parent *device_parent; + struct wined3d *wined3d; + struct wined3d_adapter *adapter; + + /* Window styles to restore when switching fullscreen mode */ + LONG style; + LONG exStyle; + + /* X and GL Information */ + GLenum offscreenBuffer; + + /* Selected capabilities */ + int vs_selected_mode; + int ps_selected_mode; + const struct wined3d_shader_backend_ops *shader_backend; + void *shader_priv; + void *fragment_priv; + void *blit_priv; + struct StateEntry StateTable[STATE_HIGHEST + 1]; + /* Array of functions for states which are handled by more than one pipeline part */ + APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1]; + const struct fragment_pipeline *frag_pipe; + const struct blit_shader *blitter; + + unsigned int max_ffp_textures; + DWORD d3d_vshader_constantF, d3d_pshader_constantF; /* Advertised d3d caps, not GL ones */ + DWORD vs_clipping; + + WORD view_ident : 1; /* true iff view matrix is identity */ + WORD untransformed : 1; + WORD vertexBlendUsed : 1; /* To avoid needless setting of the blend matrices */ + WORD isRecordingState : 1; + WORD isInDraw : 1; + WORD bCursorVisible : 1; + WORD d3d_initialized : 1; + WORD inScene : 1; /* A flag to check for proper BeginScene / EndScene call pairs */ + WORD softwareVertexProcessing : 1; /* process vertex shaders using software or hardware */ + WORD useDrawStridedSlow : 1; + WORD instancedDraw : 1; + WORD filter_messages : 1; + WORD padding : 4; + + BYTE fixed_function_usage_map; /* MAX_TEXTURES, 8 */ + +#define DDRAW_PITCH_ALIGNMENT 8 +#define D3D8_PITCH_ALIGNMENT 4 + unsigned char surface_alignment; /* Line Alignment of surfaces */ + + /* State block related */ + struct wined3d_stateblock *stateBlock; + struct wined3d_stateblock *updateStateBlock; + + /* Internal use fields */ + WINED3DDEVICE_CREATION_PARAMETERS createParms; + WINED3DDEVTYPE devType; + HWND focus_window; + + struct wined3d_swapchain **swapchains; + UINT swapchain_count; + + struct list resources; /* a linked list to track resources created by the device */ + struct list shaders; /* a linked list to track shaders (pixel and vertex) */ + unsigned int highest_dirty_ps_const, highest_dirty_vs_const; + + /* Render Target Support */ + DWORD valid_rt_mask; + struct wined3d_fb_state fb; + struct wined3d_surface *onscreen_depth_stencil; + struct wined3d_surface *auto_depth_stencil; + + /* palettes texture management */ + PALETTEENTRY **palettes; + UINT palette_count; + UINT currentPalette; + + /* For rendering to a texture using glCopyTexImage */ + GLuint depth_blt_texture; + GLuint depth_blt_rb; + UINT depth_blt_rb_w; + UINT depth_blt_rb_h; + + /* Cursor management */ + UINT xHotSpot; + UINT yHotSpot; + UINT xScreenSpace; + UINT yScreenSpace; + UINT cursorWidth, cursorHeight; + GLuint cursorTexture; + HCURSOR hardwareCursor; + + /* The Wine logo surface */ + struct wined3d_surface *logo_surface; + + /* Textures for when no other textures are mapped */ + UINT dummyTextureName[MAX_TEXTURES]; + + /* DirectDraw stuff */ + DWORD ddraw_width, ddraw_height; + enum wined3d_format_id ddraw_format; + + /* With register combiners we can skip junk texture stages */ + DWORD texUnitMap[MAX_COMBINED_SAMPLERS]; + DWORD rev_tex_unit_map[MAX_COMBINED_SAMPLERS]; + + /* Stream source management */ + struct wined3d_stream_info strided_streams; + const WineDirect3DVertexStridedData *up_strided; + struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; + unsigned int num_buffer_queries; + + /* Context management */ + struct wined3d_context **contexts; + UINT context_count; + + /* High level patch management */ +#define PATCHMAP_SIZE 43 +#define PATCHMAP_HASHFUNC(x) ((x) % PATCHMAP_SIZE) /* Primitive and simple function */ + struct list patches[PATCHMAP_SIZE]; + struct WineD3DRectPatch *currentPatch; +}; + +HRESULT device_clear_render_targets(struct wined3d_device *device, UINT rt_count, struct wined3d_surface **rts, + struct wined3d_surface *depth_stencil, UINT rect_count, const RECT *rects, const RECT *draw_rect, + DWORD flags, const WINED3DCOLORVALUE *color, float depth, DWORD stencil) DECLSPEC_HIDDEN; +BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void device_get_draw_rect(struct wined3d_device *device, RECT *rect) DECLSPEC_HIDDEN; +HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d, + UINT adapter_idx, WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, + struct wined3d_device_parent *device_parent) DECLSPEC_HIDDEN; +void device_preload_textures(struct wined3d_device *device) DECLSPEC_HIDDEN; +LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL unicode, + UINT message, WPARAM wparam, LPARAM lparam, WNDPROC proc) DECLSPEC_HIDDEN; +void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; +void device_stream_info_from_declaration(struct wined3d_device *device, + BOOL use_vshader, struct wined3d_stream_info *stream_info, BOOL *fixup) DECLSPEC_HIDDEN; +void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context, + struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN; +void device_update_stream_info(struct wined3d_device *device, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; +void device_update_tex_unit_map(struct wined3d_device *device) DECLSPEC_HIDDEN; +void IWineD3DDeviceImpl_MarkStateDirty(struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; + +static inline BOOL isStateDirty(struct wined3d_context *context, DWORD state) +{ + DWORD idx = state / (sizeof(*context->isStateDirty) * CHAR_BIT); + BYTE shift = state & ((sizeof(*context->isStateDirty) * CHAR_BIT) - 1); + return context->isStateDirty[idx] & (1 << shift); +} + +#define WINED3D_RESOURCE_ACCESS_GPU 0x1 +#define WINED3D_RESOURCE_ACCESS_CPU 0x2 +/* SCRATCH is mostly the same as CPU, but can't be used by the GPU at all, + * not even for resource uploads. */ +#define WINED3D_RESOURCE_ACCESS_SCRATCH 0x4 + +struct wined3d_resource_ops +{ + void (*resource_unload)(struct wined3d_resource *resource); +}; + +struct wined3d_resource +{ + LONG ref; + struct wined3d_device *device; + WINED3DRESOURCETYPE resourceType; + const struct wined3d_format *format; + WINED3DMULTISAMPLE_TYPE multisample_type; + UINT multisample_quality; + DWORD usage; + WINED3DPOOL pool; + DWORD access_flags; + UINT width; + UINT height; + UINT depth; + UINT size; + DWORD priority; + BYTE *allocatedMemory; /* Pointer to the real data location */ + BYTE *heapMemory; /* Pointer to the HeapAlloced block of memory */ + struct list privateData; + struct list resource_list_entry; + + void *parent; + const struct wined3d_parent_ops *parent_ops; + const struct wined3d_resource_ops *resource_ops; +}; + +void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; +HRESULT resource_free_private_data(struct wined3d_resource *resource, REFGUID guid) DECLSPEC_HIDDEN; +DWORD resource_get_priority(const struct wined3d_resource *resource) DECLSPEC_HIDDEN; +HRESULT resource_get_private_data(const struct wined3d_resource *resource, REFGUID guid, + void *data, DWORD *data_size) DECLSPEC_HIDDEN; +HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device, + WINED3DRESOURCETYPE resource_type, const struct wined3d_format *format, + WINED3DMULTISAMPLE_TYPE multisample_type, UINT multisample_quality, + DWORD usage, WINED3DPOOL pool, UINT width, UINT height, UINT depth, UINT size, + void *parent, const struct wined3d_parent_ops *parent_ops, + const struct wined3d_resource_ops *resource_ops) DECLSPEC_HIDDEN; +DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority) DECLSPEC_HIDDEN; +HRESULT resource_set_private_data(struct wined3d_resource *resource, REFGUID guid, + const void *data, DWORD data_size, DWORD flags) DECLSPEC_HIDDEN; +void resource_unload(struct wined3d_resource *resource) DECLSPEC_HIDDEN; + +/* Tests show that the start address of resources is 32 byte aligned */ +#define RESOURCE_ALIGNMENT 16 + +typedef enum winetexturestates { + WINED3DTEXSTA_ADDRESSU = 0, + WINED3DTEXSTA_ADDRESSV = 1, + WINED3DTEXSTA_ADDRESSW = 2, + WINED3DTEXSTA_BORDERCOLOR = 3, + WINED3DTEXSTA_MAGFILTER = 4, + WINED3DTEXSTA_MINFILTER = 5, + WINED3DTEXSTA_MIPFILTER = 6, + WINED3DTEXSTA_MAXMIPLEVEL = 7, + WINED3DTEXSTA_MAXANISOTROPY = 8, + WINED3DTEXSTA_SRGBTEXTURE = 9, + WINED3DTEXSTA_SHADOW = 10, + MAX_WINETEXTURESTATES = 11, +} winetexturestates; + +enum WINED3DSRGB +{ + SRGB_ANY = 0, /* Uses the cached value(e.g. external calls) */ + SRGB_RGB = 1, /* Loads the rgb texture */ + SRGB_SRGB = 2, /* Loads the srgb texture */ +}; + +struct gl_texture +{ + DWORD states[MAX_WINETEXTURESTATES]; + BOOL dirty; + GLuint name; +}; + +struct wined3d_texture_ops +{ + HRESULT (*texture_bind)(struct wined3d_texture *texture, + const struct wined3d_gl_info *gl_info, BOOL srgb); + void (*texture_preload)(struct wined3d_texture *texture, enum WINED3DSRGB srgb); + void (*texture_sub_resource_add_dirty_region)(struct wined3d_resource *sub_resource, + const WINED3DBOX *dirty_region); + void (*texture_sub_resource_cleanup)(struct wined3d_resource *sub_resource); +}; + +#define WINED3D_TEXTURE_COND_NP2 0x1 +#define WINED3D_TEXTURE_POW2_MAT_IDENT 0x2 +#define WINED3D_TEXTURE_IS_SRGB 0x4 + +struct wined3d_texture +{ + struct wined3d_resource resource; + const struct wined3d_texture_ops *texture_ops; + struct gl_texture texture_rgb, texture_srgb; + struct wined3d_resource **sub_resources; + UINT layer_count; + UINT level_count; + float pow2_matrix[16]; + UINT lod; + WINED3DTEXTUREFILTERTYPE filter_type; + LONG bind_count; + DWORD sampler; + DWORD flags; + const struct min_lookup *min_mip_lookup; + const GLenum *mag_lookup; + GLenum target; +}; + +static inline struct wined3d_texture *wined3d_texture_from_resource(struct wined3d_resource *resource) +{ + return CONTAINING_RECORD(resource, struct wined3d_texture, resource); +} + +static inline struct gl_texture *wined3d_texture_get_gl_texture(struct wined3d_texture *texture, + const struct wined3d_gl_info *gl_info, BOOL srgb) +{ + return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + ? &texture->texture_srgb : &texture->texture_rgb; +} + +void wined3d_texture_apply_state_changes(struct wined3d_texture *texture, + const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1], + const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; +void wined3d_texture_set_dirty(struct wined3d_texture *texture, BOOL dirty) DECLSPEC_HIDDEN; + +struct wined3d_volume +{ + struct wined3d_resource resource; + struct wined3d_texture *container; + BOOL lockable; + BOOL locked; + WINED3DBOX lockedBox; + WINED3DBOX dirtyBox; + BOOL dirty; +}; + +static inline struct wined3d_volume *volume_from_resource(struct wined3d_resource *resource) +{ + return CONTAINING_RECORD(resource, struct wined3d_volume, resource); +} + +void volume_add_dirty_box(struct wined3d_volume *volume, const WINED3DBOX *dirty_box) DECLSPEC_HIDDEN; +void volume_load(struct wined3d_volume *volume, UINT level, BOOL srgb_mode) DECLSPEC_HIDDEN; +void volume_set_container(struct wined3d_volume *volume, struct wined3d_texture *container) DECLSPEC_HIDDEN; + +/***************************************************************************** + * Structure for DIB Surfaces (GetDC and GDI surfaces) + */ +typedef struct wineD3DSurface_DIB { + HBITMAP DIBsection; + void* bitmap_data; + UINT bitmap_size; + HGDIOBJ holdbitmap; + BOOL client_memory; +} wineD3DSurface_DIB; + +struct wined3d_renderbuffer_entry +{ + struct list entry; + GLuint id; + UINT width; + UINT height; +}; + +struct fbo_entry +{ + struct list entry; + struct wined3d_surface **render_targets; + struct wined3d_surface *depth_stencil; + DWORD location; + BOOL attached; + GLuint id; +}; + +struct wined3d_clipper +{ + LONG ref; + + HWND hWnd; +}; + +enum wined3d_container_type +{ + WINED3D_CONTAINER_NONE = 0, + WINED3D_CONTAINER_SWAPCHAIN, + WINED3D_CONTAINER_TEXTURE, +}; + +struct wined3d_subresource_container +{ + enum wined3d_container_type type; + union + { + struct wined3d_swapchain *swapchain; + struct wined3d_texture *texture; + void *base; + } u; +}; + +struct wined3d_surface_ops +{ + HRESULT (*surface_private_setup)(struct wined3d_surface *surface); + void (*surface_cleanup)(struct wined3d_surface *surface); + void (*surface_realize_palette)(struct wined3d_surface *surface); + HRESULT (*surface_draw_overlay)(struct wined3d_surface *surface); + void (*surface_preload)(struct wined3d_surface *surface); + void (*surface_map)(struct wined3d_surface *surface, const RECT *rect, DWORD flags); + void (*surface_unmap)(struct wined3d_surface *surface); + HRESULT (*surface_getdc)(struct wined3d_surface *surface); + HRESULT (*surface_flip)(struct wined3d_surface *surface, struct wined3d_surface *override); + HRESULT (*surface_blt)(struct wined3d_surface *dst_surface, const RECT *dst_rect, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD flags, + const WINEDDBLTFX *fx, WINED3DTEXTUREFILTERTYPE filter); + HRESULT (*surface_bltfast)(struct wined3d_surface *dst_surface, DWORD dst_x, DWORD dst_y, + struct wined3d_surface *src_surface, const RECT *src_rect, DWORD trans); + HRESULT (*surface_set_mem)(struct wined3d_surface *surface, void *mem); +}; + +struct wined3d_surface +{ + struct wined3d_resource resource; + const struct wined3d_surface_ops *surface_ops; + struct wined3d_subresource_container container; + struct wined3d_palette *palette; /* D3D7 style palette handling */ + PALETTEENTRY *palette9; /* D3D8/9 style palette handling */ + + DWORD flags; + + WINED3DSURFTYPE surface_type; + UINT pow2Width; + UINT pow2Height; + + /* A method to retrieve the drawable size. Not in the Vtable to make it changeable */ + void (*get_drawable_size)(struct wined3d_context *context, UINT *width, UINT *height); + + /* PBO */ + GLuint pbo; + GLuint texture_name; + GLuint texture_name_srgb; + GLint texture_level; + GLenum texture_target; + + RECT lockedRect; + RECT dirtyRect; + int lockCount; +#define MAXLOCKCOUNT 50 /* After this amount of locks do not free the sysmem copy */ + + /* For GetDC */ + wineD3DSurface_DIB dib; + HDC hDC; + + /* Color keys for DDraw */ + WINEDDCOLORKEY DestBltCKey; + WINEDDCOLORKEY DestOverlayCKey; + WINEDDCOLORKEY SrcOverlayCKey; + WINEDDCOLORKEY SrcBltCKey; + DWORD CKeyFlags; + + WINEDDCOLORKEY glCKey; + + struct list renderbuffers; + struct wined3d_renderbuffer_entry *current_renderbuffer; + SIZE ds_current_size; + + /* DirectDraw clippers */ + struct wined3d_clipper *clipper; + + /* DirectDraw Overlay handling */ + RECT overlay_srcrect; + RECT overlay_destrect; + struct wined3d_surface *overlay_dest; + struct list overlays; + struct list overlay_entry; +}; + +static inline struct wined3d_surface *surface_from_resource(struct wined3d_resource *resource) +{ + return CONTAINING_RECORD(resource, struct wined3d_surface, resource); +} + +static inline GLuint surface_get_texture_name(struct wined3d_surface *surface, + const struct wined3d_gl_info *gl_info, BOOL srgb) +{ + return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + ? surface->texture_name_srgb : surface->texture_name; +} + +void surface_add_dirty_rect(struct wined3d_surface *surface, const WINED3DBOX *dirty_rect) DECLSPEC_HIDDEN; +void surface_bind(struct wined3d_surface *surface, const struct wined3d_gl_info *gl_info, BOOL srgb) DECLSPEC_HIDDEN; +HRESULT surface_color_fill(struct wined3d_surface *s, const RECT *rect, const WINED3DCOLORVALUE *color) DECLSPEC_HIDDEN; +GLenum surface_get_gl_buffer(struct wined3d_surface *surface) DECLSPEC_HIDDEN; +BOOL surface_init_sysmem(struct wined3d_surface *surface) DECLSPEC_HIDDEN; +void surface_internal_preload(struct wined3d_surface *surface, enum WINED3DSRGB srgb) DECLSPEC_HIDDEN; +BOOL surface_is_offscreen(struct wined3d_surface *surface) DECLSPEC_HIDDEN; +HRESULT surface_load(struct wined3d_surface *surface, BOOL srgb) DECLSPEC_HIDDEN; +void surface_load_ds_location(struct wined3d_surface *surface, + struct wined3d_context *context, DWORD location) DECLSPEC_HIDDEN; +HRESULT surface_load_location(struct wined3d_surface *surface, DWORD flag, const RECT *rect) DECLSPEC_HIDDEN; +void surface_modify_ds_location(struct wined3d_surface *surface, DWORD location, UINT w, UINT h) DECLSPEC_HIDDEN; +void surface_modify_location(struct wined3d_surface *surface, DWORD flag, BOOL persistent) DECLSPEC_HIDDEN; +void surface_prepare_texture(struct wined3d_surface *surface, + const struct wined3d_gl_info *gl_info, BOOL srgb) DECLSPEC_HIDDEN; +void surface_set_compatible_renderbuffer(struct wined3d_surface *surface, struct wined3d_surface *rt) DECLSPEC_HIDDEN; +void surface_set_container(struct wined3d_surface *surface, + enum wined3d_container_type type, void *container) DECLSPEC_HIDDEN; +void surface_set_texture_name(struct wined3d_surface *surface, GLuint name, BOOL srgb_name) DECLSPEC_HIDDEN; +void surface_set_texture_target(struct wined3d_surface *surface, GLenum target) DECLSPEC_HIDDEN; +void surface_translate_drawable_coords(struct wined3d_surface *surface, HWND window, RECT *rect) DECLSPEC_HIDDEN; + +void get_drawable_size_swapchain(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; +void get_drawable_size_backbuffer(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; +void get_drawable_size_fbo(struct wined3d_context *context, UINT *width, UINT *height) DECLSPEC_HIDDEN; + +void draw_textured_quad(struct wined3d_surface *src_surface, const RECT *src_rect, + const RECT *dst_rect, WINED3DTEXTUREFILTERTYPE Filter) DECLSPEC_HIDDEN; +void flip_surface(struct wined3d_surface *front, struct wined3d_surface *back) DECLSPEC_HIDDEN; + +/* Surface flags: */ +#define SFLAG_CONVERTED 0x00000002 /* Converted for color keying or Palettized */ +#define SFLAG_DIBSECTION 0x00000004 /* Has a DIB section attached for GetDC */ +#define SFLAG_LOCKABLE 0x00000008 /* Surface can be locked */ +#define SFLAG_DISCARD 0x00000010 /* ??? */ +#define SFLAG_LOCKED 0x00000020 /* Surface is locked atm */ +#define SFLAG_INTEXTURE 0x00000040 /* The GL texture contains the newest surface content */ +#define SFLAG_INSRGBTEX 0x00000080 /* The GL srgb texture contains the newest surface content */ +#define SFLAG_INDRAWABLE 0x00000100 /* The gl drawable contains the most up to date data */ +#define SFLAG_INSYSMEM 0x00000200 /* The system memory copy is most up to date */ +#define SFLAG_NONPOW2 0x00000400 /* Surface sizes are not a power of 2 */ +#define SFLAG_DYNLOCK 0x00000800 /* Surface is often locked by the app */ +#define SFLAG_DCINUSE 0x00001000 /* Set between GetDC and ReleaseDC calls */ +#define SFLAG_LOST 0x00002000 /* Surface lost flag for DDraw */ +#define SFLAG_USERPTR 0x00004000 /* The application allocated the memory for this surface */ +#define SFLAG_GLCKEY 0x00008000 /* The gl texture was created with a color key */ +#define SFLAG_CLIENT 0x00010000 /* GL_APPLE_client_storage is used on that texture */ +#define SFLAG_ALLOCATED 0x00020000 /* A gl texture is allocated for this surface */ +#define SFLAG_SRGBALLOCATED 0x00040000 /* A srgb gl texture is allocated for this surface */ +#define SFLAG_PBO 0x00080000 /* Has a PBO attached for speeding up data transfers for dynamically locked surfaces */ +#define SFLAG_NORMCOORD 0x00100000 /* Set if the GL texture coords are normalized(non-texture rectangle) */ +#define SFLAG_DS_ONSCREEN 0x00200000 /* Is a depth stencil, last modified onscreen */ +#define SFLAG_DS_OFFSCREEN 0x00400000 /* Is a depth stencil, last modified offscreen */ +#define SFLAG_INOVERLAYDRAW 0x00800000 /* Overlay drawing is in progress. Recursion prevention */ + +/* In some conditions the surface memory must not be freed: + * SFLAG_CONVERTED: Converting the data back would take too long + * SFLAG_DIBSECTION: The dib code manages the memory + * SFLAG_LOCKED: The app requires access to the surface data + * SFLAG_DYNLOCK: Avoid freeing the data for performance + * SFLAG_PBO: PBOs don't use 'normal' memory. It is either allocated by the driver or must be NULL. + * SFLAG_CLIENT: OpenGL uses our memory as backup + */ +#define SFLAG_DONOTFREE (SFLAG_CONVERTED | \ + SFLAG_DIBSECTION | \ + SFLAG_LOCKED | \ + SFLAG_DYNLOCK | \ + SFLAG_USERPTR | \ + SFLAG_PBO | \ + SFLAG_CLIENT) + +#define SFLAG_LOCATIONS (SFLAG_INSYSMEM | \ + SFLAG_INTEXTURE | \ + SFLAG_INDRAWABLE | \ + SFLAG_INSRGBTEX) + +#define SFLAG_DS_LOCATIONS (SFLAG_DS_ONSCREEN | \ + SFLAG_DS_OFFSCREEN) +#define SFLAG_DS_DISCARDED SFLAG_DS_LOCATIONS + +typedef enum { + NO_CONVERSION, + CONVERT_PALETTED, + CONVERT_PALETTED_CK, + CONVERT_CK_565, + CONVERT_CK_5551, + CONVERT_CK_RGB24, + CONVERT_RGB32_888 +} CONVERT_TYPES; + +HRESULT d3dfmt_get_conv(struct wined3d_surface *surface, BOOL need_alpha_ck, BOOL use_texturing, + struct wined3d_format *format, CONVERT_TYPES *convert) DECLSPEC_HIDDEN; +void d3dfmt_p8_init_palette(struct wined3d_surface *surface, BYTE table[256][4], BOOL colorkey) DECLSPEC_HIDDEN; + +BOOL palette9_changed(struct wined3d_surface *surface) DECLSPEC_HIDDEN; + +struct wined3d_vertex_declaration_element +{ + const struct wined3d_format *format; + BOOL ffp_valid; + WORD input_slot; + WORD offset; + UINT output_slot; + BYTE method; + BYTE usage; + BYTE usage_idx; +}; + +struct wined3d_vertex_declaration +{ + LONG ref; + void *parent; + const struct wined3d_parent_ops *parent_ops; + struct wined3d_device *device; + + struct wined3d_vertex_declaration_element *elements; + UINT element_count; + + DWORD streams[MAX_STREAMS]; + UINT num_streams; + BOOL position_transformed; + BOOL half_float_conv_needed; +}; + +/* Internal state Block for Begin/End/Capture/Create/Apply info */ +/* Note: Very long winded but gl Lists are not flexible enough */ +/* to resolve everything we need, so doing it manually for now */ +typedef struct SAVEDSTATES { + DWORD transform[(HIGHEST_TRANSFORMSTATE >> 5) + 1]; + WORD streamSource; /* MAX_STREAMS, 16 */ + WORD streamFreq; /* MAX_STREAMS, 16 */ + DWORD renderState[(WINEHIGHEST_RENDER_STATE >> 5) + 1]; + DWORD textureState[MAX_TEXTURES]; /* WINED3D_HIGHEST_TEXTURE_STATE + 1, 18 */ + WORD samplerState[MAX_COMBINED_SAMPLERS]; /* WINED3D_HIGHEST_SAMPLER_STATE + 1, 14 */ + DWORD clipplane; /* WINED3DMAXUSERCLIPPLANES, 32 */ + WORD pixelShaderConstantsB; /* MAX_CONST_B, 16 */ + WORD pixelShaderConstantsI; /* MAX_CONST_I, 16 */ + BOOL *pixelShaderConstantsF; + WORD vertexShaderConstantsB; /* MAX_CONST_B, 16 */ + WORD vertexShaderConstantsI; /* MAX_CONST_I, 16 */ + BOOL *vertexShaderConstantsF; + DWORD textures : 20; /* MAX_COMBINED_SAMPLERS, 20 */ + DWORD primitive_type : 1; + DWORD indices : 1; + DWORD material : 1; + DWORD viewport : 1; + DWORD vertexDecl : 1; + DWORD pixelShader : 1; + DWORD vertexShader : 1; + DWORD scissorRect : 1; + DWORD padding : 4; +} SAVEDSTATES; + +struct StageState { + DWORD stage; + DWORD state; +}; + +struct wined3d_stream_state +{ + struct wined3d_buffer *buffer; + UINT offset; + UINT stride; + UINT frequency; + UINT flags; +}; + +struct wined3d_state +{ + struct wined3d_vertex_declaration *vertex_declaration; + struct wined3d_stream_state streams[MAX_STREAMS + 1 /* tesselated pseudo-stream */]; + BOOL user_stream; + struct wined3d_buffer *index_buffer; + enum wined3d_format_id index_format; + INT base_vertex_index; + INT load_base_vertex_index; /* Non-indexed drawing needs 0 here, indexed needs base_vertex_index. */ + GLenum gl_primitive_type; + + struct wined3d_shader *vertex_shader; + BOOL vs_consts_b[MAX_CONST_B]; + INT vs_consts_i[MAX_CONST_I * 4]; + float *vs_consts_f; + + struct wined3d_shader *pixel_shader; + BOOL ps_consts_b[MAX_CONST_B]; + INT ps_consts_i[MAX_CONST_I * 4]; + float *ps_consts_f; + + struct wined3d_texture *textures[MAX_COMBINED_SAMPLERS]; + DWORD sampler_states[MAX_COMBINED_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1]; + DWORD texture_states[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1]; + DWORD lowest_disabled_stage; + + WINED3DMATRIX transforms[HIGHEST_TRANSFORMSTATE + 1]; + double clip_planes[MAX_CLIPPLANES][4]; + WINED3DCLIPSTATUS clip_status; + WINED3DMATERIAL material; + WINED3DVIEWPORT viewport; + RECT scissor_rect; + + /* Light hashmap . Collisions are handled using standard wine double linked lists */ +#define LIGHTMAP_SIZE 43 /* Use of a prime number recommended. Set to 1 for a linked list! */ +#define LIGHTMAP_HASHFUNC(x) ((x) % LIGHTMAP_SIZE) /* Primitive and simple function */ + struct list light_map[LIGHTMAP_SIZE]; /* Hash map containing the lights */ + const struct wined3d_light_info *lights[MAX_ACTIVE_LIGHTS]; /* Map of opengl lights to d3d lights */ + + DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; +}; + +struct wined3d_stateblock +{ + LONG ref; /* Note: Ref counting not required */ + struct wined3d_device *device; + WINED3DSTATEBLOCKTYPE blockType; + + /* Array indicating whether things have been set or changed */ + SAVEDSTATES changed; + struct wined3d_state state; + + /* Contained state management */ + DWORD contained_render_states[WINEHIGHEST_RENDER_STATE + 1]; + unsigned int num_contained_render_states; + DWORD contained_transform_states[HIGHEST_TRANSFORMSTATE + 1]; + unsigned int num_contained_transform_states; + DWORD contained_vs_consts_i[MAX_CONST_I]; + unsigned int num_contained_vs_consts_i; + DWORD contained_vs_consts_b[MAX_CONST_B]; + unsigned int num_contained_vs_consts_b; + DWORD *contained_vs_consts_f; + unsigned int num_contained_vs_consts_f; + DWORD contained_ps_consts_i[MAX_CONST_I]; + unsigned int num_contained_ps_consts_i; + DWORD contained_ps_consts_b[MAX_CONST_B]; + unsigned int num_contained_ps_consts_b; + DWORD *contained_ps_consts_f; + unsigned int num_contained_ps_consts_f; + struct StageState contained_tss_states[MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)]; + unsigned int num_contained_tss_states; + struct StageState contained_sampler_states[MAX_COMBINED_SAMPLERS * WINED3D_HIGHEST_SAMPLER_STATE]; + unsigned int num_contained_sampler_states; +}; + +void stateblock_init_contained_states(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN; +void stateblock_init_default_state(struct wined3d_stateblock *stateblock) DECLSPEC_HIDDEN; + +static inline void stateblock_apply_state(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) +{ + const struct StateEntry *statetable = stateblock->device->StateTable; + DWORD rep = statetable[state].representative; + statetable[rep].apply(rep, stateblock, context); +} + +/* Direct3D terminology with little modifications. We do not have an issued state + * because only the driver knows about it, but we have a created state because d3d + * allows GetData on a created issue, but opengl doesn't + */ +enum query_state { + QUERY_CREATED, + QUERY_SIGNALLED, + QUERY_BUILDING +}; + +struct wined3d_query_ops +{ + HRESULT (*query_get_data)(struct wined3d_query *query, void *data, DWORD data_size, DWORD flags); + HRESULT (*query_issue)(struct wined3d_query *query, DWORD flags); +}; + +struct wined3d_query +{ + LONG ref; + const struct wined3d_query_ops *query_ops; + struct wined3d_device *device; + enum query_state state; + WINED3DQUERYTYPE type; + DWORD data_size; + void *extendedData; +}; + +/* TODO: Add tests and support for FLOAT16_4 POSITIONT, D3DCOLOR position, other + * fixed function semantics as D3DCOLOR or FLOAT16 */ +enum wined3d_buffer_conversion_type +{ + CONV_NONE, + CONV_D3DCOLOR, + CONV_POSITIONT, +}; + +struct wined3d_map_range +{ + UINT offset; + UINT size; +}; + +#define WINED3D_BUFFER_OPTIMIZED 0x01 /* Optimize has been called for the buffer */ +#define WINED3D_BUFFER_HASDESC 0x02 /* A vertex description has been found */ +#define WINED3D_BUFFER_CREATEBO 0x04 /* Attempt to create a buffer object next PreLoad */ +#define WINED3D_BUFFER_DOUBLEBUFFER 0x08 /* Use a vbo and local allocated memory */ +#define WINED3D_BUFFER_FLUSH 0x10 /* Manual unmap flushing */ +#define WINED3D_BUFFER_DISCARD 0x20 /* A DISCARD lock has occurred since the last PreLoad */ +#define WINED3D_BUFFER_NOSYNC 0x40 /* All locks since the last PreLoad had NOOVERWRITE set */ +#define WINED3D_BUFFER_APPLESYNC 0x80 /* Using sync as in GL_APPLE_flush_buffer_range */ + +struct wined3d_buffer +{ + struct wined3d_resource resource; + + struct wined3d_buffer_desc desc; + + GLuint buffer_object; + GLenum buffer_object_usage; + GLenum buffer_type_hint; + UINT buffer_object_size; + LONG bind_count; + DWORD flags; + + LONG lock_count; + struct wined3d_map_range *maps; + ULONG maps_size, modified_areas; + struct wined3d_event_query *query; + + /* conversion stuff */ + UINT decl_change_count, full_conversion_count; + UINT draw_count; + UINT stride; /* 0 if no conversion */ + UINT conversion_stride; /* 0 if no shifted conversion */ + enum wined3d_buffer_conversion_type *conversion_map; /* NULL if no conversion */ +}; + +static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resource *resource) +{ + return CONTAINING_RECORD(resource, struct wined3d_buffer, resource); +} + +const BYTE *buffer_get_memory(struct wined3d_buffer *buffer, const struct wined3d_gl_info *gl_info, + GLuint *buffer_object) DECLSPEC_HIDDEN; +BYTE *buffer_get_sysmem(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; + +struct wined3d_rendertarget_view +{ + LONG refcount; + + struct wined3d_resource *resource; + void *parent; +}; + +struct wined3d_swapchain_ops +{ + HRESULT (*swapchain_present)(struct wined3d_swapchain *swapchain, const RECT *src_rect, + const RECT *dst_rect, const RGNDATA *dirty_region, DWORD flags); +}; + +struct wined3d_swapchain +{ + LONG ref; + void *parent; + const struct wined3d_parent_ops *parent_ops; + const struct wined3d_swapchain_ops *swapchain_ops; + struct wined3d_device *device; + + struct wined3d_surface **back_buffers; + struct wined3d_surface *front_buffer; + WINED3DPRESENT_PARAMETERS presentParms; + DWORD orig_width, orig_height; + enum wined3d_format_id orig_fmt; + WINED3DGAMMARAMP orig_gamma; + BOOL render_to_fbo; + const struct wined3d_format *ds_format; + + LONG prev_time, frames; /* Performance tracking */ + + struct wined3d_context **context; + unsigned int num_contexts; + + HWND win_handle; + HWND device_window; + + HDC backup_dc; + HWND backup_wnd; +}; + +void x11_copy_to_screen(struct wined3d_swapchain *swapchain, const RECT *rect) DECLSPEC_HIDDEN; + +struct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; + +#define DEFAULT_REFRESH_RATE 0 + +/***************************************************************************** + * Utility function prototypes + */ + +/* Trace routines */ +const char *debug_d3dformat(enum wined3d_format_id format_id) DECLSPEC_HIDDEN; +const char *debug_d3ddevicetype(WINED3DDEVTYPE devtype) DECLSPEC_HIDDEN; +const char *debug_d3dresourcetype(WINED3DRESOURCETYPE res) DECLSPEC_HIDDEN; +const char *debug_d3dusage(DWORD usage) DECLSPEC_HIDDEN; +const char *debug_d3dusagequery(DWORD usagequery) DECLSPEC_HIDDEN; +const char *debug_d3ddeclmethod(WINED3DDECLMETHOD method) DECLSPEC_HIDDEN; +const char *debug_d3ddeclusage(BYTE usage) DECLSPEC_HIDDEN; +const char *debug_d3dprimitivetype(WINED3DPRIMITIVETYPE PrimitiveType) DECLSPEC_HIDDEN; +const char *debug_d3drenderstate(DWORD state) DECLSPEC_HIDDEN; +const char *debug_d3dsamplerstate(DWORD state) DECLSPEC_HIDDEN; +const char *debug_d3dstate(DWORD state) DECLSPEC_HIDDEN; +const char *debug_d3dtexturefiltertype(WINED3DTEXTUREFILTERTYPE filter_type) DECLSPEC_HIDDEN; +const char *debug_d3dtexturestate(DWORD state) DECLSPEC_HIDDEN; +const char *debug_d3dtstype(WINED3DTRANSFORMSTATETYPE tstype) DECLSPEC_HIDDEN; +const char *debug_d3dpool(WINED3DPOOL pool) DECLSPEC_HIDDEN; +const char *debug_fbostatus(GLenum status) DECLSPEC_HIDDEN; +const char *debug_glerror(GLenum error) DECLSPEC_HIDDEN; +const char *debug_d3dbasis(WINED3DBASISTYPE basis) DECLSPEC_HIDDEN; +const char *debug_d3ddegree(WINED3DDEGREETYPE order) DECLSPEC_HIDDEN; +const char *debug_d3dtop(WINED3DTEXTUREOP d3dtop) DECLSPEC_HIDDEN; +void dump_color_fixup_desc(struct color_fixup_desc fixup) DECLSPEC_HIDDEN; +const char *debug_surflocation(DWORD flag) DECLSPEC_HIDDEN; + +/* Routines for GL <-> D3D values */ +GLenum StencilOp(DWORD op) DECLSPEC_HIDDEN; +GLenum CompareFunc(DWORD func) DECLSPEC_HIDDEN; +BOOL is_invalid_op(const struct wined3d_state *state, int stage, + WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) DECLSPEC_HIDDEN; +void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state, + BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, + INT texture_idx, DWORD dst) DECLSPEC_HIDDEN; +void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords, + BOOL transformed, enum wined3d_format_id coordtype, BOOL ffp_can_disable_proj) DECLSPEC_HIDDEN; +void texture_activate_dimensions(const struct wined3d_texture *texture, + const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; +void sampler_texdim(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void tex_alphaop(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void apply_pixelshader(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void state_fogcolor(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void state_fogdensity(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void state_fogstartend(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; +void state_fog_fragpart(DWORD state, struct wined3d_stateblock *stateblock, + struct wined3d_context *context) DECLSPEC_HIDDEN; + +BOOL getColorBits(const struct wined3d_format *format, + BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize) DECLSPEC_HIDDEN; +BOOL getDepthStencilBits(const struct wined3d_format *format, + BYTE *depthSize, BYTE *stencilSize) DECLSPEC_HIDDEN; + +/* Math utils */ +void multiply_matrix(WINED3DMATRIX *dest, const WINED3DMATRIX *src1, const WINED3DMATRIX *src2) DECLSPEC_HIDDEN; +UINT wined3d_log2i(UINT32 x) DECLSPEC_HIDDEN; +unsigned int count_bits(unsigned int mask) DECLSPEC_HIDDEN; + +void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, int *vs_selected) DECLSPEC_HIDDEN; + +typedef struct local_constant { + struct list entry; + unsigned int idx; + DWORD value[4]; +} local_constant; + +struct wined3d_shader_limits +{ + unsigned int temporary; + unsigned int texcoord; + unsigned int sampler; + unsigned int constant_int; + unsigned int constant_float; + unsigned int constant_bool; + unsigned int address; + unsigned int packed_output; + unsigned int packed_input; + unsigned int attributes; + unsigned int label; +}; + +#ifdef __GNUC__ +#define PRINTF_ATTR(fmt,args) __attribute__((format (printf,fmt,args))) +#else +#define PRINTF_ATTR(fmt,args) +#endif + +/* Base Shader utility functions. */ +int shader_addline(struct wined3d_shader_buffer *buffer, const char *fmt, ...) PRINTF_ATTR(2,3) DECLSPEC_HIDDEN; +int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *fmt, va_list args) DECLSPEC_HIDDEN; + +/* Vertex shader utility functions */ +extern BOOL vshader_get_input(struct wined3d_shader *shader, + BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum) DECLSPEC_HIDDEN; + +struct wined3d_vertex_shader +{ + struct wined3d_shader_attribute attributes[MAX_ATTRIBS]; +}; + +struct wined3d_pixel_shader +{ + /* Pixel shader input semantics */ + DWORD input_reg_map[MAX_REG_INPUT]; + BOOL input_reg_used[MAX_REG_INPUT]; + unsigned int declared_in_count; + + /* Some information about the shader behavior */ + char vpos_uniform; + BOOL color0_mov; + DWORD color0_reg; +}; + +struct wined3d_shader +{ + LONG ref; + struct wined3d_shader_limits limits; + DWORD *function; + UINT functionLength; + BOOL load_local_constsF; + const struct wined3d_shader_frontend *frontend; + void *frontend_data; + void *backend_data; + + void *parent; + const struct wined3d_parent_ops *parent_ops; + + /* Programs this shader is linked with */ + struct list linked_programs; + + /* Immediate constants (override global ones) */ + struct list constantsB; + struct list constantsF; + struct list constantsI; + struct wined3d_shader_reg_maps reg_maps; + + struct wined3d_shader_signature_element input_signature[max(MAX_ATTRIBS, MAX_REG_INPUT)]; + struct wined3d_shader_signature_element output_signature[MAX_REG_OUTPUT]; + + /* Pointer to the parent device */ + struct wined3d_device *device; + struct list shader_list_entry; + + union + { + struct wined3d_vertex_shader vs; + struct wined3d_pixel_shader ps; + } u; +}; + +void pixelshader_update_samplers(struct wined3d_shader_reg_maps *reg_maps, + struct wined3d_texture * const *textures) DECLSPEC_HIDDEN; +void find_ps_compile_args(const struct wined3d_state *state, + const struct wined3d_shader *shader, struct ps_compile_args *args) DECLSPEC_HIDDEN; + +void find_vs_compile_args(const struct wined3d_state *state, + const struct wined3d_shader *shader, struct vs_compile_args *args) DECLSPEC_HIDDEN; + +void shader_buffer_clear(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN; +BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN; +void shader_buffer_free(struct wined3d_shader_buffer *buffer) DECLSPEC_HIDDEN; +void shader_dump_src_param(const struct wined3d_shader_src_param *param, + const struct wined3d_shader_version *shader_version) DECLSPEC_HIDDEN; +void shader_dump_dst_param(const struct wined3d_shader_dst_param *param, + const struct wined3d_shader_version *shader_version) DECLSPEC_HIDDEN; +unsigned int shader_find_free_input_register(const struct wined3d_shader_reg_maps *reg_maps, + unsigned int max) DECLSPEC_HIDDEN; +void shader_generate_main(struct wined3d_shader *shader, struct wined3d_shader_buffer *buffer, + const struct wined3d_shader_reg_maps *reg_maps, const DWORD *pFunction, void *backend_ctx) DECLSPEC_HIDDEN; +BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage) DECLSPEC_HIDDEN; + +static inline BOOL shader_is_pshader_version(enum wined3d_shader_type type) +{ + return type == WINED3D_SHADER_TYPE_PIXEL; +} + +static inline BOOL shader_is_vshader_version(enum wined3d_shader_type type) +{ + return type == WINED3D_SHADER_TYPE_VERTEX; +} + +static inline BOOL shader_is_scalar(const struct wined3d_shader_register *reg) +{ + switch (reg->type) + { + case WINED3DSPR_RASTOUT: + /* oFog & oPts */ + if (reg->idx) return TRUE; + /* oPos */ + return FALSE; + + case WINED3DSPR_DEPTHOUT: /* oDepth */ + case WINED3DSPR_CONSTBOOL: /* b# */ + case WINED3DSPR_LOOP: /* aL */ + case WINED3DSPR_PREDICATE: /* p0 */ + return TRUE; + + case WINED3DSPR_MISCTYPE: + switch(reg->idx) + { + case 0: /* vPos */ + return FALSE; + case 1: /* vFace */ + return TRUE; + default: + return FALSE; + } + + case WINED3DSPR_IMMCONST: + return reg->immconst_type == WINED3D_IMMCONST_SCALAR; + + default: + return FALSE; + } +} + +static inline void shader_get_position_fixup(const struct wined3d_context *context, + const struct wined3d_state *state, float *position_fixup) +{ + position_fixup[0] = 1.0f; + position_fixup[1] = 1.0f; + position_fixup[2] = (63.0f / 64.0f) / state->viewport.Width; + position_fixup[3] = -(63.0f / 64.0f) / state->viewport.Height; + + if (context->render_offscreen) + { + position_fixup[1] *= -1.0f; + position_fixup[3] *= -1.0f; + } +} + +static inline BOOL shader_constant_is_local(const struct wined3d_shader *shader, DWORD reg) +{ + struct local_constant *lconst; + + if (shader->load_local_constsF) + return FALSE; + + LIST_FOR_EACH_ENTRY(lconst, &shader->constantsF, local_constant, entry) + { + if (lconst->idx == reg) + return TRUE; + } + + return FALSE; +} + +/* Using additional shader constants (uniforms in GLSL / program environment + * or local parameters in ARB) is costly: + * ARB only knows float4 parameters and GLSL compiler are not really smart + * when it comes to efficiently pack float2 uniforms, so no space is wasted + * (in fact most compilers map a float2 to a full float4 uniform). + * + * For NP2 texcoord fixup we only need 2 floats (width and height) for each + * 2D texture used in the shader. We therefore pack fixup info for 2 textures + * into a single shader constant (uniform / program parameter). + * + * This structure is shared between the GLSL and the ARB backend.*/ +struct ps_np2fixup_info { + unsigned char idx[MAX_FRAGMENT_SAMPLERS]; /* indices to the real constant */ + WORD active; /* bitfield indicating if we can apply the fixup */ + WORD num_consts; +}; + +/* sRGB correction constants */ +static const float srgb_cmp = 0.0031308f; +static const float srgb_mul_low = 12.92f; +static const float srgb_pow = 0.41666f; +static const float srgb_mul_high = 1.055f; +static const float srgb_sub_high = 0.055f; + +struct wined3d_palette +{ + LONG ref; + void *parent; + struct wined3d_device *device; + + HPALETTE hpal; + WORD palVersion; /*| */ + WORD palNumEntries; /*| LOGPALETTE */ + PALETTEENTRY palents[256]; /*| */ + /* This is to store the palette in 'screen format' */ + int screen_palents[256]; + DWORD flags; +}; + +/* DirectDraw utility functions */ +extern enum wined3d_format_id pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN; + +/***************************************************************************** + * Pixel format management + */ + +/* WineD3D pixel format flags */ +#define WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING 0x00000001 +#define WINED3DFMT_FLAG_FILTERING 0x00000002 +#define WINED3DFMT_FLAG_DEPTH 0x00000004 +#define WINED3DFMT_FLAG_STENCIL 0x00000008 +#define WINED3DFMT_FLAG_RENDERTARGET 0x00000010 +#define WINED3DFMT_FLAG_FOURCC 0x00000020 +#define WINED3DFMT_FLAG_FBO_ATTACHABLE 0x00000040 +#define WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB 0x00000080 +#define WINED3DFMT_FLAG_GETDC 0x00000100 +#define WINED3DFMT_FLAG_FLOAT 0x00000200 +#define WINED3DFMT_FLAG_BUMPMAP 0x00000400 +#define WINED3DFMT_FLAG_SRGB_READ 0x00000800 +#define WINED3DFMT_FLAG_SRGB_WRITE 0x00001000 +#define WINED3DFMT_FLAG_VTF 0x00002000 +#define WINED3DFMT_FLAG_SHADOW 0x00004000 +#define WINED3DFMT_FLAG_COMPRESSED 0x00008000 +#define WINED3DFMT_FLAG_BROKEN_PITCH 0x00010000 + +struct wined3d_format +{ + enum wined3d_format_id id; + + DWORD red_mask; + DWORD green_mask; + DWORD blue_mask; + DWORD alpha_mask; + UINT byte_count; + BYTE depth_size; + BYTE stencil_size; + + UINT block_width; + UINT block_height; + UINT block_byte_count; + + enum wined3d_ffp_emit_idx emit_idx; + GLint component_count; + GLenum gl_vtx_type; + GLint gl_vtx_format; + GLboolean gl_normalized; + unsigned int component_size; + + GLint glInternal; + GLint glGammaInternal; + GLint rtInternal; + GLint glFormat; + GLint glType; + UINT conv_byte_count; + unsigned int flags; + float heightscale; + struct color_fixup_desc color_fixup; + void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height); +}; + +const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info, + enum wined3d_format_id format_id) DECLSPEC_HIDDEN; +UINT wined3d_format_calculate_size(const struct wined3d_format *format, + UINT alignment, UINT width, UINT height) DECLSPEC_HIDDEN; +DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, + const WINED3DCOLORVALUE *color) DECLSPEC_HIDDEN; + +static inline BOOL use_vs(const struct wined3d_state *state) +{ + /* Check stateblock->vertexDecl to allow this to be used from + * IWineD3DDeviceImpl_FindTexUnitMap(). This is safe because + * stateblock->vertexShader implies a vertex declaration instead of ddraw + * style strided data. */ + return state->vertex_shader && !state->vertex_declaration->position_transformed; +} + +static inline BOOL use_ps(const struct wined3d_state *state) +{ + return !!state->pixel_shader; +} + +/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ +#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL" + +#define MAKEDWORD_VERSION(maj, min) (((maj & 0xffff) << 16) | (min & 0xffff)) + +#endif diff --cc reactos/include/reactos/wine/math.h index 00000000000,00000000000..1d86ef9a7df new file mode 100644 --- /dev/null +++ b/reactos/include/reactos/wine/math.h @@@ -1,0 -1,0 +1,26 @@@ ++#ifndef __WINE_MATH_H_ ++#define __WINE_MATH_H_ ++ ++#include ++ ++#ifdef _MSC_VER ++__forceinline float _NaN() ++{ ++ unsigned long NaN = 0x7fc00000; ++ return *(float*)&NaN; ++} ++#define NAN _NaN() ++ ++__forceinline float _Infinity() ++{ ++ unsigned long Infinity = 0x7f800000; ++ return *(float*)&Infinity; ++} ++#define INFINITY _Infinity() ++ ++#else ++#define NAN (0.0f / 0.0f) ++#define INFINITY (1.0F/0.0F) ++#endif ++ ++#endif /* __WINE_MATH_H_ */