[WINED3D]
[reactos.git] / reactos / dll / directx / wine / wined3d / directx.c
index dd0ec43..267ed0b 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <config.h>
-#include <wine/port.h>
-
-#include <stdio.h>
-
 #include "wined3d_private.h"
-//#include "winternl.h"
+#include <winternl.h>
+#include <winnls.h>
+
+#include <wine/unicode.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 #define WINE_DEFAULT_VIDMEM (64 * 1024 * 1024)
+#define DEFAULT_REFRESH_RATE 0
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
+#endif
 
 /* The driver names reflect the lowest GPU supported
  * by a certain driver, so DRIVER_AMD_R300 supports
@@ -50,6 +55,7 @@ enum wined3d_display_driver
     DRIVER_NVIDIA_GEFORCE2MX,
     DRIVER_NVIDIA_GEFORCEFX,
     DRIVER_NVIDIA_GEFORCE6,
+    DRIVER_VMWARE,
     DRIVER_UNKNOWN
 };
 
@@ -66,11 +72,23 @@ enum wined3d_gl_vendor
     GL_VENDOR_UNKNOWN,
     GL_VENDOR_APPLE,
     GL_VENDOR_FGLRX,
-    GL_VENDOR_INTEL,
     GL_VENDOR_MESA,
     GL_VENDOR_NVIDIA,
 };
 
+enum wined3d_d3d_level
+{
+    WINED3D_D3D_LEVEL_5,
+    WINED3D_D3D_LEVEL_6,
+    WINED3D_D3D_LEVEL_7,
+    WINED3D_D3D_LEVEL_8,
+    WINED3D_D3D_LEVEL_9_SM2,
+    WINED3D_D3D_LEVEL_9_SM3,
+    WINED3D_D3D_LEVEL_10,
+    WINED3D_D3D_LEVEL_11,
+    WINED3D_D3D_LEVEL_COUNT
+};
+
 /* The d3d device ID */
 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
 
@@ -91,7 +109,9 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_APPLE_ycbcr_422",                  APPLE_YCBCR_422               },
 
     /* ARB */
+    {"GL_ARB_blend_func_extended",          ARB_BLEND_FUNC_EXTENDED       },
     {"GL_ARB_color_buffer_float",           ARB_COLOR_BUFFER_FLOAT        },
+    {"GL_ARB_debug_output",                 ARB_DEBUG_OUTPUT              },
     {"GL_ARB_depth_buffer_float",           ARB_DEPTH_BUFFER_FLOAT        },
     {"GL_ARB_depth_clamp",                  ARB_DEPTH_CLAMP               },
     {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE             },
@@ -106,6 +126,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_half_float_pixel",             ARB_HALF_FLOAT_PIXEL          },
     {"GL_ARB_half_float_vertex",            ARB_HALF_FLOAT_VERTEX         },
     {"GL_ARB_instanced_arrays",             ARB_INSTANCED_ARRAYS,         },
+    {"GL_ARB_internalformat_query2",        ARB_INTERNALFORMAT_QUERY2,    },
     {"GL_ARB_map_buffer_alignment",         ARB_MAP_BUFFER_ALIGNMENT      },
     {"GL_ARB_map_buffer_range",             ARB_MAP_BUFFER_RANGE          },
     {"GL_ARB_multisample",                  ARB_MULTISAMPLE               }, /* needs GLX_ARB_MULTISAMPLE as well */
@@ -130,9 +151,12 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_texture_env_dot3",             ARB_TEXTURE_ENV_DOT3          },
     {"GL_ARB_texture_float",                ARB_TEXTURE_FLOAT             },
     {"GL_ARB_texture_mirrored_repeat",      ARB_TEXTURE_MIRRORED_REPEAT   },
+    {"GL_ARB_texture_mirror_clamp_to_edge", ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE},
     {"GL_ARB_texture_non_power_of_two",     ARB_TEXTURE_NON_POWER_OF_TWO  },
     {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE         },
     {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG                },
+    {"GL_ARB_timer_query",                  ARB_TIMER_QUERY               },
+    {"GL_ARB_uniform_buffer_object",        ARB_UNIFORM_BUFFER_OBJECT     },
     {"GL_ARB_vertex_array_bgra",            ARB_VERTEX_ARRAY_BGRA         },
     {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND              },
     {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT      },
@@ -161,7 +185,6 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_EXT_gpu_program_parameters",       EXT_GPU_PROGRAM_PARAMETERS    },
     {"GL_EXT_gpu_shader4",                  EXT_GPU_SHADER4               },
     {"GL_EXT_packed_depth_stencil",         EXT_PACKED_DEPTH_STENCIL      },
-    {"GL_EXT_paletted_texture",             EXT_PALETTED_TEXTURE          },
     {"GL_EXT_point_parameters",             EXT_POINT_PARAMETERS          },
     {"GL_EXT_provoking_vertex",             EXT_PROVOKING_VERTEX          },
     {"GL_EXT_secondary_color",              EXT_SECONDARY_COLOR           },
@@ -175,6 +198,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_EXT_texture_env_dot3",             EXT_TEXTURE_ENV_DOT3          },
     {"GL_EXT_texture_filter_anisotropic",   EXT_TEXTURE_FILTER_ANISOTROPIC},
     {"GL_EXT_texture_lod_bias",             EXT_TEXTURE_LOD_BIAS          },
+    {"GL_EXT_texture_mirror_clamp",         EXT_TEXTURE_MIRROR_CLAMP      },
     {"GL_EXT_texture_sRGB",                 EXT_TEXTURE_SRGB              },
     {"GL_EXT_texture_sRGB_decode",          EXT_TEXTURE_SRGB_DECODE       },
     {"GL_EXT_vertex_array_bgra",            EXT_VERTEX_ARRAY_BGRA         },
@@ -252,21 +276,7 @@ const GLenum magLookup_noFilter[] =
     GL_NEAREST, GL_NEAREST, GL_NEAREST,
 };
 
-/* drawStridedSlow attributes */
-glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc specular_func_3ubv;
-glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
-glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
-glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
-
-/**
- * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
- * i.e., there is no GL Context - Get a default rendering context to enable the
- * function query some info from GL.
- */
-
-struct wined3d_fake_gl_ctx
+struct wined3d_caps_gl_ctx
 {
     HDC dc;
     HWND wnd;
@@ -275,12 +285,12 @@ struct wined3d_fake_gl_ctx
     HGLRC restore_gl_ctx;
 };
 
-static void WineD3D_ReleaseFakeGLContext(const struct wined3d_fake_gl_ctx *ctx)
+static void wined3d_caps_gl_ctx_destroy(const struct wined3d_caps_gl_ctx *ctx)
 {
-    TRACE("Destroying fake GL context.\n");
+    TRACE("Destroying caps GL context.\n");
 
     if (!wglMakeCurrent(NULL, NULL))
-        ERR("Failed to disable fake GL context.\n");
+        ERR("Failed to disable caps GL context.\n");
 
     if (!wglDeleteContext(ctx->gl_ctx))
     {
@@ -288,15 +298,43 @@ static void WineD3D_ReleaseFakeGLContext(const struct wined3d_fake_gl_ctx *ctx)
         ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
     }
 
-    ReleaseDC(ctx->wnd, ctx->dc);
+    wined3d_release_dc(ctx->wnd, ctx->dc);
     DestroyWindow(ctx->wnd);
 
     if (ctx->restore_gl_ctx && !wglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
         ERR("Failed to restore previous GL context.\n");
 }
 
-/* Do not call while under the GL lock. */
-static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
+static void wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_gl_ctx,
+        struct wined3d_gl_info *gl_info, const GLint *ctx_attribs)
+{
+    HGLRC new_ctx;
+
+    if (!(gl_info->p_wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB")))
+        return;
+
+    if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(caps_gl_ctx->dc, NULL, ctx_attribs)))
+    {
+        ERR("Failed to create a context using wglCreateContextAttribsARB(), last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglMakeCurrent(caps_gl_ctx->dc, new_ctx))
+    {
+        ERR("Failed to make new context current, last error %#x.\n", GetLastError());
+        if (!wglDeleteContext(new_ctx))
+            ERR("Failed to delete new context, last error %#x.\n", GetLastError());
+        gl_info->p_wglCreateContextAttribsARB = NULL;
+        return;
+    }
+
+    if (!wglDeleteContext(caps_gl_ctx->gl_ctx))
+        ERR("Failed to delete old context, last error %#x.\n", GetLastError());
+    caps_gl_ctx->gl_ctx = new_ctx;
+}
+
+static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx)
 {
     PIXELFORMATDESCRIPTOR pfd;
     int iPixelFormat;
@@ -350,7 +388,7 @@ static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
     /* Make it the current GL context. */
     if (!wglMakeCurrent(ctx->dc, ctx->gl_ctx))
     {
-        ERR("Failed to make fake GL context current.\n");
+        ERR("Failed to make caps GL context current.\n");
         goto fail;
     }
 
@@ -370,11 +408,13 @@ fail:
 }
 
 /* Adjust the amount of used texture memory */
-unsigned int adapter_adjust_memory(struct wined3d_adapter *adapter, int amount)
+UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount)
 {
-    adapter->UsedTextureRam += amount;
-    TRACE("Adjusted adapter memory by %d to %d.\n", amount, adapter->UsedTextureRam);
-    return adapter->UsedTextureRam;
+    adapter->vram_bytes_used += amount;
+    TRACE("Adjusted used adapter memory by 0x%s to 0x%s.\n",
+            wine_dbgstr_longlong(amount),
+            wine_dbgstr_longlong(adapter->vram_bytes_used));
+    return adapter->vram_bytes_used;
 }
 
 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
@@ -417,7 +457,7 @@ static BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
 {
     GLuint prog;
     BOOL ret = FALSE;
-    const char *testcode =
+    static const char testcode[] =
         "!!ARBvp1.0\n"
         "PARAM C[66] = { program.env[0..65] };\n"
         "ADDRESS A0;"
@@ -553,7 +593,7 @@ static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
 
     if (memcmp(check, pattern, sizeof(check)))
     {
-        WARN("PBO test failed, read back data doesn't match original.\n"
+        WARN_(d3d_perf)("PBO test failed, read back data doesn't match original.\n"
                 "Disabling PBOs. This may result in slower performance.\n");
         gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
     }
@@ -584,7 +624,7 @@ static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char
     /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
      * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
      * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
-     * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
+     * varyings and we subtract one in dx9 shaders it's not going to hurt us because the dx9 limit is
      * hardcoded
      *
      * dx10 cards usually have 64 varyings */
@@ -631,7 +671,7 @@ static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const ch
     GLuint prog;
     BOOL ret = FALSE;
     GLint pos;
-    const char *testcode =
+    static const char testcode[] =
         "!!ARBvp1.0\n"
         "OPTION NV_vertex_program2;\n"
         "MOV result.clip[0], 0.0;\n"
@@ -759,6 +799,101 @@ static BOOL match_r200(const struct wined3d_gl_info *gl_info, const char *gl_ren
     return FALSE;
 }
 
+static BOOL match_broken_arb_fog(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
+        enum wined3d_gl_vendor gl_vendor, enum wined3d_pci_vendor card_vendor, enum wined3d_pci_device device)
+{
+    DWORD data[4];
+    GLuint tex, fbo;
+    GLenum status;
+    float color[4] = {0.0f, 1.0f, 0.0f, 0.0f};
+    GLuint prog;
+    GLint err_pos;
+    static const char program_code[] =
+        "!!ARBfp1.0\n"
+        "OPTION ARB_fog_linear;\n"
+        "MOV result.color, {1.0, 0.0, 0.0, 0.0};\n"
+        "END\n";
+
+    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+        return FALSE;
+    if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
+        return FALSE;
+
+    gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+    checkGLcall("glTexImage2D");
+
+    gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+    gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
+    checkGLcall("glFramebufferTexture2D");
+
+    status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE) ERR("FBO status %#x\n", status);
+    checkGLcall("glCheckFramebufferStatus");
+
+    gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
+    gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
+    checkGLcall("glClear");
+    gl_info->gl_ops.gl.p_glViewport(0, 0, 4, 1);
+    checkGLcall("glViewport");
+
+    gl_info->gl_ops.gl.p_glEnable(GL_FOG);
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_START, 0.5f);
+    gl_info->gl_ops.gl.p_glFogf(GL_FOG_END, 0.5f);
+    gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
+    gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_NICEST);
+    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_COLOR, color);
+    checkGLcall("fog setup");
+
+    GL_EXTCALL(glGenProgramsARB(1, &prog));
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog));
+    GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
+            strlen(program_code), program_code));
+    gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
+    checkGLcall("Test fragment program setup");
+
+    gl_info->gl_ops.gl.p_glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &err_pos);
+    if (err_pos != -1)
+    {
+        const char *error_str;
+        error_str = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+        FIXME("Fog test program error at position %d: %s\n\n", err_pos, debugstr_a(error_str));
+    }
+
+    gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+    gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f,  0.0f);
+    gl_info->gl_ops.gl.p_glVertex3f( 1.0f, -1.0f,  1.0f);
+    gl_info->gl_ops.gl.p_glVertex3f(-1.0f,  1.0f,  0.0f);
+    gl_info->gl_ops.gl.p_glVertex3f( 1.0f,  1.0f,  1.0f);
+    gl_info->gl_ops.gl.p_glEnd();
+    checkGLcall("ARBfp fog test draw");
+
+    gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+    checkGLcall("glGetTexImage");
+    data[0] &= 0x00ffffff;
+    data[1] &= 0x00ffffff;
+    data[2] &= 0x00ffffff;
+    data[3] &= 0x00ffffff;
+
+    gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, 0);
+
+    gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
+    gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
+    gl_info->gl_ops.gl.p_glDisable(GL_FOG);
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0));
+    gl_info->gl_ops.gl.p_glDisable(GL_FRAGMENT_PROGRAM_ARB);
+    GL_EXTCALL(glDeleteProgramsARB(1, &prog));
+    checkGLcall("ARBfp fog test teardown");
+
+    TRACE("Fog test data: %08x %08x %08x %08x\n", data[0], data[1], data[2], data[3]);
+    return data[0] != 0x00ff0000 || data[3] != 0x0000ff00;
+}
+
 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
 {
     /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
@@ -882,6 +1017,11 @@ static void quirk_r200_constants(struct wined3d_gl_info *gl_info)
     gl_info->reserved_arb_constants = max(gl_info->reserved_arb_constants, 1);
 }
 
+static void quirk_broken_arb_fog(struct wined3d_gl_info *gl_info)
+{
+    gl_info->quirks |= WINED3D_QUIRK_BROKEN_ARB_FOG;
+}
+
 struct driver_quirk
 {
     BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
@@ -967,6 +1107,11 @@ static const struct driver_quirk quirk_table[] =
         quirk_r200_constants,
         "r200 vertex shader constants"
     },
+    {
+        match_broken_arb_fog,
+        quirk_broken_arb_fog,
+        "ARBfp fogstart == fogend workaround"
+    },
 };
 
 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
@@ -1044,6 +1189,9 @@ static const struct driver_version_information driver_version_table[] =
     {DRIVER_NVIDIA_GEFORCEFX,   DRIVER_MODEL_NT5X,  "nv4_disp.dll", 14, 11, 7516},
     {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT5X,  "nv4_disp.dll", 15, 12, 6658},
     {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT6X,  "nvd3dum.dll",  15, 12, 6658},
+
+    /* VMware */
+    {DRIVER_VMWARE,             DRIVER_MODEL_NT5X,  "vm3dum.dll",   14, 1,  1134},
 };
 
 struct gpu_description
@@ -1097,7 +1245,9 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX260,     "NVIDIA GeForce GTX 260",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX275,     "NVIDIA GeForce GTX 275",           DRIVER_NVIDIA_GEFORCE6,  896 },
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX280,     "NVIDIA GeForce GTX 280",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_315M,       "NVIDIA GeForce 315M",              DRIVER_NVIDIA_GEFORCE6,  512 },
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_320M,       "NVIDIA GeForce 320M",              DRIVER_NVIDIA_GEFORCE6,  256},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_410M,       "NVIDIA GeForce 410M",              DRIVER_NVIDIA_GEFORCE6,  512},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT320M,     "NVIDIA GeForce GT 320M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT325M,     "NVIDIA GeForce GT 325M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT330,      "NVIDIA GeForce GT 330",            DRIVER_NVIDIA_GEFORCE6,  1024},
@@ -1120,15 +1270,26 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX570,     "NVIDIA GeForce GTX 570",           DRIVER_NVIDIA_GEFORCE6,  1280},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX580,     "NVIDIA GeForce GTX 580",           DRIVER_NVIDIA_GEFORCE6,  1536},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT610,      "NVIDIA GeForce GT 610",            DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630,      "NVIDIA GeForce GT 630",            DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630M,     "NVIDIA GeForce GT 630M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT640M,     "NVIDIA GeForce GT 640M",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT650M,     "NVIDIA GeForce GT 650M",           DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650,     "NVIDIA GeForce GTX 650",           DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650TI,   "NVIDIA GeForce GTX 650 Ti",        DRIVER_NVIDIA_GEFORCE6,  1024},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660,     "NVIDIA GeForce GTX 660",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660M,    "NVIDIA GeForce GTX 660M",          DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660TI,   "NVIDIA GeForce GTX 660 Ti",        DRIVER_NVIDIA_GEFORCE6,  2048},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670,     "NVIDIA GeForce GTX 670",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670MX,   "NVIDIA GeForce GTX 670MX",         DRIVER_NVIDIA_GEFORCE6,  3072},
     {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX680,     "NVIDIA GeForce GTX 680",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX750,     "NVIDIA GeForce GTX 750",           DRIVER_NVIDIA_GEFORCE6,  1024},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX750TI,   "NVIDIA GeForce GTX 750 Ti",        DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX760,     "NVIDIA Geforce GTX 760",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX765M,    "NVIDIA GeForce GTX 765M",          DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770M,    "NVIDIA GeForce GTX 770M",          DRIVER_NVIDIA_GEFORCE6,  3072},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770,     "NVIDIA GeForce GTX 770",           DRIVER_NVIDIA_GEFORCE6,  2048},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780,     "NVIDIA GeForce GTX 780",           DRIVER_NVIDIA_GEFORCE6,  3072},
+    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780TI,   "NVIDIA GeForce GTX 780 Ti",        DRIVER_NVIDIA_GEFORCE6,  3072},
 
     /* AMD cards */
     {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
@@ -1142,6 +1303,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3200,         "ATI Radeon HD 3200 Graphics",      DRIVER_AMD_R600,         128 },
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4200M,        "ATI Mobility Radeon HD 4200",      DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4350,         "ATI Radeon HD 4350",               DRIVER_AMD_R600,         256 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        DRIVER_AMD_R600,         512 },
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4700,         "ATI Radeon HD 4700 Series",        DRIVER_AMD_R600,         512 },
@@ -1160,9 +1322,20 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6700,         "AMD Radeon HD 6700 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6800,         "AMD Radeon HD 6800 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6900,         "AMD Radeon HD 6900 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7660D,        "AMD Radeon HD 7660D",              DRIVER_AMD_R600,         2048},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7700,         "AMD Radeon HD 7700 Series",        DRIVER_AMD_R600,         1024},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7800,         "AMD Radeon HD 7800 Series",        DRIVER_AMD_R600,         2048},
     {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7900,         "AMD Radeon HD 7900 Series",        DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8600M,        "AMD Radeon HD 8600M Series",       DRIVER_AMD_R600,         1024},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8670,         "AMD Radeon HD 8670",               DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8770,         "AMD Radeon HD 8770",               DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R3,             "AMD Radeon HD 8400 / R3 Series",   DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R7,             "AMD Radeon(TM) R7 Graphics",       DRIVER_AMD_R600,         2048},
+    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9,             "AMD Radeon R9 290",                DRIVER_AMD_R600,         4096},
+
+    /* VMware */
+    {HW_VENDOR_VMWARE,     CARD_VMWARE_SVGA3D,             "VMware SVGA 3D (Microsoft Corporation - WDDM)",             DRIVER_VMWARE,        1024},
+
     /* Intel cards */
     {HW_VENDOR_INTEL,      CARD_INTEL_830M,                "Intel(R) 82830M Graphics Controller",                       DRIVER_INTEL_GMA800,  32 },
     {HW_VENDOR_INTEL,      CARD_INTEL_855GM,               "Intel(R) 82852/82855 GM/GME Graphics Controller",           DRIVER_INTEL_GMA800,  32 },
@@ -1198,6 +1371,7 @@ static const struct gpu_description gpu_description_table[] =
     {HW_VENDOR_INTEL,      CARD_INTEL_IVBD,                "Intel(R) Ivybridge Desktop",                                DRIVER_INTEL_GMA3000, 1024},
     {HW_VENDOR_INTEL,      CARD_INTEL_IVBM,                "Intel(R) Ivybridge Mobile",                                 DRIVER_INTEL_GMA3000, 1024},
     {HW_VENDOR_INTEL,      CARD_INTEL_IVBS,                "Intel(R) Ivybridge Server",                                 DRIVER_INTEL_GMA3000, 1024},
+    {HW_VENDOR_INTEL,      CARD_INTEL_HWM,                 "Intel(R) Haswell Mobile",                                   DRIVER_INTEL_GMA3000, 1024},
 };
 
 static const struct driver_version_information *get_driver_version_info(enum wined3d_display_driver driver,
@@ -1220,33 +1394,56 @@ static const struct driver_version_information *get_driver_version_info(enum win
     return NULL;
 }
 
+static const struct gpu_description *get_gpu_description(enum wined3d_pci_vendor vendor,
+        enum wined3d_pci_device device)
+{
+    unsigned int i;
+
+    for (i = 0; i < (sizeof(gpu_description_table) / sizeof(*gpu_description_table)); ++i)
+    {
+        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].card)
+            return &gpu_description_table[i];
+    }
+
+    return NULL;
+}
+
 static void init_driver_info(struct wined3d_driver_info *driver_info,
         enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
 {
     OSVERSIONINFOW os_version;
     WORD driver_os_version;
-    unsigned int i;
-    enum wined3d_display_driver driver = DRIVER_UNKNOWN;
+    enum wined3d_display_driver driver;
     enum wined3d_driver_model driver_model;
     const struct driver_version_information *version_info;
+    const struct gpu_description *gpu_desc;
 
-    if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
+    if (driver_info->vendor != PCI_VENDOR_NONE || driver_info->device != PCI_DEVICE_NONE)
     {
-        TRACE("Overriding PCI vendor ID with 0x%04x.\n", wined3d_settings.pci_vendor_id);
-        vendor = wined3d_settings.pci_vendor_id;
-    }
-    driver_info->vendor = vendor;
+        static unsigned int once;
 
-    if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
-    {
-        TRACE("Overriding PCI device ID with 0x%04x.\n", wined3d_settings.pci_device_id);
-        device = wined3d_settings.pci_device_id;
+        TRACE("GPU override %04x:%04x.\n", wined3d_settings.pci_vendor_id, wined3d_settings.pci_device_id);
+
+        driver_info->vendor = wined3d_settings.pci_vendor_id;
+        if (driver_info->vendor == PCI_VENDOR_NONE)
+            driver_info->vendor = vendor;
+
+        driver_info->device = wined3d_settings.pci_device_id;
+        if (driver_info->device == PCI_DEVICE_NONE)
+            driver_info->device = device;
+
+        if (get_gpu_description(driver_info->vendor, driver_info->device))
+        {
+            vendor = driver_info->vendor;
+            device = driver_info->device;
+        }
+        else if (!once++)
+            ERR_(winediag)("Invalid GPU override %04x:%04x specified, ignoring.\n",
+                    driver_info->vendor, driver_info->device);
     }
-    driver_info->device = device;
 
-    /* Set a default amount of video memory (64MB). In general this code isn't used unless the user
-     * overrides the pci ids to a card which is not in our database. */
-    driver_info->vidmem = WINE_DEFAULT_VIDMEM;
+    driver_info->vendor = vendor;
+    driver_info->device = device;
 
     memset(&os_version, 0, sizeof(os_version));
     os_version.dwOSVersionInfoSize = sizeof(os_version);
@@ -1280,14 +1477,19 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
                     driver_os_version = 7;
                     driver_model = DRIVER_MODEL_NT6X;
                 }
+                else if (os_version.dwMinorVersion == 1)
+                {
+                    driver_os_version = 8;
+                    driver_model = DRIVER_MODEL_NT6X;
+                }
                 else
                 {
-                    if (os_version.dwMinorVersion > 1)
+                    if (os_version.dwMinorVersion > 2)
                     {
-                        FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
+                        FIXME("Unhandled OS version %u.%u, reporting Win 8.\n",
                                 os_version.dwMajorVersion, os_version.dwMinorVersion);
                     }
-                    driver_os_version = 8;
+                    driver_os_version = 9;
                     driver_model = DRIVER_MODEL_NT6X;
                 }
                 break;
@@ -1301,25 +1503,25 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
         }
     }
 
-    /* When we reach this stage we always have a vendor or device id (it can be a default one).
-     * This means that unless the ids are overridden, we will always find a GPU description. */
-    for (i = 0; i < (sizeof(gpu_description_table) / sizeof(gpu_description_table[0])); i++)
+    if ((gpu_desc = get_gpu_description(driver_info->vendor, driver_info->device)))
     {
-        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].card)
-        {
-            TRACE("Found card %04x:%04x in driver DB.\n", vendor, device);
-
-            driver_info->description = gpu_description_table[i].description;
-            driver_info->vidmem = gpu_description_table[i].vidmem * 1024*1024;
-            driver = gpu_description_table[i].driver;
-            break;
-        }
+        driver_info->description = gpu_desc->description;
+        driver_info->vram_bytes = (UINT64)gpu_desc->vidmem * 1024 * 1024;
+        driver = gpu_desc->driver;
+    }
+    else
+    {
+        ERR("Card %04x:%04x not found in driver DB.\n", vendor, device);
+        driver_info->description = "Direct3D HAL";
+        driver_info->vram_bytes = WINE_DEFAULT_VIDMEM;
+        driver = DRIVER_UNKNOWN;
     }
 
     if (wined3d_settings.emulated_textureram)
     {
-        TRACE("Overriding amount of video memory with %u bytes.\n", wined3d_settings.emulated_textureram);
-        driver_info->vidmem = wined3d_settings.emulated_textureram;
+        TRACE("Overriding amount of video memory with 0x%s bytes.\n",
+                wine_dbgstr_longlong(wined3d_settings.emulated_textureram));
+        driver_info->vram_bytes = wined3d_settings.emulated_textureram;
     }
 
     /* Try to obtain driver version information for the current Windows version. This fails in
@@ -1335,8 +1537,8 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
      * - the gpu is not in our database (can happen when the user overrides the vendor_id / device_id)
      *   This could be an indication that our database is not up to date, so this should be fixed.
      */
-    version_info = get_driver_version_info(driver, driver_model);
-    if (version_info)
+    if ((version_info = get_driver_version_info(driver, driver_model))
+            || (version_info = get_driver_version_info(driver, DRIVER_MODEL_NT5X)))
     {
         driver_info->name = version_info->driver_name;
         driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
@@ -1344,23 +1546,11 @@ static void init_driver_info(struct wined3d_driver_info *driver_info,
     }
     else
     {
-        version_info = get_driver_version_info(driver, DRIVER_MODEL_NT5X);
-        if (version_info)
-        {
-            driver_info->name = version_info->driver_name;
-            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, version_info->version);
-            driver_info->version_low = MAKEDWORD_VERSION(version_info->subversion, version_info->build);
-        }
-        else
-        {
-            driver_info->description = "Direct3D HAL";
-            driver_info->name = "Display";
-            driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
-            driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
-
-            FIXME("Unable to find a driver/device info for vendor_id=%#x device_id=%#x for driver_model=%d\n",
-                    vendor, device, driver_model);
-        }
+        ERR("No driver version info found for device %04x:%04x, driver model %#x.\n",
+                vendor, device, driver_model);
+        driver_info->name = "Display";
+        driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
+        driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
     }
 
     TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
@@ -1430,20 +1620,16 @@ static enum wined3d_gl_vendor wined3d_guess_gl_vendor(const struct wined3d_gl_in
     if (strstr(gl_vendor_string, "ATI"))
         return GL_VENDOR_FGLRX;
 
-    if (strstr(gl_vendor_string, "Intel(R)")
-            /* Intel switched from Intel(R) to Intel® recently, so just match Intel. */
-            || strstr(gl_renderer, "Intel")
-            || strstr(gl_vendor_string, "Intel Inc."))
-        return GL_VENDOR_INTEL;
-
     if (strstr(gl_vendor_string, "Mesa")
             || strstr(gl_vendor_string, "X.Org")
             || strstr(gl_vendor_string, "Advanced Micro Devices, Inc.")
             || strstr(gl_vendor_string, "DRI R300 Project")
             || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
             || strstr(gl_vendor_string, "VMware, Inc.")
+            || strstr(gl_vendor_string, "Intel")
             || strstr(gl_renderer, "Mesa")
-            || strstr(gl_renderer, "Gallium"))
+            || strstr(gl_renderer, "Gallium")
+            || strstr(gl_renderer, "Intel"))
         return GL_VENDOR_MESA;
 
     FIXME("Received unrecognized GL_VENDOR %s. Returning GL_VENDOR_UNKNOWN.\n",
@@ -1477,6 +1663,9 @@ static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_s
             || strstr(gl_vendor_string, "Intel Inc."))
         return HW_VENDOR_INTEL;
 
+    if (strstr(gl_renderer, "SVGA3D"))
+        return HW_VENDOR_VMWARE;
+
     if (strstr(gl_vendor_string, "Mesa")
             || strstr(gl_vendor_string, "Brian Paul")
             || strstr(gl_vendor_string, "Tungsten Graphics, Inc")
@@ -1488,675 +1677,561 @@ static enum wined3d_pci_vendor wined3d_guess_card_vendor(const char *gl_vendor_s
     return HW_VENDOR_NVIDIA;
 }
 
-static UINT d3d_level_from_gl_info(const struct wined3d_gl_info *gl_info)
-{
-    UINT level = 0;
-
-    if (gl_info->supported[ARB_MULTITEXTURE])
-        level = 6;
-    if (gl_info->supported[ARB_TEXTURE_COMPRESSION]
-            && gl_info->supported[ARB_TEXTURE_CUBE_MAP]
-            && gl_info->supported[ARB_TEXTURE_ENV_DOT3])
-        level = 7;
-    if (level == 7 && gl_info->supported[ARB_MULTISAMPLE]
-            && gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
-        level = 8;
-    if (level == 8 && gl_info->supported[ARB_FRAGMENT_PROGRAM]
-            && gl_info->supported[ARB_VERTEX_SHADER])
-        level = 9;
-    if (level == 9 && gl_info->supported[EXT_GPU_SHADER4])
-        level = 10;
-
-    return level;
-}
+static const struct wined3d_shader_backend_ops *select_shader_backend(const struct wined3d_gl_info *gl_info);
+static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info, const struct wined3d_shader_backend_ops *shader_backend_ops);
 
-static enum wined3d_pci_device select_card_nvidia_binary(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+static enum wined3d_d3d_level d3d_level_from_gl_info(const struct wined3d_gl_info *gl_info)
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-    unsigned int i;
-
-    if (d3d_level >= 10)
-    {
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            {"GTX 680",     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
-            {"GTX 670",     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
-            {"GTX 660 Ti",  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
-            {"GTX 660",     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
-            {"GTX 650 Ti",  CARD_NVIDIA_GEFORCE_GTX650TI},  /* Geforce 600 - lowend */
-            {"GTX 650",     CARD_NVIDIA_GEFORCE_GTX650},    /* Geforce 600 - lowend */
-            {"GT 650M",     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
-            {"GT 640M",     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
-            {"GT 630M",     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
-            {"GT 610",      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
-            {"GTX 580",     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
-            {"GTX 570",     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
-            {"GTX 560 Ti",  CARD_NVIDIA_GEFORCE_GTX560TI},  /* Geforce 500 - midend */
-            {"GTX 560",     CARD_NVIDIA_GEFORCE_GTX560},    /* Geforce 500 - midend */
-            {"GT 555M",     CARD_NVIDIA_GEFORCE_GT555M},    /* Geforce 500 - midend mobile */
-            {"GTX 550 Ti",  CARD_NVIDIA_GEFORCE_GTX550},    /* Geforce 500 - midend */
-            {"GT 540M",     CARD_NVIDIA_GEFORCE_GT540M},    /* Geforce 500 - midend mobile */
-            {"GT 520",      CARD_NVIDIA_GEFORCE_GT520},     /* Geforce 500 - lowend */
-            {"GTX 480",     CARD_NVIDIA_GEFORCE_GTX480},    /* Geforce 400 - highend */
-            {"GTX 470",     CARD_NVIDIA_GEFORCE_GTX470},    /* Geforce 400 - midend high */
-            {"GTX 465",     CARD_NVIDIA_GEFORCE_GTX465},    /* Geforce 400 - midend */
-            {"GTX 460M",    CARD_NVIDIA_GEFORCE_GTX460M},   /* Geforce 400 - highend mobile */
-            {"GTX 460",     CARD_NVIDIA_GEFORCE_GTX460},    /* Geforce 400 - midend */
-            {"GTS 450",     CARD_NVIDIA_GEFORCE_GTS450},    /* Geforce 400 - midend low */
-            {"GT 440",      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
-            {"GT 430",      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
-            {"GT 420",      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
-            {"GT 330",      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
-            {"GTS 360M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
-            {"GTS 350M",    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
-            {"GT 330M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
-            {"GT 325M",     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
-            {"GT 320M",     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
-            {"320M",        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
-            {"GTX 295",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 285",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 280",     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
-            {"GTX 275",     CARD_NVIDIA_GEFORCE_GTX275},    /* Geforce 200 - midend high */
-            {"GTX 260",     CARD_NVIDIA_GEFORCE_GTX260},    /* Geforce 200 - midend */
-            {"GT 240",      CARD_NVIDIA_GEFORCE_GT240},     /* Geforce 200 - midend */
-            {"GT 220",      CARD_NVIDIA_GEFORCE_GT220},     /* Geforce 200 - lowend */
-            {"Geforce 310", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"Geforce 305", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"Geforce 210", CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"G 210",       CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
-            {"GTS 250",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"GTS 150",     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"9800",        CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
-            {"GT 140",      CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
-            {"9600",        CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
-            {"GT 130",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"GT 120",      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"9500",        CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
-            {"9400M",       CARD_NVIDIA_GEFORCE_9400M},     /* Geforce 9 - lowend */
-            {"9400",        CARD_NVIDIA_GEFORCE_9400GT},    /* Geforce 9 - lowend */
-            {"9300",        CARD_NVIDIA_GEFORCE_9300},      /* Geforce 9 - lowend low */
-            {"9200",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"9100",        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"G 100",       CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
-            {"8800 GTX",    CARD_NVIDIA_GEFORCE_8800GTX},   /* Geforce 8 - highend high */
-            {"8800",        CARD_NVIDIA_GEFORCE_8800GTS},   /* Geforce 8 - highend */
-            {"8600M",       CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
-            {"8600 M",      CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
-            {"8700",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
-            {"8600",        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
-            {"8500",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
-            {"8400",        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
-            {"8300",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-            {"8200",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-            {"8100",        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
+    struct shader_caps shader_caps;
+    struct fragment_caps fragment_caps;
+    const struct wined3d_shader_backend_ops *shader_backend;
+    const struct fragment_pipeline *fragment_pipeline;
 
-    /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
-     * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
-     */
-    if (d3d_level >= 9 && gl_info->supported[NV_VERTEX_PROGRAM3])
-    {
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            {"Quadro FX 5", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"Quadro FX 4", CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7950",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7900",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7800",        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
-            {"7700",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
-            {"7600",        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
-            {"7400",        CARD_NVIDIA_GEFORCE_7400},      /* Geforce 7 - lower medium */
-            {"7300",        CARD_NVIDIA_GEFORCE_7300},      /* Geforce 7 - lowend */
-            {"6800",        CARD_NVIDIA_GEFORCE_6800},      /* Geforce 6 - highend */
-            {"6700",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-            {"6610",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-            {"6600",        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
+    shader_backend = select_shader_backend(gl_info);
+    shader_backend->shader_get_caps(gl_info, &shader_caps);
 
-    if (d3d_level >= 9)
+    if (shader_caps.vs_version >= 5)
+        return WINED3D_D3D_LEVEL_11;
+    if (shader_caps.vs_version == 4)
     {
-        /* GeforceFX - highend */
-        if (strstr(gl_renderer, "5800")
-                || strstr(gl_renderer, "5900")
-                || strstr(gl_renderer, "5950")
-                || strstr(gl_renderer, "Quadro FX"))
-        {
-            return CARD_NVIDIA_GEFORCEFX_5800;
-        }
-
-        /* GeforceFX - midend */
-        if (strstr(gl_renderer, "5600")
-                || strstr(gl_renderer, "5650")
-                || strstr(gl_renderer, "5700")
-                || strstr(gl_renderer, "5750"))
-        {
-            return CARD_NVIDIA_GEFORCEFX_5600;
-        }
-
-        /* GeforceFX - lowend */
-        return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
+        /* No backed supports SM 5 at the moment */
+        if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 00))
+            return WINED3D_D3D_LEVEL_11;
+        return WINED3D_D3D_LEVEL_10;
     }
-
-    if (d3d_level >= 8)
+    if (shader_caps.vs_version == 3)
     {
-        if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
-        {
-            return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
-        }
-
-        return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
+        /* Wine can not use SM 4 on mesa drivers as the necessary functionality is not exposed
+         * on compatibility contexts */
+        if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 30))
+            return WINED3D_D3D_LEVEL_10;
+        return WINED3D_D3D_LEVEL_9_SM3;
     }
+    if (shader_caps.vs_version == 2)
+        return WINED3D_D3D_LEVEL_9_SM2;
+    if (shader_caps.vs_version == 1)
+        return WINED3D_D3D_LEVEL_8;
 
-    if (d3d_level >= 7)
-    {
-        if (strstr(gl_renderer, "GeForce4 MX"))
-        {
-            return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
-        }
-
-        if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
-        {
-            return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
-        }
-
-        if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
-        {
-            return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
-        }
-
-        return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
-    }
+    fragment_pipeline = select_fragment_implementation(gl_info, shader_backend);
+    fragment_pipeline->get_caps(gl_info, &fragment_caps);
 
-    if (strstr(gl_renderer, "TNT2"))
-    {
-        return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
-    }
+    if (fragment_caps.TextureOpCaps & WINED3DTEXOPCAPS_DOTPRODUCT3)
+        return WINED3D_D3D_LEVEL_7;
+    if (fragment_caps.MaxSimultaneousTextures > 1)
+        return WINED3D_D3D_LEVEL_6;
 
-    return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
+    return WINED3D_D3D_LEVEL_5;
 }
 
-static enum wined3d_pci_device select_card_amd_binary(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+static const struct wined3d_renderer_table
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-
-    /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
-     *
-     * Beware: renderer string do not match exact card model,
-     * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
-    if (d3d_level >= 10)
-    {
-        unsigned int i;
-
-        static const struct
-        {
-            const char *renderer;
-            enum wined3d_pci_device id;
-        }
-        cards[] =
-        {
-            /* Southern Islands */
-            {"HD 7900", CARD_AMD_RADEON_HD7900},
-            {"HD 7800", CARD_AMD_RADEON_HD7800},
-            {"HD 7700", CARD_AMD_RADEON_HD7700},
-            /* Northern Islands */
-            {"HD 6970", CARD_AMD_RADEON_HD6900},
-            {"HD 6900", CARD_AMD_RADEON_HD6900},
-            {"HD 6800", CARD_AMD_RADEON_HD6800},
-            {"HD 6770M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6750M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6700", CARD_AMD_RADEON_HD6700},
-            {"HD 6670", CARD_AMD_RADEON_HD6600},
-            {"HD 6630M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6600M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6600", CARD_AMD_RADEON_HD6600},
-            {"HD 6570", CARD_AMD_RADEON_HD6600},
-            {"HD 6500M",CARD_AMD_RADEON_HD6600M},
-            {"HD 6500", CARD_AMD_RADEON_HD6600},
-            {"HD 6400", CARD_AMD_RADEON_HD6400},
-            {"HD 6300", CARD_AMD_RADEON_HD6300},
-            {"HD 6200", CARD_AMD_RADEON_HD6300},
-            /* Evergreen */
-            {"HD 5870", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS PRO */
-            {"HD 5850", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS XT */
-            {"HD 5800", CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS HD58xx generic renderer string */
-            {"HD 5770", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER XT */
-            {"HD 5750", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER LE */
-            {"HD 5700", CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER HD57xx generic renderer string */
-            {"HD 5670", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD XT */
-            {"HD 5570", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD PRO mapped to HD5600 series */
-            {"HD 5550", CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD LE mapped to HD5600 series */
-            {"HD 5450", CARD_AMD_RADEON_HD5400},    /* Radeon EG CEDAR PRO */
-            {"HD 5000", CARD_AMD_RADEON_HD5600},    /* Defaulting to HD 5600 */
-            /* R700 */
-            {"HD 4890", CARD_AMD_RADEON_HD4800},    /* Radeon RV790 */
-            {"HD 4870", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4850", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4830", CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
-            {"HD 4800", CARD_AMD_RADEON_HD4800},    /* Radeon RV7xx HD48xx generic renderer string */
-            {"HD 4770", CARD_AMD_RADEON_HD4700},    /* Radeon RV740 */
-            {"HD 4700", CARD_AMD_RADEON_HD4700},    /* Radeon RV7xx HD47xx generic renderer string */
-            {"HD 4670", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4650", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4600", CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
-            {"HD 4550", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
-            {"HD 4350", CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
-            /* R600/R700 integrated */
-            {"HD 3300", CARD_AMD_RADEON_HD3200},
-            {"HD 3200", CARD_AMD_RADEON_HD3200},
-            {"HD 3100", CARD_AMD_RADEON_HD3200},
-            /* R600 */
-            {"HD 3870", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 3850", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 2900", CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
-            {"HD 3830", CARD_AMD_RADEON_HD2600},    /* China-only midend */
-            {"HD 3690", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 3650", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 2600", CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
-            {"HD 3470", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3450", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3430", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 3400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 2400", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-            {"HD 2350", CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
-        };
-
-        for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-        {
-            if (strstr(gl_renderer, cards[i].renderer))
-                return cards[i].id;
-        }
-        return PCI_DEVICE_NONE;
-    }
-
-    if (d3d_level >= 9)
-    {
-        /* Radeon R5xx */
-        if (strstr(gl_renderer, "X1600")
-                || strstr(gl_renderer, "X1650")
-                || strstr(gl_renderer, "X1800")
-                || strstr(gl_renderer, "X1900")
-                || strstr(gl_renderer, "X1950"))
-        {
-            return CARD_AMD_RADEON_X1600;
-        }
-
-        /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
-         * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
-        if (strstr(gl_renderer, "X700")
-                || strstr(gl_renderer, "X800")
-                || strstr(gl_renderer, "X850")
-                || strstr(gl_renderer, "X1300")
-                || strstr(gl_renderer, "X1400")
-                || strstr(gl_renderer, "X1450")
-                || strstr(gl_renderer, "X1550")
-                || strstr(gl_renderer, "X2300")
-                || strstr(gl_renderer, "X2500")
-                || strstr(gl_renderer, "HD 2300")
-                )
-        {
-            return CARD_AMD_RADEON_X700;
-        }
-
-        /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
-        if (strstr(gl_renderer, "Radeon Xpress"))
-        {
-            return CARD_AMD_RADEON_XPRESS_200M;
-        }
-    }
-    return PCI_DEVICE_NONE;
+    const char *renderer;
+    enum wined3d_pci_device id;
 }
-
-static enum wined3d_pci_device select_card_intel(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+cards_nvidia_binary[] =
 {
-    unsigned int i;
-
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Ivybridge */
-        {"Ivybridge Server",            CARD_INTEL_IVBS},
-        {"Ivybridge Mobile",            CARD_INTEL_IVBM},
-        {"Ivybridge Desktop",           CARD_INTEL_IVBD},
-        /* Sandybridge */
-        {"Sandybridge Server",          CARD_INTEL_SNBS},
-        {"Sandybridge Mobile",          CARD_INTEL_SNBM},
-        {"Sandybridge Desktop",         CARD_INTEL_SNBD},
-        /* Ironlake */
-        {"Ironlake Mobile",             CARD_INTEL_ILKM},
-        {"Ironlake Desktop",            CARD_INTEL_ILKD},
-        /* G4x */
-        {"B43",                         CARD_INTEL_B43},
-        {"G41",                         CARD_INTEL_G41},
-        {"G45",                         CARD_INTEL_G45},
-        {"Q45",                         CARD_INTEL_Q45},
-        {"Integrated Graphics Device",  CARD_INTEL_IGD},
-        {"GM45",                        CARD_INTEL_GM45},
-        /* i965 */
-        {"965GME",                      CARD_INTEL_965GME},
-        {"965GM",                       CARD_INTEL_965GM},
-        {"X3100",                       CARD_INTEL_965GM},  /* MacOS */
-        {"946GZ",                       CARD_INTEL_946GZ},
-        {"965G",                        CARD_INTEL_965G},
-        {"965Q",                        CARD_INTEL_965Q},
-        /* i945 */
-        {"Pineview M",                  CARD_INTEL_PNVM},
-        {"Pineview G",                  CARD_INTEL_PNVG},
-        {"IGD",                         CARD_INTEL_PNVG},
-        {"Q33",                         CARD_INTEL_Q33},
-        {"G33",                         CARD_INTEL_G33},
-        {"Q35",                         CARD_INTEL_Q35},
-        {"945GME",                      CARD_INTEL_945GME},
-        {"945GM",                       CARD_INTEL_945GM},
-        {"GMA 950",                     CARD_INTEL_945GM},  /* MacOS */
-        {"945G",                        CARD_INTEL_945G},
-        /* i915 */
-        {"915GM",                       CARD_INTEL_915GM},
-        {"E7221G",                      CARD_INTEL_E7221G},
-        {"915G",                        CARD_INTEL_915G},
-        /* i8xx */
-        {"865G",                        CARD_INTEL_865G},
-        {"845G",                        CARD_INTEL_845G},
-        {"855GM",                       CARD_INTEL_855GM},
-        {"830M",                        CARD_INTEL_830M},
-    };
-
-    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-    {
-        if (strstr(gl_renderer, cards[i].renderer))
-            return cards[i].id;
-    }
-
-    return PCI_DEVICE_NONE;
-}
-
-static enum wined3d_pci_device select_card_amd_mesa(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+    /* Direct 3D 11 */
+    {"GTX 780 Ti",                  CARD_NVIDIA_GEFORCE_GTX780TI},  /* Geforce 700 - highend */
+    {"GTX 780",                     CARD_NVIDIA_GEFORCE_GTX780},    /* Geforce 700 - highend */
+    {"GTX 770M",                    CARD_NVIDIA_GEFORCE_GTX770M},   /* Geforce 700 - midend high mobile */
+    {"GTX 770",                     CARD_NVIDIA_GEFORCE_GTX770},    /* Geforce 700 - highend */
+    {"GTX 765M",                    CARD_NVIDIA_GEFORCE_GTX765M},   /* Geforce 700 - midend high mobile */
+    {"GTX 760",                     CARD_NVIDIA_GEFORCE_GTX760},    /* Geforce 700 - midend high  */
+    {"GTX 750 Ti",                  CARD_NVIDIA_GEFORCE_GTX750TI},  /* Geforce 700 - midend */
+    {"GTX 750",                     CARD_NVIDIA_GEFORCE_GTX750},    /* Geforce 700 - midend */
+    {"GTX 680",                     CARD_NVIDIA_GEFORCE_GTX680},    /* Geforce 600 - highend */
+    {"GTX 670MX",                   CARD_NVIDIA_GEFORCE_GTX670MX},  /* Geforce 600 - highend */
+    {"GTX 670",                     CARD_NVIDIA_GEFORCE_GTX670},    /* Geforce 600 - midend high */
+    {"GTX 660 Ti",                  CARD_NVIDIA_GEFORCE_GTX660TI},  /* Geforce 600 - midend high */
+    {"GTX 660M",                    CARD_NVIDIA_GEFORCE_GTX660M},   /* Geforce 600 - midend high mobile */
+    {"GTX 660",                     CARD_NVIDIA_GEFORCE_GTX660},    /* Geforce 600 - midend high */
+    {"GTX 650 Ti",                  CARD_NVIDIA_GEFORCE_GTX650TI},  /* Geforce 600 - lowend */
+    {"GTX 650",                     CARD_NVIDIA_GEFORCE_GTX650},    /* Geforce 600 - lowend */
+    {"GT 650M",                     CARD_NVIDIA_GEFORCE_GT650M},    /* Geforce 600 - midend mobile */
+    {"GT 640M",                     CARD_NVIDIA_GEFORCE_GT640M},    /* Geforce 600 - midend mobile */
+    {"GT 630M",                     CARD_NVIDIA_GEFORCE_GT630M},    /* Geforce 600 - midend mobile */
+    {"GT 630",                      CARD_NVIDIA_GEFORCE_GT630},     /* Geforce 600 - lowend */
+    {"GT 610",                      CARD_NVIDIA_GEFORCE_GT610},     /* Geforce 600 - lowend */
+    {"GTX 580",                     CARD_NVIDIA_GEFORCE_GTX580},    /* Geforce 500 - highend */
+    {"GTX 570",                     CARD_NVIDIA_GEFORCE_GTX570},    /* Geforce 500 - midend high */
+    {"GTX 560 Ti",                  CARD_NVIDIA_GEFORCE_GTX560TI},  /* Geforce 500 - midend */
+    {"GTX 560",                     CARD_NVIDIA_GEFORCE_GTX560},    /* Geforce 500 - midend */
+    {"GT 555M",                     CARD_NVIDIA_GEFORCE_GT555M},    /* Geforce 500 - midend mobile */
+    {"GTX 550 Ti",                  CARD_NVIDIA_GEFORCE_GTX550},    /* Geforce 500 - midend */
+    {"GT 540M",                     CARD_NVIDIA_GEFORCE_GT540M},    /* Geforce 500 - midend mobile */
+    {"GT 520",                      CARD_NVIDIA_GEFORCE_GT520},     /* Geforce 500 - lowend */
+    {"GTX 480",                     CARD_NVIDIA_GEFORCE_GTX480},    /* Geforce 400 - highend */
+    {"GTX 470",                     CARD_NVIDIA_GEFORCE_GTX470},    /* Geforce 400 - midend high */
+    /* Direct 3D 10 */
+    {"GTX 465",                     CARD_NVIDIA_GEFORCE_GTX465},    /* Geforce 400 - midend */
+    {"GTX 460M",                    CARD_NVIDIA_GEFORCE_GTX460M},   /* Geforce 400 - highend mobile */
+    {"GTX 460",                     CARD_NVIDIA_GEFORCE_GTX460},    /* Geforce 400 - midend */
+    {"GTS 450",                     CARD_NVIDIA_GEFORCE_GTS450},    /* Geforce 400 - midend low */
+    {"GT 440",                      CARD_NVIDIA_GEFORCE_GT440},     /* Geforce 400 - lowend */
+    {"GT 430",                      CARD_NVIDIA_GEFORCE_GT430},     /* Geforce 400 - lowend */
+    {"GT 420",                      CARD_NVIDIA_GEFORCE_GT420},     /* Geforce 400 - lowend */
+    {"410M",                        CARD_NVIDIA_GEFORCE_410M},      /* Geforce 400 - lowend mobile */
+    {"GT 330",                      CARD_NVIDIA_GEFORCE_GT330},     /* Geforce 300 - highend */
+    {"GTS 360M",                    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+    {"GTS 350M",                    CARD_NVIDIA_GEFORCE_GTS350M},   /* Geforce 300 - highend mobile */
+    {"GT 330M",                     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+    {"GT 325M",                     CARD_NVIDIA_GEFORCE_GT325M},    /* Geforce 300 - midend mobile */
+    {"GT 320M",                     CARD_NVIDIA_GEFORCE_GT320M},    /* Geforce 300 - midend mobile */
+    {"320M",                        CARD_NVIDIA_GEFORCE_320M},      /* Geforce 300 - midend mobile */
+    {"315M",                        CARD_NVIDIA_GEFORCE_315M},      /* Geforce 300 - midend mobile */
+    {"GTX 295",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 285",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 280",                     CARD_NVIDIA_GEFORCE_GTX280},    /* Geforce 200 - highend */
+    {"GTX 275",                     CARD_NVIDIA_GEFORCE_GTX275},    /* Geforce 200 - midend high */
+    {"GTX 260",                     CARD_NVIDIA_GEFORCE_GTX260},    /* Geforce 200 - midend */
+    {"GT 240",                      CARD_NVIDIA_GEFORCE_GT240},     /* Geforce 200 - midend */
+    {"GT 220",                      CARD_NVIDIA_GEFORCE_GT220},     /* Geforce 200 - lowend */
+    {"GeForce 310",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GeForce 305",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GeForce 210",                 CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"G 210",                       CARD_NVIDIA_GEFORCE_210},       /* Geforce 200 - lowend */
+    {"GTS 250",                     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"GTS 150",                     CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"9800",                        CARD_NVIDIA_GEFORCE_9800GT},    /* Geforce 9 - highend / Geforce 200 - midend */
+    {"GT 140",                      CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+    {"9600",                        CARD_NVIDIA_GEFORCE_9600GT},    /* Geforce 9 - midend */
+    {"GT 130",                      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"GT 120",                      CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"9500",                        CARD_NVIDIA_GEFORCE_9500GT},    /* Geforce 9 - midend low / Geforce 200 - low */
+    {"9400M",                       CARD_NVIDIA_GEFORCE_9400M},     /* Geforce 9 - lowend */
+    {"9400",                        CARD_NVIDIA_GEFORCE_9400GT},    /* Geforce 9 - lowend */
+    {"9300",                        CARD_NVIDIA_GEFORCE_9300},      /* Geforce 9 - lowend low */
+    {"9200",                        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"9100",                        CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"G 100",                       CARD_NVIDIA_GEFORCE_9200},      /* Geforce 9 - lowend low */
+    {"8800 GTX",                    CARD_NVIDIA_GEFORCE_8800GTX},   /* Geforce 8 - highend high */
+    {"8800",                        CARD_NVIDIA_GEFORCE_8800GTS},   /* Geforce 8 - highend */
+    {"8600M",                       CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+    {"8600 M",                      CARD_NVIDIA_GEFORCE_8600MGT},   /* Geforce 8 - midend mobile */
+    {"8700",                        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+    {"8600",                        CARD_NVIDIA_GEFORCE_8600GT},    /* Geforce 8 - midend */
+    {"8500",                        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+    {"8400",                        CARD_NVIDIA_GEFORCE_8400GS},    /* Geforce 8 - mid-lowend */
+    {"8300",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    {"8200",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    {"8100",                        CARD_NVIDIA_GEFORCE_8300GS},    /* Geforce 8 - lowend */
+    /* Direct 3D 9 SM3 */
+    {"Quadro FX 5",                 CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"Quadro FX 4",                 CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7950",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7900",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7800",                        CARD_NVIDIA_GEFORCE_7800GT},    /* Geforce 7 - highend */
+    {"7700",                        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+    {"7600",                        CARD_NVIDIA_GEFORCE_7600},      /* Geforce 7 - midend */
+    {"7400",                        CARD_NVIDIA_GEFORCE_7400},      /* Geforce 7 - lower medium */
+    {"7300",                        CARD_NVIDIA_GEFORCE_7300},      /* Geforce 7 - lowend */
+    {"6800",                        CARD_NVIDIA_GEFORCE_6800},      /* Geforce 6 - highend */
+    {"6700",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    {"6610",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    {"6600",                        CARD_NVIDIA_GEFORCE_6600GT},    /* Geforce 6 - midend */
+    /* Direct 3D 9 SM2 */
+    {"Quadro FX",                   CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5950",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5900",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5800",                        CARD_NVIDIA_GEFORCEFX_5800},    /* GeforceFX - highend */
+    {"5750",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5700",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5650",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5600",                        CARD_NVIDIA_GEFORCEFX_5600},    /* GeforceFX - midend */
+    {"5500",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5300",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5250",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5200",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    {"5100",                        CARD_NVIDIA_GEFORCEFX_5200},    /* GeforceFX - lowend */
+    /* Direct 3D 8 */
+    {"Quadro4",                     CARD_NVIDIA_GEFORCE4_TI4200},
+    {"GeForce4 Ti",                 CARD_NVIDIA_GEFORCE4_TI4200},   /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800 */
+    /* Direct 3D 7 */
+    {"GeForce4 MX",                 CARD_NVIDIA_GEFORCE4_MX},       /* MX420/MX440/MX460/MX4000 */
+    {"Quadro2 MXR",                 CARD_NVIDIA_GEFORCE2_MX},
+    {"GeForce2 MX",                 CARD_NVIDIA_GEFORCE2_MX},       /* Geforce2 standard/MX100/MX200/MX400 */
+    {"Quadro2",                     CARD_NVIDIA_GEFORCE2},
+    {"GeForce2",                    CARD_NVIDIA_GEFORCE2},          /* Geforce2 GTS/Pro/Ti/Ultra */
+    /* Direct 3D 6 */
+    {"TNT2",                        CARD_NVIDIA_RIVA_TNT2},         /* Riva TNT2 standard/M64/Pro/Ultra */
+},
+/* See http://developer.amd.com/resources/hardware-drivers/ati-catalyst-pc-vendor-id-1002-li/
+ *
+ * Beware: renderer string do not match exact card model,
+ * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
+cards_amd_binary[] =
 {
-    unsigned int i;
-
-    /* 20101109 - These are never returned by current Gallium radeon
-     * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351.
-     *
-     * These are returned but not handled: RC410, RV380. */
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Southern Islands */
-        {"TAHITI",      CARD_AMD_RADEON_HD7900},
-        {"PITCAIRN",    CARD_AMD_RADEON_HD7800},
-        {"CAPE VERDE",  CARD_AMD_RADEON_HD7700},
-        /* Northern Islands */
-        {"CAYMAN",      CARD_AMD_RADEON_HD6900},
-        {"BARTS",       CARD_AMD_RADEON_HD6800},
-        {"TURKS",       CARD_AMD_RADEON_HD6600},
-        {"SUMO2",       CARD_AMD_RADEON_HD6410D},   /* SUMO2 first, because we do a strstr(). */
-        {"SUMO",        CARD_AMD_RADEON_HD6550D},
-        {"CAICOS",      CARD_AMD_RADEON_HD6400},
-        {"PALM",        CARD_AMD_RADEON_HD6300},
-        /* Evergreen */
-        {"HEMLOCK",     CARD_AMD_RADEON_HD5900},
-        {"CYPRESS",     CARD_AMD_RADEON_HD5800},
-        {"JUNIPER",     CARD_AMD_RADEON_HD5700},
-        {"REDWOOD",     CARD_AMD_RADEON_HD5600},
-        {"CEDAR",       CARD_AMD_RADEON_HD5400},
-        /* R700 */
-        {"R700",        CARD_AMD_RADEON_HD4800},
-        {"RV790",       CARD_AMD_RADEON_HD4800},
-        {"RV770",       CARD_AMD_RADEON_HD4800},
-        {"RV740",       CARD_AMD_RADEON_HD4700},
-        {"RV730",       CARD_AMD_RADEON_HD4600},
-        {"RV710",       CARD_AMD_RADEON_HD4350},
-        /* R600/R700 integrated */
-        {"RS880",       CARD_AMD_RADEON_HD3200},
-        {"RS780",       CARD_AMD_RADEON_HD3200},
-        /* R600 */
-        {"R680",        CARD_AMD_RADEON_HD2900},
-        {"R600",        CARD_AMD_RADEON_HD2900},
-        {"RV670",       CARD_AMD_RADEON_HD2900},
-        {"RV635",       CARD_AMD_RADEON_HD2600},
-        {"RV630",       CARD_AMD_RADEON_HD2600},
-        {"RV620",       CARD_AMD_RADEON_HD2350},
-        {"RV610",       CARD_AMD_RADEON_HD2350},
-        /* R500 */
-        {"R580",        CARD_AMD_RADEON_X1600},
-        {"R520",        CARD_AMD_RADEON_X1600},
-        {"RV570",       CARD_AMD_RADEON_X1600},
-        {"RV560",       CARD_AMD_RADEON_X1600},
-        {"RV535",       CARD_AMD_RADEON_X1600},
-        {"RV530",       CARD_AMD_RADEON_X1600},
-        {"RV516",       CARD_AMD_RADEON_X700},
-        {"RV515",       CARD_AMD_RADEON_X700},
-        /* R400 */
-        {"R481",        CARD_AMD_RADEON_X700},
-        {"R480",        CARD_AMD_RADEON_X700},
-        {"R430",        CARD_AMD_RADEON_X700},
-        {"R423",        CARD_AMD_RADEON_X700},
-        {"R420",        CARD_AMD_RADEON_X700},
-        {"R410",        CARD_AMD_RADEON_X700},
-        {"RV410",       CARD_AMD_RADEON_X700},
-        /* Radeon Xpress - onboard, DX9b, Shader 2.0, 300-400MHz */
-        {"RS740",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS690",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS600",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS485",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS482",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS480",       CARD_AMD_RADEON_XPRESS_200M},
-        {"RS400",       CARD_AMD_RADEON_XPRESS_200M},
-        /* R300 */
-        {"R360",        CARD_AMD_RADEON_9500},
-        {"R350",        CARD_AMD_RADEON_9500},
-        {"R300",        CARD_AMD_RADEON_9500},
-        {"RV370",       CARD_AMD_RADEON_9500},
-        {"RV360",       CARD_AMD_RADEON_9500},
-        {"RV351",       CARD_AMD_RADEON_9500},
-        {"RV350",       CARD_AMD_RADEON_9500},
-    };
-
-    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-    {
-        if (strstr(gl_renderer, cards[i].renderer))
-            return cards[i].id;
-    }
-
-    return PCI_DEVICE_NONE;
-}
-
-static enum wined3d_pci_device select_card_nvidia_mesa(const struct wined3d_gl_info *gl_info,
-        const char *gl_renderer)
+    /* Southern Islands */
+    {"HD 7900",                     CARD_AMD_RADEON_HD7900},
+    {"HD 7800",                     CARD_AMD_RADEON_HD7800},
+    {"HD 7700",                     CARD_AMD_RADEON_HD7700},
+    /* Northern Islands */
+    {"HD 6970",                     CARD_AMD_RADEON_HD6900},
+    {"HD 6900",                     CARD_AMD_RADEON_HD6900},
+    {"HD 6800",                     CARD_AMD_RADEON_HD6800},
+    {"HD 6770M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6750M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6700",                     CARD_AMD_RADEON_HD6700},
+    {"HD 6670",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6630M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6600M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6600",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6570",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6500M",                    CARD_AMD_RADEON_HD6600M},
+    {"HD 6500",                     CARD_AMD_RADEON_HD6600},
+    {"HD 6400",                     CARD_AMD_RADEON_HD6400},
+    {"HD 6300",                     CARD_AMD_RADEON_HD6300},
+    {"HD 6200",                     CARD_AMD_RADEON_HD6300},
+    /* Evergreen */
+    {"HD 5870",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS PRO */
+    {"HD 5850",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS XT */
+    {"HD 5800",                     CARD_AMD_RADEON_HD5800},    /* Radeon EG CYPRESS HD58xx generic renderer string */
+    {"HD 5770",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER XT */
+    {"HD 5750",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER LE */
+    {"HD 5700",                     CARD_AMD_RADEON_HD5700},    /* Radeon EG JUNIPER HD57xx generic renderer string */
+    {"HD 5670",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD XT */
+    {"HD 5570",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD PRO mapped to HD5600 series */
+    {"HD 5550",                     CARD_AMD_RADEON_HD5600},    /* Radeon EG REDWOOD LE mapped to HD5600 series */
+    {"HD 5450",                     CARD_AMD_RADEON_HD5400},    /* Radeon EG CEDAR PRO */
+    {"HD 5000",                     CARD_AMD_RADEON_HD5600},    /* Defaulting to HD 5600 */
+    /* R700 */
+    {"HD 4890",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV790 */
+    {"HD 4870",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4850",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4830",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV770 */
+    {"HD 4800",                     CARD_AMD_RADEON_HD4800},    /* Radeon RV7xx HD48xx generic renderer string */
+    {"HD 4770",                     CARD_AMD_RADEON_HD4700},    /* Radeon RV740 */
+    {"HD 4700",                     CARD_AMD_RADEON_HD4700},    /* Radeon RV7xx HD47xx generic renderer string */
+    {"HD 4670",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4650",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4600",                     CARD_AMD_RADEON_HD4600},    /* Radeon RV730 */
+    {"HD 4550",                     CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+    {"HD 4350",                     CARD_AMD_RADEON_HD4350},    /* Radeon RV710 */
+    /* R600/R700 integrated */
+    {"HD 4200M",                    CARD_AMD_RADEON_HD4200M},
+    {"HD 3300",                     CARD_AMD_RADEON_HD3200},
+    {"HD 3200",                     CARD_AMD_RADEON_HD3200},
+    {"HD 3100",                     CARD_AMD_RADEON_HD3200},
+    /* R600 */
+    {"HD 3870",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 3850",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 2900",                     CARD_AMD_RADEON_HD2900},    /* HD2900/HD3800 - highend */
+    {"HD 3830",                     CARD_AMD_RADEON_HD2600},    /* China-only midend */
+    {"HD 3690",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 3650",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 2600",                     CARD_AMD_RADEON_HD2600},    /* HD2600/HD3600 - midend */
+    {"HD 3470",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3450",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3430",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 3400",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 2400",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    {"HD 2350",                     CARD_AMD_RADEON_HD2350},    /* HD2350/HD2400/HD3400 - lowend */
+    /* Radeon R5xx */
+    {"X1950",                       CARD_AMD_RADEON_X1600},
+    {"X1900",                       CARD_AMD_RADEON_X1600},
+    {"X1800",                       CARD_AMD_RADEON_X1600},
+    {"X1650",                       CARD_AMD_RADEON_X1600},
+    {"X1600",                       CARD_AMD_RADEON_X1600},
+    /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300/X2500/HD2300 (lowend R5xx)
+     * Note X2300/X2500/HD2300 are R5xx GPUs with a 2xxx naming but they are still DX9-only */
+    {"HD 2300",                     CARD_AMD_RADEON_X700},
+    {"X2500",                       CARD_AMD_RADEON_X700},
+    {"X2300",                       CARD_AMD_RADEON_X700},
+    {"X1550",                       CARD_AMD_RADEON_X700},
+    {"X1450",                       CARD_AMD_RADEON_X700},
+    {"X1400",                       CARD_AMD_RADEON_X700},
+    {"X1300",                       CARD_AMD_RADEON_X700},
+    {"X850",                        CARD_AMD_RADEON_X700},
+    {"X800",                        CARD_AMD_RADEON_X700},
+    {"X700",                        CARD_AMD_RADEON_X700},
+    /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400 MHz */
+    {"Radeon Xpress",               CARD_AMD_RADEON_XPRESS_200M},
+},
+cards_intel[] =
 {
-    unsigned int i;
-
-    static const struct
-    {
-        const char *renderer;
-        enum wined3d_pci_device id;
-    }
-    cards[] =
-    {
-        /* Kepler */
-        {"NVE4",    CARD_NVIDIA_GEFORCE_GTX680},
-        /* Fermi */
-        {"NVD9",    CARD_NVIDIA_GEFORCE_GT520},
-        {"NVCF",    CARD_NVIDIA_GEFORCE_GTX550},
-        {"NVCE",    CARD_NVIDIA_GEFORCE_GTX560},
-        {"NVC8",    CARD_NVIDIA_GEFORCE_GTX570},
-        {"NVC4",    CARD_NVIDIA_GEFORCE_GTX460},
-        {"NVC3",    CARD_NVIDIA_GEFORCE_GT440},
-        {"NVC1",    CARD_NVIDIA_GEFORCE_GT420},
-        {"NVC0",    CARD_NVIDIA_GEFORCE_GTX480},
-        /* Tesla */
-        {"NVAF",    CARD_NVIDIA_GEFORCE_GT320M},
-        {"NVAC",    CARD_NVIDIA_GEFORCE_8200},
-        {"NVAA",    CARD_NVIDIA_GEFORCE_8200},
-        {"NVA8",    CARD_NVIDIA_GEFORCE_210},
-        {"NVA5",    CARD_NVIDIA_GEFORCE_GT220},
-        {"NVA3",    CARD_NVIDIA_GEFORCE_GT240},
-        {"NVA0",    CARD_NVIDIA_GEFORCE_GTX280},
-        {"NV98",    CARD_NVIDIA_GEFORCE_9200},
-        {"NV96",    CARD_NVIDIA_GEFORCE_9400GT},
-        {"NV94",    CARD_NVIDIA_GEFORCE_9600GT},
-        {"NV92",    CARD_NVIDIA_GEFORCE_9800GT},
-        {"NV86",    CARD_NVIDIA_GEFORCE_8500GT},
-        {"NV84",    CARD_NVIDIA_GEFORCE_8600GT},
-        {"NV50",    CARD_NVIDIA_GEFORCE_8800GTX},
-        /* Curie */
-        {"NV68",    CARD_NVIDIA_GEFORCE_6200},      /* 7050 */
-        {"NV67",    CARD_NVIDIA_GEFORCE_6200},      /* 7000M */
-        {"NV63",    CARD_NVIDIA_GEFORCE_6200},      /* 7100 */
-        {"NV4E",    CARD_NVIDIA_GEFORCE_6200},      /* 6100 Go / 6150 Go */
-        {"NV4C",    CARD_NVIDIA_GEFORCE_6200},      /* 6150SE */
-        {"NV4B",    CARD_NVIDIA_GEFORCE_7600},
-        {"NV4A",    CARD_NVIDIA_GEFORCE_6200},
-        {"NV49",    CARD_NVIDIA_GEFORCE_7800GT},    /* 7900 */
-        {"NV47",    CARD_NVIDIA_GEFORCE_7800GT},
-        {"NV46",    CARD_NVIDIA_GEFORCE_7400},
-        {"NV45",    CARD_NVIDIA_GEFORCE_6800},
-        {"NV44",    CARD_NVIDIA_GEFORCE_6200},
-        {"NV43",    CARD_NVIDIA_GEFORCE_6600GT},
-        {"NV42",    CARD_NVIDIA_GEFORCE_6800},
-        {"NV41",    CARD_NVIDIA_GEFORCE_6800},
-        {"NV40",    CARD_NVIDIA_GEFORCE_6800},
-        /* Rankine */
-        {"NV38",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5950 Ultra */
-        {"NV36",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5700/5750 */
-        {"NV35",    CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5900 */
-        {"NV34",    CARD_NVIDIA_GEFORCEFX_5200},
-        {"NV31",    CARD_NVIDIA_GEFORCEFX_5600},
-        {"NV30",    CARD_NVIDIA_GEFORCEFX_5800},
-        /* Kelvin */
-        {"nv28",    CARD_NVIDIA_GEFORCE4_TI4200},
-        {"nv25",    CARD_NVIDIA_GEFORCE4_TI4200},
-        {"nv20",    CARD_NVIDIA_GEFORCE3},
-        /* Celsius */
-        {"nv1F",    CARD_NVIDIA_GEFORCE4_MX},       /* GF4 MX IGP */
-        {"nv1A",    CARD_NVIDIA_GEFORCE2},          /* GF2 IGP */
-        {"nv18",    CARD_NVIDIA_GEFORCE4_MX},
-        {"nv17",    CARD_NVIDIA_GEFORCE4_MX},
-        {"nv16",    CARD_NVIDIA_GEFORCE2},
-        {"nv15",    CARD_NVIDIA_GEFORCE2},
-        {"nv11",    CARD_NVIDIA_GEFORCE2_MX},
-        {"nv10",    CARD_NVIDIA_GEFORCE},
-        /* Fahrenheit */
-        {"nv05",    CARD_NVIDIA_RIVA_TNT2},
-        {"nv04",    CARD_NVIDIA_RIVA_TNT},
-        {"nv03",    CARD_NVIDIA_RIVA_128},
-    };
-
-    for (i = 0; i < sizeof(cards) / sizeof(*cards); ++i)
-    {
-        if (strstr(gl_renderer, cards[i].renderer))
-            return cards[i].id;
-    }
-    return PCI_DEVICE_NONE;
-}
+    /* Haswell */
+    {"Haswell Mobile",              CARD_INTEL_HWM},
+    /* Ivybridge */
+    {"Ivybridge Server",            CARD_INTEL_IVBS},
+    {"Ivybridge Mobile",            CARD_INTEL_IVBM},
+    {"Ivybridge Desktop",           CARD_INTEL_IVBD},
+    /* Sandybridge */
+    {"Sandybridge Server",          CARD_INTEL_SNBS},
+    {"Sandybridge Mobile",          CARD_INTEL_SNBM},
+    {"Sandybridge Desktop",         CARD_INTEL_SNBD},
+    /* Ironlake */
+    {"Ironlake Mobile",             CARD_INTEL_ILKM},
+    {"Ironlake Desktop",            CARD_INTEL_ILKD},
+    /* G4x */
+    {"B43",                         CARD_INTEL_B43},
+    {"G41",                         CARD_INTEL_G41},
+    {"G45",                         CARD_INTEL_G45},
+    {"Q45",                         CARD_INTEL_Q45},
+    {"Integrated Graphics Device",  CARD_INTEL_IGD},
+    {"GM45",                        CARD_INTEL_GM45},
+    /* i965 */
+    {"965GME",                      CARD_INTEL_965GME},
+    {"965GM",                       CARD_INTEL_965GM},
+    {"X3100",                       CARD_INTEL_965GM},  /* MacOS */
+    {"946GZ",                       CARD_INTEL_946GZ},
+    {"965G",                        CARD_INTEL_965G},
+    {"965Q",                        CARD_INTEL_965Q},
+    /* i945 */
+    {"Pineview M",                  CARD_INTEL_PNVM},
+    {"Pineview G",                  CARD_INTEL_PNVG},
+    {"IGD",                         CARD_INTEL_PNVG},
+    {"Q33",                         CARD_INTEL_Q33},
+    {"G33",                         CARD_INTEL_G33},
+    {"Q35",                         CARD_INTEL_Q35},
+    {"945GME",                      CARD_INTEL_945GME},
+    {"945GM",                       CARD_INTEL_945GM},
+    {"GMA 950",                     CARD_INTEL_945GM},  /* MacOS */
+    {"945G",                        CARD_INTEL_945G},
+    /* i915 */
+    {"915GM",                       CARD_INTEL_915GM},
+    {"E7221G",                      CARD_INTEL_E7221G},
+    {"915G",                        CARD_INTEL_915G},
+    /* i8xx */
+    {"865G",                        CARD_INTEL_865G},
+    {"845G",                        CARD_INTEL_845G},
+    {"855GM",                       CARD_INTEL_855GM},
+    {"830M",                        CARD_INTEL_830M},
+},
+/* 20101109 - These are never returned by current Gallium radeon
+ * drivers: R700, RV790, R680, RV535, RV516, R410, RS485, RV360, RV351.
+ *
+ * These are returned but not handled: RC410, RV380. */
+cards_amd_mesa[] =
+{
+    /* Sea Islands */
+    {"HAWAII",                      CARD_AMD_RADEON_R9    },
+    {"KAVERI",                      CARD_AMD_RADEON_R7    },
+    {"KABINI",                      CARD_AMD_RADEON_R3    },
+    {"BONAIRE",                     CARD_AMD_RADEON_HD8770},
+    /* Southern Islands */
+    {"OLAND",                       CARD_AMD_RADEON_HD8670},
+    {"HAINAN",                      CARD_AMD_RADEON_HD8600M},
+    {"TAHITI",                      CARD_AMD_RADEON_HD7900},
+    {"PITCAIRN",                    CARD_AMD_RADEON_HD7800},
+    {"CAPE VERDE",                  CARD_AMD_RADEON_HD7700},
+    /* Northern Islands */
+    {"ARUBA",                       CARD_AMD_RADEON_HD7660D},
+    {"CAYMAN",                      CARD_AMD_RADEON_HD6900},
+    {"BARTS",                       CARD_AMD_RADEON_HD6800},
+    {"TURKS",                       CARD_AMD_RADEON_HD6600},
+    {"SUMO2",                       CARD_AMD_RADEON_HD6410D},   /* SUMO2 first, because we do a strstr(). */
+    {"SUMO",                        CARD_AMD_RADEON_HD6550D},
+    {"CAICOS",                      CARD_AMD_RADEON_HD6400},
+    {"PALM",                        CARD_AMD_RADEON_HD6300},
+    /* Evergreen */
+    {"HEMLOCK",                     CARD_AMD_RADEON_HD5900},
+    {"CYPRESS",                     CARD_AMD_RADEON_HD5800},
+    {"JUNIPER",                     CARD_AMD_RADEON_HD5700},
+    {"REDWOOD",                     CARD_AMD_RADEON_HD5600},
+    {"CEDAR",                       CARD_AMD_RADEON_HD5400},
+    /* R700 */
+    {"R700",                        CARD_AMD_RADEON_HD4800},
+    {"RV790",                       CARD_AMD_RADEON_HD4800},
+    {"RV770",                       CARD_AMD_RADEON_HD4800},
+    {"RV740",                       CARD_AMD_RADEON_HD4700},
+    {"RV730",                       CARD_AMD_RADEON_HD4600},
+    {"RV710",                       CARD_AMD_RADEON_HD4350},
+    /* R600/R700 integrated */
+    {"RS880",                       CARD_AMD_RADEON_HD4200M},
+    {"RS780",                       CARD_AMD_RADEON_HD3200},
+    /* R600 */
+    {"R680",                        CARD_AMD_RADEON_HD2900},
+    {"R600",                        CARD_AMD_RADEON_HD2900},
+    {"RV670",                       CARD_AMD_RADEON_HD2900},
+    {"RV635",                       CARD_AMD_RADEON_HD2600},
+    {"RV630",                       CARD_AMD_RADEON_HD2600},
+    {"RV620",                       CARD_AMD_RADEON_HD2350},
+    {"RV610",                       CARD_AMD_RADEON_HD2350},
+    /* R500 */
+    {"R580",                        CARD_AMD_RADEON_X1600},
+    {"R520",                        CARD_AMD_RADEON_X1600},
+    {"RV570",                       CARD_AMD_RADEON_X1600},
+    {"RV560",                       CARD_AMD_RADEON_X1600},
+    {"RV535",                       CARD_AMD_RADEON_X1600},
+    {"RV530",                       CARD_AMD_RADEON_X1600},
+    {"RV516",                       CARD_AMD_RADEON_X700},
+    {"RV515",                       CARD_AMD_RADEON_X700},
+    /* R400 */
+    {"R481",                        CARD_AMD_RADEON_X700},
+    {"R480",                        CARD_AMD_RADEON_X700},
+    {"R430",                        CARD_AMD_RADEON_X700},
+    {"R423",                        CARD_AMD_RADEON_X700},
+    {"R420",                        CARD_AMD_RADEON_X700},
+    {"R410",                        CARD_AMD_RADEON_X700},
+    {"RV410",                       CARD_AMD_RADEON_X700},
+    /* Radeon Xpress - onboard, DX9b, Shader 2.0, 300-400 MHz */
+    {"RS740",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS690",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS600",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS485",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS482",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS480",                       CARD_AMD_RADEON_XPRESS_200M},
+    {"RS400",                       CARD_AMD_RADEON_XPRESS_200M},
+    /* R300 */
+    {"R360",                        CARD_AMD_RADEON_9500},
+    {"R350",                        CARD_AMD_RADEON_9500},
+    {"R300",                        CARD_AMD_RADEON_9500},
+    {"RV370",                       CARD_AMD_RADEON_9500},
+    {"RV360",                       CARD_AMD_RADEON_9500},
+    {"RV351",                       CARD_AMD_RADEON_9500},
+    {"RV350",                       CARD_AMD_RADEON_9500},
+},
+cards_nvidia_mesa[] =
+{
+    /* Maxwell */
+    {"NV117",                       CARD_NVIDIA_GEFORCE_GTX750},
+    /* Kepler */
+    {"NVF1",                        CARD_NVIDIA_GEFORCE_GTX780TI},
+    {"NVF0",                        CARD_NVIDIA_GEFORCE_GTX780},
+    {"NVE6",                        CARD_NVIDIA_GEFORCE_GTX770M},
+    {"NVE4",                        CARD_NVIDIA_GEFORCE_GTX680},
+    /* Fermi */
+    {"NVD9",                        CARD_NVIDIA_GEFORCE_GT520},
+    {"NVCF",                        CARD_NVIDIA_GEFORCE_GTX550},
+    {"NVCE",                        CARD_NVIDIA_GEFORCE_GTX560},
+    {"NVC8",                        CARD_NVIDIA_GEFORCE_GTX570},
+    {"NVC4",                        CARD_NVIDIA_GEFORCE_GTX460},
+    {"NVC3",                        CARD_NVIDIA_GEFORCE_GT440},
+    {"NVC1",                        CARD_NVIDIA_GEFORCE_GT420},
+    {"NVC0",                        CARD_NVIDIA_GEFORCE_GTX480},
+    /* Tesla */
+    {"NVAF",                        CARD_NVIDIA_GEFORCE_GT320M},
+    {"NVAC",                        CARD_NVIDIA_GEFORCE_8200},
+    {"NVAA",                        CARD_NVIDIA_GEFORCE_8200},
+    {"NVA8",                        CARD_NVIDIA_GEFORCE_210},
+    {"NVA5",                        CARD_NVIDIA_GEFORCE_GT220},
+    {"NVA3",                        CARD_NVIDIA_GEFORCE_GT240},
+    {"NVA0",                        CARD_NVIDIA_GEFORCE_GTX280},
+    {"NV98",                        CARD_NVIDIA_GEFORCE_9200},
+    {"NV96",                        CARD_NVIDIA_GEFORCE_9400GT},
+    {"NV94",                        CARD_NVIDIA_GEFORCE_9600GT},
+    {"NV92",                        CARD_NVIDIA_GEFORCE_9800GT},
+    {"NV86",                        CARD_NVIDIA_GEFORCE_8500GT},
+    {"NV84",                        CARD_NVIDIA_GEFORCE_8600GT},
+    {"NV50",                        CARD_NVIDIA_GEFORCE_8800GTX},
+    /* Curie */
+    {"NV68",                        CARD_NVIDIA_GEFORCE_6200},      /* 7050 */
+    {"NV67",                        CARD_NVIDIA_GEFORCE_6200},      /* 7000M */
+    {"NV63",                        CARD_NVIDIA_GEFORCE_6200},      /* 7100 */
+    {"NV4E",                        CARD_NVIDIA_GEFORCE_6200},      /* 6100 Go / 6150 Go */
+    {"NV4C",                        CARD_NVIDIA_GEFORCE_6200},      /* 6150SE */
+    {"NV4B",                        CARD_NVIDIA_GEFORCE_7600},
+    {"NV4A",                        CARD_NVIDIA_GEFORCE_6200},
+    {"NV49",                        CARD_NVIDIA_GEFORCE_7800GT},    /* 7900 */
+    {"NV47",                        CARD_NVIDIA_GEFORCE_7800GT},
+    {"NV46",                        CARD_NVIDIA_GEFORCE_7400},
+    {"NV45",                        CARD_NVIDIA_GEFORCE_6800},
+    {"NV44",                        CARD_NVIDIA_GEFORCE_6200},
+    {"NV43",                        CARD_NVIDIA_GEFORCE_6600GT},
+    {"NV42",                        CARD_NVIDIA_GEFORCE_6800},
+    {"NV41",                        CARD_NVIDIA_GEFORCE_6800},
+    {"NV40",                        CARD_NVIDIA_GEFORCE_6800},
+    /* Rankine */
+    {"NV38",                        CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5950 Ultra */
+    {"NV36",                        CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5700/5750 */
+    {"NV35",                        CARD_NVIDIA_GEFORCEFX_5800},    /* FX 5900 */
+    {"NV34",                        CARD_NVIDIA_GEFORCEFX_5200},
+    {"NV31",                        CARD_NVIDIA_GEFORCEFX_5600},
+    {"NV30",                        CARD_NVIDIA_GEFORCEFX_5800},
+    /* Kelvin */
+    {"nv28",                        CARD_NVIDIA_GEFORCE4_TI4200},
+    {"nv25",                        CARD_NVIDIA_GEFORCE4_TI4200},
+    {"nv20",                        CARD_NVIDIA_GEFORCE3},
+    /* Celsius */
+    {"nv1F",                        CARD_NVIDIA_GEFORCE4_MX},       /* GF4 MX IGP */
+    {"nv1A",                        CARD_NVIDIA_GEFORCE2},          /* GF2 IGP */
+    {"nv18",                        CARD_NVIDIA_GEFORCE4_MX},
+    {"nv17",                        CARD_NVIDIA_GEFORCE4_MX},
+    {"nv16",                        CARD_NVIDIA_GEFORCE2},
+    {"nv15",                        CARD_NVIDIA_GEFORCE2},
+    {"nv11",                        CARD_NVIDIA_GEFORCE2_MX},
+    {"nv10",                        CARD_NVIDIA_GEFORCE},
+    /* Fahrenheit */
+    {"nv05",                        CARD_NVIDIA_RIVA_TNT2},
+    {"nv04",                        CARD_NVIDIA_RIVA_TNT},
+    {"nv03",                        CARD_NVIDIA_RIVA_128},
+},
+cards_vmware[] =
+{
+    {"SVGA3D",                      CARD_VMWARE_SVGA3D},
+};
 
 static const struct gl_vendor_selection
 {
     enum wined3d_gl_vendor gl_vendor;
     const char *description;        /* Description of the card selector i.e. Apple OS/X Intel */
-    enum wined3d_pci_device (*select_card)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
+    const struct wined3d_renderer_table *cards; /* To be used as cards[], pointer to the first member in an array */
+    size_t cards_size;              /* Number of entries in the array above */
 }
+amd_gl_vendor_table[] =
+{
+    {GL_VENDOR_APPLE,   "Apple OSX AMD/ATI binary driver",  cards_amd_binary,       ARRAY_SIZE(cards_amd_binary)},
+    {GL_VENDOR_FGLRX,   "AMD/ATI binary driver",            cards_amd_binary,       ARRAY_SIZE(cards_amd_binary)},
+    {GL_VENDOR_MESA,    "Mesa AMD/ATI driver",              cards_amd_mesa,         ARRAY_SIZE(cards_amd_mesa)},
+},
 nvidia_gl_vendor_table[] =
 {
-    {GL_VENDOR_NVIDIA, "Nvidia binary driver", select_card_nvidia_binary},
-    {GL_VENDOR_APPLE, "Apple OSX NVidia binary driver", select_card_nvidia_binary},
-    {GL_VENDOR_MESA, "Mesa Nouveau driver", select_card_nvidia_mesa},
+    {GL_VENDOR_APPLE,   "Apple OSX NVidia binary driver",   cards_nvidia_binary,    ARRAY_SIZE(cards_nvidia_binary)},
+    {GL_VENDOR_MESA,    "Mesa Nouveau driver",              cards_nvidia_mesa,      ARRAY_SIZE(cards_nvidia_mesa)},
+    {GL_VENDOR_NVIDIA,  "Nvidia binary driver",             cards_nvidia_binary,    ARRAY_SIZE(cards_nvidia_binary)},
 },
-amd_gl_vendor_table[] =
+vmware_gl_vendor_table[] =
 {
-    {GL_VENDOR_APPLE, "Apple OSX AMD/ATI binary driver", select_card_amd_binary},
-    {GL_VENDOR_FGLRX, "AMD/ATI binary driver", select_card_amd_binary},
-    {GL_VENDOR_MESA, "Mesa AMD/ATI driver", select_card_amd_mesa},
+    {GL_VENDOR_MESA,    "VMware driver",                    cards_vmware,           ARRAY_SIZE(cards_vmware)},
 },
 intel_gl_vendor_table[] =
 {
-    {GL_VENDOR_APPLE, "Apple OSX Intel binary driver", select_card_intel},
-    {GL_VENDOR_INTEL, "Mesa Intel driver", select_card_intel},
-    {GL_VENDOR_MESA, "Mesa Intel driver", select_card_intel},
+    {GL_VENDOR_APPLE,   "Apple OSX Intel binary driver",    cards_intel,            ARRAY_SIZE(cards_intel)},
+    {GL_VENDOR_MESA,    "Mesa Intel driver",                cards_intel,            ARRAY_SIZE(cards_intel)},
 };
 
-static enum wined3d_pci_device select_card_fallback_nvidia(const struct wined3d_gl_info *gl_info)
+static const enum wined3d_pci_device
+card_fallback_nvidia[] =
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-    if (d3d_level >= 10)
-        return CARD_NVIDIA_GEFORCE_8800GTX;
-    if (d3d_level >= 9 && gl_info->supported[NV_VERTEX_PROGRAM3])
-        return CARD_NVIDIA_GEFORCE_6800;
-    if (d3d_level >= 9)
-        return CARD_NVIDIA_GEFORCEFX_5800;
-    if (d3d_level >= 8)
-        return CARD_NVIDIA_GEFORCE3;
-    if (d3d_level >= 7)
-        return CARD_NVIDIA_GEFORCE;
-    if (d3d_level >= 6)
-        return CARD_NVIDIA_RIVA_TNT;
-    return CARD_NVIDIA_RIVA_128;
-}
-
-static enum wined3d_pci_device select_card_fallback_amd(const struct wined3d_gl_info *gl_info)
+    CARD_NVIDIA_RIVA_128,           /* D3D5 */
+    CARD_NVIDIA_RIVA_TNT,           /* D3D6 */
+    CARD_NVIDIA_GEFORCE,            /* D3D7 */
+    CARD_NVIDIA_GEFORCE3,           /* D3D8 */
+    CARD_NVIDIA_GEFORCEFX_5800,     /* D3D9_SM2 */
+    CARD_NVIDIA_GEFORCE_6800,       /* D3D9_SM3 */
+    CARD_NVIDIA_GEFORCE_8800GTX,    /* D3D10 */
+    CARD_NVIDIA_GEFORCE_GTX470,     /* D3D11 */
+},
+card_fallback_amd[] =
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-    if (d3d_level >= 10)
-        return CARD_AMD_RADEON_HD2900;
-    if (d3d_level >= 9)
-        return CARD_AMD_RADEON_9500;
-    if (d3d_level >= 8)
-        return CARD_AMD_RADEON_8500;
-    if (d3d_level >= 7)
-        return CARD_AMD_RADEON_7200;
-    return CARD_AMD_RAGE_128PRO;
-}
-
-static enum wined3d_pci_device select_card_fallback_intel(const struct wined3d_gl_info *gl_info)
+    CARD_AMD_RAGE_128PRO,           /* D3D5 */
+    CARD_AMD_RAGE_128PRO,           /* D3D6 */
+    CARD_AMD_RADEON_7200,           /* D3D7 */
+    CARD_AMD_RADEON_8500,           /* D3D8 */
+    CARD_AMD_RADEON_9500,           /* D3D9_SM2 */
+    CARD_AMD_RADEON_X1600,          /* D3D9_SM3 */
+    CARD_AMD_RADEON_HD2900,         /* D3D10 */
+    CARD_AMD_RADEON_HD5600,         /* D3D11 */
+},
+card_fallback_intel[] =
 {
-    UINT d3d_level = d3d_level_from_gl_info(gl_info);
-    if (d3d_level >= 10)
-        return CARD_INTEL_G45;
-    return CARD_INTEL_915G;
-}
+    CARD_INTEL_915G,                /* D3D5 */
+    CARD_INTEL_915G,                /* D3D6 */
+    CARD_INTEL_915G,                /* D3D7 */
+    CARD_INTEL_915G,                /* D3D8 */
+    CARD_INTEL_915G,                /* D3D9_SM2 */
+    CARD_INTEL_915G,                /* D3D9_SM3 */
+    CARD_INTEL_G45,                 /* D3D10 */
+    CARD_INTEL_IVBD,                /* D3D11 */
+};
+C_ASSERT(ARRAY_SIZE(card_fallback_nvidia)  == WINED3D_D3D_LEVEL_COUNT);
+C_ASSERT(ARRAY_SIZE(card_fallback_amd)     == WINED3D_D3D_LEVEL_COUNT);
+C_ASSERT(ARRAY_SIZE(card_fallback_intel)   == WINED3D_D3D_LEVEL_COUNT);
 
 static enum wined3d_pci_device select_card_handler(const struct gl_vendor_selection *table,
-        unsigned int table_size, enum wined3d_gl_vendor gl_vendor,
-        const struct wined3d_gl_info *gl_info, const char *gl_renderer)
+        unsigned int table_size, enum wined3d_gl_vendor gl_vendor, const char *gl_renderer)
 {
-    unsigned int i;
+    unsigned int i, j;
 
     for (i = 0; i < table_size; ++i)
     {
@@ -2164,7 +2239,13 @@ static enum wined3d_pci_device select_card_handler(const struct gl_vendor_select
             continue;
 
         TRACE("Applying card selector \"%s\".\n", table[i].description);
-        return table[i].select_card(gl_info, gl_renderer);
+
+        for (j = 0; j < table[i].cards_size; ++j)
+        {
+            if (strstr(gl_renderer, table[i].cards[j].renderer))
+                return table[i].cards[j].id;
+        }
+        return PCI_DEVICE_NONE;
     }
     FIXME("Couldn't find a suitable card selector for GL vendor %04x (using GL_RENDERER %s)\n",
             gl_vendor, debugstr_a(gl_renderer));
@@ -2178,19 +2259,22 @@ static const struct
     const char *description;        /* Description of the card selector i.e. Apple OS/X Intel */
     const struct gl_vendor_selection *gl_vendor_selection;
     unsigned int gl_vendor_count;
-    enum wined3d_pci_device (*select_card_fallback)(const struct wined3d_gl_info *gl_info);
+    const enum wined3d_pci_device *card_fallback; /* An array with D3D_LEVEL_COUNT elements */
 }
 card_vendor_table[] =
 {
-    {HW_VENDOR_NVIDIA,  "Nvidia",  nvidia_gl_vendor_table,
-            sizeof(nvidia_gl_vendor_table) / sizeof(nvidia_gl_vendor_table[0]),
-            select_card_fallback_nvidia},
-    {HW_VENDOR_AMD,     "AMD",     amd_gl_vendor_table,
-            sizeof(amd_gl_vendor_table) / sizeof(amd_gl_vendor_table[0]),
-            select_card_fallback_amd},
-    {HW_VENDOR_INTEL,   "Intel",   intel_gl_vendor_table,
-            sizeof(intel_gl_vendor_table) / sizeof(intel_gl_vendor_table[0]),
-            select_card_fallback_intel},
+    {HW_VENDOR_AMD,         "AMD",      amd_gl_vendor_table,
+            sizeof(amd_gl_vendor_table) / sizeof(*amd_gl_vendor_table),
+            card_fallback_amd},
+    {HW_VENDOR_NVIDIA,      "Nvidia",   nvidia_gl_vendor_table,
+            sizeof(nvidia_gl_vendor_table) / sizeof(*nvidia_gl_vendor_table),
+            card_fallback_nvidia},
+    {HW_VENDOR_VMWARE,      "VMware",   vmware_gl_vendor_table,
+            sizeof(vmware_gl_vendor_table) / sizeof(*vmware_gl_vendor_table),
+            card_fallback_amd},
+    {HW_VENDOR_INTEL,       "Intel",    intel_gl_vendor_table,
+            sizeof(intel_gl_vendor_table) / sizeof(*intel_gl_vendor_table),
+            card_fallback_intel},
 };
 
 
@@ -2232,7 +2316,7 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
      * size of the database can be made quite small because when you know what
      * type of 3d functionality a card has, you know to which GPU family the
      * GPU must belong. Because of this you only have to check a small part of
-     * the renderer string to distinguishes between different models from that
+     * the renderer string to distinguish between different models from that
      * family.
      *
      * The code also selects a default amount of video memory which we will
@@ -2247,7 +2331,8 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
      * memory behind our backs if really needed. Note that the amount of video
      * memory can be overruled using a registry setting. */
 
-    int i;
+    unsigned int i;
+    enum wined3d_d3d_level d3d_level = d3d_level_from_gl_info(gl_info);
     enum wined3d_pci_device device;
 
     for (i = 0; i < (sizeof(card_vendor_table) / sizeof(*card_vendor_table)); ++i)
@@ -2257,12 +2342,12 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
 
         TRACE("Applying card selector \"%s\".\n", card_vendor_table[i].description);
         device = select_card_handler(card_vendor_table[i].gl_vendor_selection,
-                card_vendor_table[i].gl_vendor_count, *gl_vendor, gl_info, gl_renderer);
+                card_vendor_table[i].gl_vendor_count, *gl_vendor, gl_renderer);
         if (device != PCI_DEVICE_NONE)
             return device;
 
         TRACE("Unrecognized renderer %s, falling back to default.\n", debugstr_a(gl_renderer));
-        return card_vendor_table[i].select_card_fallback(gl_info);
+        return card_vendor_table[i].card_fallback[d3d_level];
     }
 
     FIXME("No card selector available for card vendor %04x (using GL_RENDERER %s).\n",
@@ -2270,7 +2355,15 @@ static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *
 
     /* Default to generic Nvidia hardware based on the supported OpenGL extensions. */
     *card_vendor = HW_VENDOR_NVIDIA;
-    return select_card_fallback_nvidia(gl_info);
+    return card_fallback_nvidia[d3d_level];
+}
+
+static const struct wined3d_vertex_pipe_ops *select_vertex_implementation(const struct wined3d_gl_info *gl_info,
+        const struct wined3d_shader_backend_ops *shader_backend_ops)
+{
+    if (shader_backend_ops == &glsl_shader_backend)
+        return &glsl_vertex_pipe;
+    return &ffp_vertex_pipe;
 }
 
 static const struct fragment_pipeline *select_fragment_implementation(const struct wined3d_gl_info *gl_info,
@@ -2376,6 +2469,9 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
     gl_info->limits.buffers = 1;
     gl_info->limits.textures = 1;
     gl_info->limits.texture_coords = 1;
+    gl_info->limits.vertex_uniform_blocks = 0;
+    gl_info->limits.geometry_uniform_blocks = 0;
+    gl_info->limits.fragment_uniform_blocks = 0;
     gl_info->limits.fragment_samplers = 1;
     gl_info->limits.vertex_samplers = 0;
     gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
@@ -2415,7 +2511,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
     }
     else
     {
-        WARN("Driver doesn't guarantee a minimum buffer map alignment.\n");
+        WARN_(d3d_perf)("Driver doesn't guarantee a minimum buffer map alignment.\n");
     }
     if (gl_info->supported[NV_REGISTER_COMBINERS])
     {
@@ -2552,6 +2648,19 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
         gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
         gl_info->limits.glsl_vs_float_constants = gl_max / 4;
         TRACE("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
+
+        if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &gl_max);
+            gl_info->limits.vertex_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
+            TRACE("Max vertex uniform blocks: %u (%d).\n", gl_info->limits.vertex_uniform_blocks, gl_max);
+        }
+    }
+    if (gl_info->supported[ARB_GEOMETRY_SHADER4] && gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_GEOMETRY_UNIFORM_BLOCKS, &gl_max);
+        gl_info->limits.geometry_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
+        TRACE("Max geometry uniform blocks: %u (%d).\n", gl_info->limits.geometry_uniform_blocks, gl_max);
     }
     if (gl_info->supported[ARB_FRAGMENT_SHADER])
     {
@@ -2561,6 +2670,20 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info)
         gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
         gl_info->limits.glsl_varyings = gl_max;
         TRACE("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
+
+        if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
+        {
+            gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &gl_max);
+            gl_info->limits.fragment_uniform_blocks = min(gl_max, WINED3D_MAX_CBS);
+            TRACE("Max fragment uniform blocks: %u (%d).\n", gl_info->limits.fragment_uniform_blocks, gl_max);
+        }
+    }
+    if (gl_info->supported[ARB_UNIFORM_BUFFER_OBJECT])
+    {
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_COMBINED_UNIFORM_BLOCKS, &gl_max);
+        TRACE("Max combined uniform blocks: %d.\n", gl_max);
+        gl_info->gl_ops.gl.p_glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &gl_max);
+        TRACE("Max uniform buffer bindings: %d.\n", gl_max);
     }
 
     if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
@@ -2582,14 +2705,17 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     struct wined3d_driver_info *driver_info = &adapter->driver_info;
     const char *gl_vendor_str, *gl_renderer_str, *gl_version_str;
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct wined3d_vertex_caps vertex_caps;
     enum wined3d_pci_vendor card_vendor;
     struct fragment_caps fragment_caps;
+    struct shader_caps shader_caps;
     const char *WGL_Extensions = NULL;
     const char *GL_Extensions = NULL;
     enum wined3d_gl_vendor gl_vendor;
     enum wined3d_pci_device device;
     DWORD gl_version;
     HDC hdc;
+    unsigned int i;
 
     TRACE("adapter %p.\n", adapter);
 
@@ -2768,6 +2894,34 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
          * we never render to sRGB surfaces). */
         gl_info->supported[ARB_FRAMEBUFFER_SRGB] = FALSE;
     }
+    if (gl_info->supported[ARB_OCCLUSION_QUERY])
+    {
+        GLint counter_bits;
+
+        GL_EXTCALL(glGetQueryivARB(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &counter_bits));
+        TRACE("Occlusion query counter has %d bits.\n", counter_bits);
+        if (!counter_bits)
+            gl_info->supported[ARB_OCCLUSION_QUERY] = FALSE;
+    }
+    if (gl_info->supported[ARB_TIMER_QUERY])
+    {
+        GLint counter_bits;
+
+        GL_EXTCALL(glGetQueryivARB(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS_ARB, &counter_bits));
+        TRACE("Timestamp query counter has %d bits.\n", counter_bits);
+        if (!counter_bits)
+            gl_info->supported[ARB_TIMER_QUERY] = FALSE;
+    }
+    if (!gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] && gl_info->supported[EXT_TEXTURE_MIRROR_CLAMP])
+    {
+        TRACE(" IMPLIED: ATI_texture_mirror_once support (by EXT_texture_mirror_clamp).\n");
+        gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
+    }
+    if (!gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE] && gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
+    {
+        TRACE(" IMPLIED: ARB_texture_mirror_clamp_to_edge support (by ATI_texture_mirror_once).\n");
+        gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE] = TRUE;
+    }
 
     wined3d_adapter_init_limits(gl_info);
 
@@ -2789,12 +2943,25 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     checkGLcall("extension detection");
 
     adapter->shader_backend = select_shader_backend(gl_info);
+    adapter->vertex_pipe = select_vertex_implementation(gl_info, adapter->shader_backend);
     adapter->fragment_pipe = select_fragment_implementation(gl_info, adapter->shader_backend);
     adapter->blitter = select_blit_implementation(gl_info, adapter->shader_backend);
 
+    adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
+    adapter->d3d_info.vs_clipping = shader_caps.wined3d_caps & WINED3D_SHADER_CAP_VS_CLIPPING;
+    adapter->d3d_info.limits.vs_version = shader_caps.vs_version;
+    adapter->d3d_info.limits.gs_version = shader_caps.gs_version;
+    adapter->d3d_info.limits.ps_version = shader_caps.ps_version;
+    adapter->d3d_info.limits.vs_uniform_count = shader_caps.vs_uniform_count;
+    adapter->d3d_info.limits.ps_uniform_count = shader_caps.ps_uniform_count;
+
+    adapter->vertex_pipe->vp_get_caps(gl_info, &vertex_caps);
+    adapter->d3d_info.xyzrhw = vertex_caps.xyzrhw;
+
     adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
-    gl_info->limits.texture_stages = fragment_caps.MaxTextureBlendStages;
-    TRACE("Max texture stages: %u.\n", gl_info->limits.texture_stages);
+    adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages;
+    adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures;
+    TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages);
 
     if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
     {
@@ -2844,7 +3011,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
         }
         else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
         {
-            WARN("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
+            WARN_(d3d_perf)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
             wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
         }
         if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
@@ -2872,7 +3039,11 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter)
     gl_info->wrap_lookup[WINED3D_TADDRESS_BORDER - WINED3D_TADDRESS_WRAP] =
             gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
     gl_info->wrap_lookup[WINED3D_TADDRESS_MIRROR_ONCE - WINED3D_TADDRESS_WRAP] =
-            gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
+            gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE] ? GL_MIRROR_CLAMP_TO_EDGE : GL_REPEAT;
+
+    adapter->d3d_info.valid_rt_mask = 0;
+    for (i = 0; i < gl_info->limits.buffers; ++i)
+        adapter->d3d_info.valid_rt_mask |= (1 << i);
 
     fixup_extensions(gl_info, gl_renderer_str, gl_vendor, card_vendor, device);
     init_driver_info(driver_info, card_vendor, device);
@@ -3215,7 +3386,7 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d,
         const char *name = adapter->driver_info.name;
         len = min(strlen(name), identifier->driver_size - 1);
         memcpy(identifier->driver, name, len);
-        identifier->driver[len] = '\0';
+        memset(&identifier->driver[len], 0, identifier->driver_size - len);
     }
 
     if (identifier->description_size)
@@ -3223,7 +3394,7 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d,
         const char *description = adapter->driver_info.description;
         len = min(strlen(description), identifier->description_size - 1);
         memcpy(identifier->description, description, len);
-        identifier->description[len] = '\0';
+        memset(&identifier->description[len], 0, identifier->description_size - len);
     }
 
     /* Note that d3d8 doesn't supply a device name. */
@@ -3246,7 +3417,7 @@ HRESULT CDECL wined3d_get_adapter_identifier(const struct wined3d *wined3d,
     memcpy(&identifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(identifier->device_identifier));
     identifier->whql_level = (flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
     memcpy(&identifier->adapter_luid, &adapter->luid, sizeof(identifier->adapter_luid));
-    identifier->video_memory = adapter->TextureRam;
+    identifier->video_memory = min(~(SIZE_T)0, adapter->vram_bytes);
 
     return WINED3D_OK;
 }
@@ -3599,6 +3770,14 @@ static BOOL CheckSurfaceCapability(const struct wined3d_adapter *adapter,
     return FALSE;
 }
 
+/* OpenGL supports mipmapping on all formats. Wrapping is unsupported, but we
+ * have to report mipmapping so we cannot reject WRAPANDMIP. Tests show that
+ * Windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to
+ * show that wrapping is supported. The lack of filtering will sort out the
+ * mipmapping capability anyway.
+ *
+ * For now lets report this on all formats, but in the future we may want to
+ * restrict it to some should applications need that. */
 HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT adapter_idx,
         enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id, DWORD usage,
         enum wined3d_resource_type resource_type, enum wined3d_format_id check_format_id)
@@ -3607,7 +3786,8 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     const struct wined3d_format *adapter_format = wined3d_get_format(gl_info, adapter_format_id);
     const struct wined3d_format *format = wined3d_get_format(gl_info, check_format_id);
-    DWORD usage_caps = 0;
+    DWORD format_flags = 0;
+    DWORD allowed_usage;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, adapter_format %s, usage %s, %s,\n"
             "resource_type %s, check_format %s.\n",
@@ -3621,375 +3801,82 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
     switch (resource_type)
     {
         case WINED3D_RTYPE_CUBE_TEXTURE:
-            /* Cubetexture allows:
-             *      - WINED3DUSAGE_AUTOGENMIPMAP
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_DYNAMIC
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             *      - WINED3DUSAGE_SOFTWAREPROCESSING
-             *      - WINED3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
             if (!gl_info->supported[ARB_TEXTURE_CUBE_MAP])
             {
                 TRACE("[FAILED] - No cube texture support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
-            {
-                TRACE("[FAILED] - Cube texture format not supported.\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
-            if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
-            {
-                if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
-                    /* When autogenmipmap isn't around continue and return
-                     * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
-                    TRACE("[FAILED] - No autogenmipmap support, but continuing.\n");
-                else
-                    usage_caps |= WINED3DUSAGE_AUTOGENMIPMAP;
-            }
-
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
-
-            /* OpenGL supports mipmapping on all formats. Wrapping is
-             * unsupported, but we have to report mipmapping so we cannot
-             * reject this flag. Tests show that Windows reports WRAPANDMIP on
-             * unfilterable surfaces as well, apparently to show that wrapping
-             * is supported. The lack of filtering will sort out the
-             * mipmapping capability anyway.
-             *
-             * For now lets report this on all formats, but in the future we
-             * may want to restrict it to some should applications need that. */
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
-
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
             break;
 
         case WINED3D_RTYPE_SURFACE:
-            /* Surface allows:
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             */
             if (!CheckSurfaceCapability(adapter, adapter_format, format, wined3d->flags & WINED3D_NO3D))
             {
                 TRACE("[FAILED] - Not supported for plain surfaces.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (usage & WINED3DUSAGE_DEPTHSTENCIL)
-            {
-                if (!CheckDepthStencilCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No depth/stencil support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_DEPTHSTENCIL;
-            }
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
+            allowed_usage = WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
             break;
 
         case WINED3D_RTYPE_TEXTURE:
-            /* Texture allows:
-             *      - WINED3DUSAGE_AUTOGENMIPMAP
-             *      - WINED3DUSAGE_DEPTHSTENCIL
-             *      - WINED3DUSAGE_DMAP
-             *      - WINED3DUSAGE_DYNAMIC
-             *      - WINED3DUSAGE_NONSECURE (d3d9ex)
-             *      - WINED3DUSAGE_RENDERTARGET
-             *      - WINED3DUSAGE_SOFTWAREPROCESSING
-             *      - WINED3DUSAGE_TEXTAPI (d3d9ex)
-             *      - WINED3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
+            if ((usage & WINED3DUSAGE_DEPTHSTENCIL) && (format->flags & WINED3DFMT_FLAG_SHADOW)
+                    && !gl_info->supported[ARB_SHADOW])
             {
-                TRACE("[FAILED] - Texture format not supported.\n");
+                TRACE("[FAILED] - No shadow sampler support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (usage & WINED3DUSAGE_AUTOGENMIPMAP)
-            {
-                if (!gl_info->supported[SGIS_GENERATE_MIPMAP])
-                    /* When autogenmipmap isn't around continue and return
-                     * WINED3DOK_NOAUTOGEN instead of D3D_OK. */
-                    TRACE("[FAILED] - No autogenmipmap support, but continuing.\n");
-                else
-                    usage_caps |= WINED3DUSAGE_AUTOGENMIPMAP;
-            }
-
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            if (usage & WINED3DUSAGE_RENDERTARGET)
-            {
-                if (!CheckRenderTargetCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No render target support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_RENDERTARGET;
-            }
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_BUMPMAP))
-                {
-                    TRACE("[FAILED] - No legacy bumpmap support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
-
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
-
-            if (usage & WINED3DUSAGE_DEPTHSTENCIL)
-            {
-                if (!CheckDepthStencilCapability(adapter, adapter_format, format))
-                {
-                    TRACE("[FAILED] - No depth/stencil support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                if ((format->flags & WINED3DFMT_FLAG_SHADOW) && !gl_info->supported[ARB_SHADOW])
-                {
-                    TRACE("[FAILED] - No shadow sampler support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_DEPTHSTENCIL;
-            }
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_AUTOGENMIPMAP
+                    | WINED3DUSAGE_DEPTHSTENCIL
+                    | WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_RENDERTARGET
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_LEGACYBUMPMAP
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
             break;
 
         case WINED3D_RTYPE_VOLUME_TEXTURE:
         case WINED3D_RTYPE_VOLUME:
             /* Volume is to VolumeTexture what Surface is to Texture, but its
              * usage caps are not documented. Most driver seem to offer
-             * (nearly) the same on Volume and VolumeTexture, so do that too.
-             *
-             * Volumetexture allows:
-             *      - D3DUSAGE_DYNAMIC
-             *      - D3DUSAGE_NONSECURE (d3d9ex)
-             *      - D3DUSAGE_SOFTWAREPROCESSING
-             *      - D3DUSAGE_QUERY_WRAPANDMIP
-             */
-            if (wined3d->flags & WINED3D_NO3D)
-            {
-                TRACE("[FAILED]\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
+             * (nearly) the same on Volume and VolumeTexture, so do that too. */
             if (!gl_info->supported[EXT_TEXTURE3D])
             {
                 TRACE("[FAILED] - No volume texture support.\n");
                 return WINED3DERR_NOTAVAILABLE;
             }
 
-            if (!(format->flags & WINED3DFMT_FLAG_TEXTURE))
-            {
-                TRACE("[FAILED] - Format not supported.\n");
-                return WINED3DERR_NOTAVAILABLE;
-            }
-
-            /* Filter formats that need conversion; For one part, this
-             * conversion is unimplemented, and volume textures are huge, so
-             * it would be a big performance hit. Unless we hit an application
-             * needing one of those formats, don't advertize them to avoid
-             * leading applications into temptation. The windows drivers don't
-             * support most of those formats on volumes anyway, except for
-             * WINED3DFMT_R32_FLOAT. */
+            /* The GL_EXT_texture_compression_s3tc spec requires that loading
+             * an s3tc compressed texture results in an error. While the D3D
+             * refrast does support s3tc volumes, at least the nvidia Windows
+             * driver does not, so we're free not to support this format. */
             switch (check_format_id)
             {
-                case WINED3DFMT_P8_UINT:
-                case WINED3DFMT_L4A4_UNORM:
-                case WINED3DFMT_R32_FLOAT:
-                case WINED3DFMT_R16_FLOAT:
-                case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
-                case WINED3DFMT_R5G5_SNORM_L6_UNORM:
-                case WINED3DFMT_R16G16_UNORM:
-                    TRACE("[FAILED] - No converted formats on volumes.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-
-                case WINED3DFMT_R8G8B8A8_SNORM:
-                case WINED3DFMT_R16G16_SNORM:
-                    if (!gl_info->supported[NV_TEXTURE_SHADER])
-                    {
-                        TRACE("[FAILED] - No converted formats on volumes.\n");
-                        return WINED3DERR_NOTAVAILABLE;
-                    }
-                    break;
-
-                case WINED3DFMT_R8G8_SNORM:
-                    if (!gl_info->supported[NV_TEXTURE_SHADER])
-                    {
-                        TRACE("[FAILED] - No converted formats on volumes.\n");
-                        return WINED3DERR_NOTAVAILABLE;
-                    }
-                    break;
-
                 case WINED3DFMT_DXT1:
                 case WINED3DFMT_DXT2:
                 case WINED3DFMT_DXT3:
                 case WINED3DFMT_DXT4:
                 case WINED3DFMT_DXT5:
-                    /* The GL_EXT_texture_compression_s3tc spec requires that
-                     * loading an s3tc compressed texture results in an error.
-                     * While the D3D refrast does support s3tc volumes, at
-                     * least the nvidia windows driver does not, so we're free
-                     * not to support this format. */
                     TRACE("[FAILED] - DXTn does not support 3D textures.\n");
                     return WINED3DERR_NOTAVAILABLE;
 
@@ -3998,86 +3885,93 @@ HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d, UINT ad
                     break;
             }
 
-            /* Always report dynamic locking. */
-            if (usage & WINED3DUSAGE_DYNAMIC)
-                usage_caps |= WINED3DUSAGE_DYNAMIC;
-
-            /* Always report software processing. */
-            if (usage & WINED3DUSAGE_SOFTWAREPROCESSING)
-                usage_caps |= WINED3DUSAGE_SOFTWAREPROCESSING;
-
-            if (usage & WINED3DUSAGE_QUERY_FILTER)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_FILTERING))
-                {
-                    TRACE("[FAILED] - No filter support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_FILTER;
-            }
+            format_flags |= WINED3DFMT_FLAG_TEXTURE;
+            allowed_usage = WINED3DUSAGE_DYNAMIC
+                    | WINED3DUSAGE_SOFTWAREPROCESSING
+                    | WINED3DUSAGE_QUERY_FILTER
+                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
+                    | WINED3DUSAGE_QUERY_SRGBREAD
+                    | WINED3DUSAGE_QUERY_SRGBWRITE
+                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
+                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
+            break;
 
-            if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-                {
-                    TRACE("[FAILED] - No post pixelshader blending support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
-            }
+        default:
+            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
+            return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_READ))
-                {
-                    TRACE("[FAILED] - No sRGB read support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBREAD;
-            }
+    if ((usage & allowed_usage) != usage)
+    {
+        TRACE("Requested usage %#x, but resource type %s only allows %#x.\n",
+                usage, debug_d3dresourcetype(resource_type), allowed_usage);
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_SRGB_WRITE))
-                {
-                    TRACE("[FAILED] - No sRGB write support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_SRGBWRITE;
-            }
+    if (usage & WINED3DUSAGE_QUERY_FILTER)
+        format_flags |= WINED3DFMT_FLAG_FILTERING;
+    if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
+        format_flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
+    if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
+        format_flags |= WINED3DFMT_FLAG_SRGB_READ;
+    if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
+        format_flags |= WINED3DFMT_FLAG_SRGB_WRITE;
+    if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
+        format_flags |= WINED3DFMT_FLAG_VTF;
+    if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
+        format_flags |= WINED3DFMT_FLAG_BUMPMAP;
 
-            if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
-            {
-                if (!(format->flags & WINED3DFMT_FLAG_VTF))
-                {
-                    TRACE("[FAILED] - No vertex texture support.\n");
-                    return WINED3DERR_NOTAVAILABLE;
-                }
-                usage_caps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
-            }
+    if ((format->flags & format_flags) != format_flags)
+    {
+        TRACE("Requested format flags %#x, but format %s only has %#x.\n",
+                format_flags, debug_d3dformat(check_format_id), format->flags);
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            if (usage & WINED3DUSAGE_QUERY_WRAPANDMIP)
-                usage_caps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
+    if ((format_flags & WINED3DFMT_FLAG_TEXTURE) && (wined3d->flags & WINED3D_NO3D))
+    {
+        TRACE("Requested texturing support, but wined3d was created with WINED3D_NO3D.\n");
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-            break;
+    if ((usage & WINED3DUSAGE_DEPTHSTENCIL)
+            && !CheckDepthStencilCapability(adapter, adapter_format, format))
+    {
+        TRACE("Requested WINED3DUSAGE_DEPTHSTENCIL, but format %s is not supported for depth / stencil buffers.\n",
+                debug_d3dformat(check_format_id));
+        return WINED3DERR_NOTAVAILABLE;
+    }
 
-        default:
-            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
-            return WINED3DERR_NOTAVAILABLE;
+    if ((usage & WINED3DUSAGE_RENDERTARGET)
+            && !CheckRenderTargetCapability(adapter, adapter_format, format))
+    {
+        TRACE("Requested WINED3DUSAGE_RENDERTARGET, but format %s is not supported for render targets.\n",
+                debug_d3dformat(check_format_id));
+        return WINED3DERR_NOTAVAILABLE;
     }
 
-    /* When the usage_caps exactly matches usage return WINED3D_OK except for
-     * the situation in which WINED3DUSAGE_AUTOGENMIPMAP isn't around, then
-     * WINED3DOK_NOAUTOGEN is returned if all the other usage flags match. */
-    if (usage_caps == usage)
-        return WINED3D_OK;
-    if (usage_caps == (usage & ~WINED3DUSAGE_AUTOGENMIPMAP))
+    if ((usage & WINED3DUSAGE_AUTOGENMIPMAP) && !gl_info->supported[SGIS_GENERATE_MIPMAP])
+    {
+        TRACE("No WINED3DUSAGE_AUTOGENMIPMAP support, returning WINED3DOK_NOAUTOGEN.\n");
         return WINED3DOK_NOAUTOGEN;
+    }
 
-    TRACE("[FAILED] - Usage %#x requested for format %s and resource_type %s but only %#x is available.\n",
-            usage, debug_d3dformat(check_format_id), debug_d3dresourcetype(resource_type), usage_caps);
+    return WINED3D_OK;
+}
 
-    return WINED3DERR_NOTAVAILABLE;
+UINT CDECL wined3d_calculate_format_pitch(const struct wined3d *wined3d, UINT adapter_idx,
+        enum wined3d_format_id format_id, UINT width)
+{
+    const struct wined3d_gl_info *gl_info;
+
+    TRACE("wined3d %p, adapter_idx %u, format_id %s, width %u.\n",
+            wined3d, adapter_idx, debug_d3dformat(format_id), width);
+
+    if (adapter_idx >= wined3d->adapter_count)
+        return ~0u;
+
+    gl_info = &wined3d->adapters[adapter_idx].gl_info;
+    return wined3d_format_calculate_pitch(wined3d_get_format(gl_info, format_id), width);
 }
 
 HRESULT CDECL wined3d_check_device_format_conversion(const struct wined3d *wined3d, UINT adapter_idx,
@@ -4094,8 +3988,7 @@ HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d, UINT adap
         enum wined3d_device_type device_type, enum wined3d_format_id display_format,
         enum wined3d_format_id backbuffer_format, BOOL windowed)
 {
-    UINT mode_count;
-    HRESULT hr;
+    BOOL present_conversion = wined3d->flags & WINED3D_PRESENT_CONVERSION;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
             wined3d, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(display_format),
@@ -4108,10 +4001,7 @@ HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d, UINT adap
      * combination is available on the given adapter. In fullscreen mode microsoft specified
      * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
      * and display format should match exactly.
-     * In windowed mode format conversion can occur and this depends on the driver. When format
-     * conversion is done, this function should nevertheless fail and applications need to use
-     * CheckDeviceFormatConversion.
-     * At the moment we assume that fullscreen and windowed have the same capabilities. */
+     * In windowed mode format conversion can occur and this depends on the driver. */
 
     /* There are only 4 display formats. */
     if (!(display_format == WINED3DFMT_B5G6R5_UNORM
@@ -4123,72 +4013,88 @@ HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d, UINT adap
         return WINED3DERR_NOTAVAILABLE;
     }
 
-    /* If the requested display format is not available, don't continue. */
-    mode_count = wined3d_get_adapter_mode_count(wined3d, adapter_idx,
-            display_format, WINED3D_SCANLINE_ORDERING_UNKNOWN);
-    if (!mode_count)
+    if (!windowed)
     {
-        TRACE("No available modes for display format %s.\n", debug_d3dformat(display_format));
-        return WINED3DERR_NOTAVAILABLE;
-    }
+        /* If the requested display format is not available, don't continue. */
+        if (!wined3d_get_adapter_mode_count(wined3d, adapter_idx,
+                display_format, WINED3D_SCANLINE_ORDERING_UNKNOWN))
+        {
+            TRACE("No available modes for display format %s.\n", debug_d3dformat(display_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
 
-    /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbuffer format,
-     * it means 'reuse' the display format for the backbuffer. */
-    if (!windowed && backbuffer_format == WINED3DFMT_UNKNOWN)
-    {
-        TRACE("backbuffer_format WINED3FMT_UNKNOWN only available in windowed mode.\n");
-        return WINED3DERR_NOTAVAILABLE;
+        present_conversion = FALSE;
     }
-
-    /* In FULLSCREEN mode WINED3DFMT_B5G6R5_UNORM can only be mixed with
-     * backbuffer format WINED3DFMT_B5G6R5_UNORM. */
-    if (display_format == WINED3DFMT_B5G6R5_UNORM && backbuffer_format != WINED3DFMT_B5G6R5_UNORM)
+    else if (display_format == WINED3DFMT_B10G10R10A2_UNORM)
     {
-        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
+        /* WINED3DFMT_B10G10R10A2_UNORM is only allowed in fullscreen mode. */
+        TRACE("Unsupported format combination %s / %s in windowed mode.\n",
                 debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
         return WINED3DERR_NOTAVAILABLE;
     }
 
-    /* In FULLSCREEN mode WINED3DFMT_B5G5R5X1_UNORM can only be mixed with
-     * backbuffer formats WINED3DFMT_B5G5R5X1_UNORM and
-     * WINED3DFMT_B5G5R5A1_UNORM. */
-    if (display_format == WINED3DFMT_B5G5R5X1_UNORM
-            && !(backbuffer_format == WINED3DFMT_B5G5R5X1_UNORM || backbuffer_format == WINED3DFMT_B5G5R5A1_UNORM))
+    if (present_conversion)
     {
-        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
-                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
-        return WINED3DERR_NOTAVAILABLE;
-    }
+        /* Use the display format as back buffer format if the latter is
+         * WINED3DFMT_UNKNOWN. */
+        if (backbuffer_format == WINED3DFMT_UNKNOWN)
+            backbuffer_format = display_format;
 
-    /* In FULLSCREEN mode WINED3DFMT_B8G8R8X8_UNORM can only be mixed with
-     * backbuffer formats WINED3DFMT_B8G8R8X8_UNORM and
-     * WINED3DFMT_B8G8R8A8_UNORM. */
-    if (display_format == WINED3DFMT_B8G8R8X8_UNORM
-            && !(backbuffer_format == WINED3DFMT_B8G8R8X8_UNORM || backbuffer_format == WINED3DFMT_B8G8R8A8_UNORM))
+        if (FAILED(wined3d_check_device_format_conversion(wined3d, adapter_idx,
+                device_type, backbuffer_format, display_format)))
+        {
+            TRACE("Format conversion from %s to %s not supported.\n",
+                    debug_d3dformat(backbuffer_format), debug_d3dformat(display_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
+    }
+    else
     {
-        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
-                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
-        return WINED3DERR_NOTAVAILABLE;
+        /* When format conversion from the back buffer format to the display
+         * format is not allowed, only a limited number of combinations are
+         * valid. */
+
+        if (display_format == WINED3DFMT_B5G6R5_UNORM && backbuffer_format != WINED3DFMT_B5G6R5_UNORM)
+        {
+            TRACE("Unsupported format combination %s / %s.\n",
+                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
+
+        if (display_format == WINED3DFMT_B5G5R5X1_UNORM
+                && !(backbuffer_format == WINED3DFMT_B5G5R5X1_UNORM || backbuffer_format == WINED3DFMT_B5G5R5A1_UNORM))
+        {
+            TRACE("Unsupported format combination %s / %s.\n",
+                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
+
+        if (display_format == WINED3DFMT_B8G8R8X8_UNORM
+                && !(backbuffer_format == WINED3DFMT_B8G8R8X8_UNORM || backbuffer_format == WINED3DFMT_B8G8R8A8_UNORM))
+        {
+            TRACE("Unsupported format combination %s / %s.\n",
+                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
+
+        if (display_format == WINED3DFMT_B10G10R10A2_UNORM
+                && backbuffer_format != WINED3DFMT_B10G10R10A2_UNORM)
+        {
+            TRACE("Unsupported format combination %s / %s.\n",
+                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+            return WINED3DERR_NOTAVAILABLE;
+        }
     }
 
-    /* WINED3DFMT_B10G10R10A2_UNORM is only allowed in fullscreen mode and it
-     * can only be mixed with backbuffer format WINED3DFMT_B10G10R10A2_UNORM. */
-    if (display_format == WINED3DFMT_B10G10R10A2_UNORM
-            && (backbuffer_format != WINED3DFMT_B10G10R10A2_UNORM || windowed))
+    /* Validate that the back buffer format is usable for render targets. */
+    if (FAILED(wined3d_check_device_format(wined3d, adapter_idx, device_type, display_format,
+            WINED3DUSAGE_RENDERTARGET, WINED3D_RTYPE_SURFACE, backbuffer_format)))
     {
-        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
-                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
+        TRACE("Format %s not allowed for render targets.\n", debug_d3dformat(backbuffer_format));
         return WINED3DERR_NOTAVAILABLE;
     }
 
-    /* Use CheckDeviceFormat to see if the backbuffer_format is usable with the given display_format */
-    hr = wined3d_check_device_format(wined3d, adapter_idx, device_type, display_format,
-            WINED3DUSAGE_RENDERTARGET, WINED3D_RTYPE_SURFACE, backbuffer_format);
-    if (FAILED(hr))
-        TRACE("Unsupported display/backbuffer format combination %s / %s.\n",
-                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
-
-    return hr;
+    return WINED3D_OK;
 }
 
 HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapter_idx,
@@ -4198,7 +4104,8 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
     struct shader_caps shader_caps;
     struct fragment_caps fragment_caps;
-    DWORD ckey_caps, blit_caps, fx_caps, pal_caps;
+    struct wined3d_vertex_caps vertex_caps;
+    DWORD ckey_caps, blit_caps, fx_caps;
 
     TRACE("wined3d %p, adapter_idx %u, device_type %s, caps %p.\n",
             wined3d, adapter_idx, debug_d3ddevicetype(device_type), caps);
@@ -4282,16 +4189,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                              WINED3DPRASTERCAPS_ZBIAS         |
                              WINED3DPRASTERCAPS_MIPMAPLODBIAS;
     }
-    if (gl_info->supported[NV_FOG_DISTANCE])
-    {
-        caps->RasterCaps          |= WINED3DPRASTERCAPS_FOGRANGE;
-    }
-                        /* FIXME Add:
-                           WINED3DPRASTERCAPS_COLORPERSPECTIVE
-                           WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
-                           WINED3DPRASTERCAPS_ANTIALIASEDGES
-                           WINED3DPRASTERCAPS_ZBUFFERLESSHSR
-                           WINED3DPRASTERCAPS_WBUFFER */
 
     caps->ZCmpCaps =  WINED3DPCMPCAPS_ALWAYS       |
                       WINED3DPCMPCAPS_EQUAL        |
@@ -4302,6 +4199,8 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                       WINED3DPCMPCAPS_NEVER        |
                       WINED3DPCMPCAPS_NOTEQUAL;
 
+    /* WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA
+     * are legacy settings for srcblend only. */
     caps->SrcBlendCaps  =  WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
                            WINED3DPBLENDCAPS_BOTHSRCALPHA    |
                            WINED3DPBLENDCAPS_DESTALPHA       |
@@ -4326,12 +4225,9 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                            WINED3DPBLENDCAPS_SRCALPHA        |
                            WINED3DPBLENDCAPS_SRCCOLOR        |
                            WINED3DPBLENDCAPS_ZERO;
-    /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
-     * according to the glBlendFunc manpage
-     *
-     * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
-     * legacy settings for srcblend only
-     */
+
+    if (gl_info->supported[ARB_BLEND_FUNC_EXTENDED])
+        caps->DestBlendCaps |= WINED3DPBLENDCAPS_SRCALPHASAT;
 
     if (gl_info->supported[EXT_BLEND_COLOR])
     {
@@ -4469,7 +4365,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
     {
         caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
     }
-    if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
+    if (gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE])
     {
         caps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
     }
@@ -4487,7 +4383,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
         {
             caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
         }
-        if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
+        if (gl_info->supported[ARB_TEXTURE_MIRROR_CLAMP_TO_EDGE])
         {
             caps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
         }
@@ -4541,28 +4437,11 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
         caps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
     }
 
-    caps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
-
-    caps->MaxUserClipPlanes = gl_info->limits.clipplanes;
-    caps->MaxActiveLights = gl_info->limits.lights;
-
-    caps->MaxVertexBlendMatrices = gl_info->limits.blends;
-    caps->MaxVertexBlendMatrixIndex   = 0;
-
     caps->MaxAnisotropy = gl_info->limits.anisotropy;
     caps->MaxPointSize = gl_info->limits.pointsize_max;
 
-
-    /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
-    caps->VertexProcessingCaps  = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
-                                  WINED3DVTXPCAPS_MATERIALSOURCE7   |
-                                  WINED3DVTXPCAPS_POSITIONALLIGHTS  |
-                                  WINED3DVTXPCAPS_LOCALVIEWER       |
-                                  WINED3DVTXPCAPS_VERTEXFOG         |
-                                  WINED3DVTXPCAPS_TEXGEN;
-
-    caps->MaxPrimitiveCount   = 0xfffff; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
-    caps->MaxVertexIndex      = 0xfffff;
+    caps->MaxPrimitiveCount   = 0x555555; /* Taken from an AMD Radeon HD 5700 (Evergreen) GPU. */
+    caps->MaxVertexIndex      = 0xffffff; /* Taken from an AMD Radeon HD 5700 (Evergreen) GPU. */
     caps->MaxStreams          = MAX_STREAMS;
     caps->MaxStreamStride     = 1024;
 
@@ -4584,6 +4463,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
 
     adapter->shader_backend->shader_get_caps(&adapter->gl_info, &shader_caps);
     adapter->fragment_pipe->get_caps(&adapter->gl_info, &fragment_caps);
+    adapter->vertex_pipe->vp_get_caps(&adapter->gl_info, &vertex_caps);
 
     /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
     caps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
@@ -4598,6 +4478,14 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
     caps->MaxTextureBlendStages            = fragment_caps.MaxTextureBlendStages;
     caps->MaxSimultaneousTextures          = fragment_caps.MaxSimultaneousTextures;
 
+    caps->MaxUserClipPlanes                = vertex_caps.max_user_clip_planes;
+    caps->MaxActiveLights                  = vertex_caps.max_active_lights;
+    caps->MaxVertexBlendMatrices           = vertex_caps.max_vertex_blend_matrices;
+    caps->MaxVertexBlendMatrixIndex        = vertex_caps.max_vertex_blend_matrix_index;
+    caps->VertexProcessingCaps             = vertex_caps.vertex_processing_caps;
+    caps->FVFCaps                          = vertex_caps.fvf_caps;
+    caps->RasterCaps                      |= vertex_caps.raster_caps;
+
     /* The following caps are shader specific, but they are things we cannot detect, or which
      * are the same among all shader models. So to avoid code duplication set the shader version
      * specific, but otherwise constant caps here
@@ -4617,6 +4505,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
 
         caps->MaxVShaderInstructionsExecuted    = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
         caps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
+        caps->VertexTextureFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT | WINED3DPTFILTERCAPS_MAGFPOINT;
     }
     else if (caps->VertexShaderVersion == 2)
     {
@@ -4725,7 +4614,7 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                         WINEDDFXCAPS_BLTSHRINKX             |
                                         WINEDDFXCAPS_BLTSHRINKXN            |
                                         WINEDDFXCAPS_BLTSHRINKY             |
-                                        WINEDDFXCAPS_BLTSHRINKXN            |
+                                        WINEDDFXCAPS_BLTSHRINKYN            |
                                         WINEDDFXCAPS_BLTSTRETCHX            |
                                         WINEDDFXCAPS_BLTSTRETCHXN           |
                                         WINEDDFXCAPS_BLTSTRETCHY            |
@@ -4740,8 +4629,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                         WINEDDCAPS_COLORKEY                 |
                                         WINEDDCAPS_COLORKEYHWASSIST         |
                                         WINEDDCAPS_ALIGNBOUNDARYSRC;
-    pal_caps =                          WINEDDPCAPS_8BIT                    |
-                                        WINEDDPCAPS_PRIMARYSURFACE;
 
     /* Fill the ddraw caps structure */
     caps->ddraw_caps.caps =             WINEDDCAPS_GDI                      |
@@ -4754,7 +4641,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                         WINEDDCAPS2_CANRENDERWINDOWED;
     caps->ddraw_caps.color_key_caps = ckey_caps;
     caps->ddraw_caps.fx_caps = fx_caps;
-    caps->ddraw_caps.pal_caps = pal_caps;
     caps->ddraw_caps.svb_caps = blit_caps;
     caps->ddraw_caps.svb_color_key_caps = ckey_caps;
     caps->ddraw_caps.svb_fx_caps = fx_caps;
@@ -4775,7 +4661,6 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte
                                         WINEDDSCAPS_SYSTEMMEMORY            |
                                         WINEDDSCAPS_VIDEOMEMORY             |
                                         WINEDDSCAPS_VISIBLE;
-    caps->ddraw_caps.stride_align = DDRAW_PITCH_ALIGNMENT;
 
     if (!(wined3d->flags & WINED3D_NO3D))
     {
@@ -4880,11 +4765,14 @@ static void WINE_GLAPI diffuse_d3dcolor(const void *data)
 static void WINE_GLAPI specular_d3dcolor(const void *data)
 {
     DWORD specularColor = *((const DWORD *)data);
-    GLbyte d[] = {D3DCOLOR_B_R(specularColor),
-            D3DCOLOR_B_G(specularColor),
-            D3DCOLOR_B_B(specularColor)};
+    GLubyte d[] =
+    {
+        D3DCOLOR_B_R(specularColor),
+        D3DCOLOR_B_G(specularColor),
+        D3DCOLOR_B_B(specularColor)
+    };
 
-    specular_func_3ubv(d);
+    context_get_current()->gl_info->gl_ops.ext.p_glSecondaryColor3ubvEXT(d);
 }
 
 static void WINE_GLAPI warn_no_specular_func(const void *data)
@@ -4892,129 +4780,137 @@ static void WINE_GLAPI warn_no_specular_func(const void *data)
     WARN("GL_EXT_secondary_color not supported\n");
 }
 
-static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
+static void wined3d_adapter_init_ffp_attrib_ops(struct wined3d_adapter *adapter)
 {
-    position_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT3]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex3fv;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT4]      = position_float4;
-    position_funcs[WINED3D_FFP_EMIT_D3DCOLOR]    = position_d3dcolor;
-    position_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT4]      = (glAttribFunc)gl_info->gl_ops.gl.p_glVertex2sv;
-    position_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
-    position_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
-
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor3fv;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4]       = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4fv;
-    diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR]     = diffuse_d3dcolor;
-    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4]       = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4ubv;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N]      = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N]      = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4sv;
-    diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N]     = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N]     = (glAttribFunc)gl_info->gl_ops.gl.p_glColor4usv;
-    diffuse_funcs[WINED3D_FFP_EMIT_UDEC3]        = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_DEC3N]        = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2]    = invalid_func;
-    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4]    = invalid_func;
-
-    /* No 4 component entry points here */
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    const struct wined3d_gl_info *gl_info = &adapter->gl_info;
+    struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;
+    struct wined3d_ffp_attrib_ops *ops = &d3d_info->ffp_attrib_ops;
+
+    ops->position[WINED3D_FFP_EMIT_FLOAT1]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT2]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex3fv;
+    if (!d3d_info->xyzrhw)
+        ops->position[WINED3D_FFP_EMIT_FLOAT4]    = position_float4;
+    else
+        ops->position[WINED3D_FFP_EMIT_FLOAT4]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex4fv;
+    ops->position[WINED3D_FFP_EMIT_D3DCOLOR]  = position_d3dcolor;
+    ops->position[WINED3D_FFP_EMIT_UBYTE4]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT2]    = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT4]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glVertex2sv;
+    ops->position[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT2N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_SHORT4N]   = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_USHORT2N]  = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_USHORT4N]  = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_UDEC3]     = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_DEC3N]     = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+    ops->position[WINED3D_FFP_EMIT_INVALID]   = invalid_func;
+
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT1]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT2]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT3]     = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor3fv;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT4]     = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4fv;
+    ops->diffuse[WINED3D_FFP_EMIT_D3DCOLOR]   = diffuse_d3dcolor;
+    ops->diffuse[WINED3D_FFP_EMIT_UBYTE4]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT2]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT4]     = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_UBYTE4N]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4ubv;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT2N]    = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_SHORT4N]    = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4sv;
+    ops->diffuse[WINED3D_FFP_EMIT_USHORT2N]   = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_USHORT4N]   = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glColor4usv;
+    ops->diffuse[WINED3D_FFP_EMIT_UDEC3]      = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_DEC3N]      = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT16_2]  = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_FLOAT16_4]  = invalid_func;
+    ops->diffuse[WINED3D_FFP_EMIT_INVALID]    = invalid_func;
+
+    /* No 4 component entry points here. */
+    ops->specular[WINED3D_FFP_EMIT_FLOAT1]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT2]    = invalid_func;
     if (gl_info->supported[EXT_SECONDARY_COLOR])
-    {
-        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
-    }
+        ops->specular[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_attrib_func)GL_EXTCALL(glSecondaryColor3fvEXT);
     else
-    {
-        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = warn_no_specular_func;
-    }
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT4]      = invalid_func;
+        ops->specular[WINED3D_FFP_EMIT_FLOAT3]    = warn_no_specular_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT4]    = invalid_func;
     if (gl_info->supported[EXT_SECONDARY_COLOR])
+        ops->specular[WINED3D_FFP_EMIT_D3DCOLOR]  = specular_d3dcolor;
+    else
+        ops->specular[WINED3D_FFP_EMIT_D3DCOLOR]  = warn_no_specular_func;
+    ops->specular[WINED3D_FFP_EMIT_UBYTE4]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT2]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT4]    = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT2N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_SHORT4N]   = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_USHORT2N]  = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_USHORT4N]  = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_UDEC3]     = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_DEC3N]     = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+    ops->specular[WINED3D_FFP_EMIT_INVALID]   = invalid_func;
+
+    /* Only 3 component entry points here. Test how others behave. Float4
+     * normals are used by one of our tests, trying to pass it to the pixel
+     * shader, which fails on Windows. */
+    ops->normal[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT3]      = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glNormal3fv;
+    /* Just ignore the 4th value. */
+    ops->normal[WINED3D_FFP_EMIT_FLOAT4]      = (wined3d_ffp_attrib_func)gl_info->gl_ops.gl.p_glNormal3fv;
+    ops->normal[WINED3D_FFP_EMIT_D3DCOLOR]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT4]      = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
+    ops->normal[WINED3D_FFP_EMIT_INVALID]     = invalid_func;
+
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT1]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord1fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT2]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT3]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord3fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_FLOAT4]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4fvARB;
+    ops->texcoord[WINED3D_FFP_EMIT_D3DCOLOR]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_UBYTE4]    = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT2]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2svARB;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT4]    = (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4svARB;
+    ops->texcoord[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT2N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_SHORT4N]   = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_USHORT2N]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_USHORT4N]  = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_UDEC3]     = invalid_texcoord_func;
+    ops->texcoord[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
+    if (gl_info->supported[NV_HALF_FLOAT])
     {
-        specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
-        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
+        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT. */
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_2] =
+                (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord2hvNV;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_4] =
+                (wined3d_ffp_texcoord_func)gl_info->gl_ops.ext.p_glMultiTexCoord4hvNV;
     }
     else
     {
-        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
-    }
-    specular_funcs[WINED3D_FFP_EMIT_UBYTE4]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT2]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT4]      = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_UBYTE4N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT2N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_SHORT4N]     = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_USHORT2N]    = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_USHORT4N]    = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_UDEC3]       = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_DEC3N]       = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2]   = invalid_func;
-    specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4]   = invalid_func;
-
-    /* Only 3 component entry points here. Test how others behave. Float4 normals are used
-     * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
-     */
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT1]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT2]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT3]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT4]         = (glAttribFunc)gl_info->gl_ops.gl.p_glNormal3fv; /* Just ignore the 4th value */
-    normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UBYTE4]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT2]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT4]         = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UBYTE4N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT2N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_SHORT4N]        = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_USHORT2N]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_USHORT4N]       = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_UDEC3]          = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_DEC3N]          = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2]      = invalid_func;
-    normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4]      = invalid_func;
-
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4]    = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4]    = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N]   = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N]  = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3]     = invalid_texcoord_func;
-    multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N]     = invalid_texcoord_func;
-    if (gl_info->supported[NV_HALF_FLOAT])
-    {
-        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
-    } else {
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
-        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
+        ops->texcoord[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
     }
+    ops->texcoord[WINED3D_FFP_EMIT_INVALID]   = invalid_texcoord_func;
 }
 
 static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc)
 {
     const struct wined3d_gl_info *gl_info = &adapter->gl_info;
-    unsigned int i;
+    int i;
 
     if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
     {
@@ -5138,12 +5034,13 @@ static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc
     }
 }
 
-/* Do not call while under the GL lock. */
 static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
 {
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
-    struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
+    struct wined3d_caps_gl_ctx caps_gl_ctx = {0};
+    unsigned int ctx_attrib_idx = 0;
     DISPLAY_DEVICEW display_device;
+    GLint ctx_attribs[3];
 
     TRACE("adapter %p, ordinal %u.\n", adapter, ordinal);
 
@@ -5183,26 +5080,34 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
     TRACE("Allocated LUID %08x:%08x for adapter %p.\n",
             adapter->luid.HighPart, adapter->luid.LowPart, adapter);
 
-    if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
+    if (!wined3d_caps_gl_ctx_create(&caps_gl_ctx))
     {
         ERR("Failed to get a GL context for adapter %p.\n", adapter);
         return FALSE;
     }
 
+    if (context_debug_output_enabled(gl_info))
+    {
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB;
+        ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB;
+    }
+    ctx_attribs[ctx_attrib_idx] = 0;
+    wined3d_caps_gl_ctx_create_attribs(&caps_gl_ctx, gl_info, ctx_attribs);
+
     if (!wined3d_adapter_init_gl_caps(adapter))
     {
         ERR("Failed to initialize GL caps for adapter %p.\n", adapter);
-        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+        wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
         return FALSE;
     }
 
-    wined3d_adapter_init_fb_cfgs(adapter, fake_gl_ctx.dc);
+    wined3d_adapter_init_fb_cfgs(adapter, caps_gl_ctx.dc);
     /* We haven't found any suitable formats. This should only happen in
      * case of GDI software rendering, which is pretty useless anyway. */
     if (!adapter->cfg_count)
     {
         WARN("No suitable pixel formats found.\n");
-        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+        wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
         HeapFree(GetProcessHeap(), 0, adapter->cfgs);
         return FALSE;
     }
@@ -5210,23 +5115,23 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
     if (!wined3d_adapter_init_format_info(adapter))
     {
         ERR("Failed to initialize GL format info.\n");
-        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+        wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
         HeapFree(GetProcessHeap(), 0, adapter->cfgs);
         return FALSE;
     }
 
-    adapter->TextureRam = adapter->driver_info.vidmem;
-    adapter->UsedTextureRam = 0;
-    TRACE("Emulating %u MB of texture ram.\n", adapter->TextureRam / (1024 * 1024));
+    adapter->vram_bytes = adapter->driver_info.vram_bytes;
+    adapter->vram_bytes_used = 0;
+    TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->vram_bytes));
 
     display_device.cb = sizeof(display_device);
     EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
     TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName));
     strcpyW(adapter->DeviceName, display_device.DeviceName);
 
-    WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
+    wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
 
-    fillGLAttribFuncs(&adapter->gl_info);
+    wined3d_adapter_init_ffp_attrib_ops(adapter);
 
     return TRUE;
 }
@@ -5243,16 +5148,17 @@ static void wined3d_adapter_init_nogl(struct wined3d_adapter *adapter, UINT ordi
     adapter->driver_info.name = "Display";
     adapter->driver_info.description = "WineD3D DirectDraw Emulation";
     if (wined3d_settings.emulated_textureram)
-        adapter->TextureRam = wined3d_settings.emulated_textureram;
+        adapter->vram_bytes = wined3d_settings.emulated_textureram;
     else
-        adapter->TextureRam = 128 * 1024 * 1024;
+        adapter->vram_bytes = 128 * 1024 * 1024;
 
     initPixelFormatsNoGL(&adapter->gl_info);
 
+    adapter->vertex_pipe = &none_vertex_pipe;
     adapter->fragment_pipe = &none_fragment_pipe;
     adapter->shader_backend = &none_shader_backend;
     adapter->blitter = &cpu_blit;
-    
+
     display_device.cb = sizeof(display_device);
     EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
     TRACE("DeviceName: %s\n", debugstr_w(display_device.DeviceName));
@@ -5266,10 +5172,8 @@ const struct wined3d_parent_ops wined3d_null_parent_ops =
     wined3d_null_wined3d_object_destroyed,
 };
 
-/* Do not call while under the GL lock. */
-HRESULT wined3d_init(struct wined3d *wined3d, UINT version, DWORD flags)
+HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags)
 {
-    wined3d->dxVersion = version;
     wined3d->ref = 1;
     wined3d->flags = flags;