directx.c 221 KB
Newer Older
1 2 3 4 5 6
/*
 * IWineD3D implementation
 *
 * Copyright 2002-2004 Jason Edmeades
 * Copyright 2003-2004 Raphael Junqueira
 * Copyright 2004 Christian Costa
Oliver Stieber's avatar
Oliver Stieber committed
7
 * Copyright 2005 Oliver Stieber
8
 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 24 25 26 27 28 29 30
 */

#include "config.h"
#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);

31 32
#define GLINFO_LOCATION (*gl_info)

33 34 35
/* The d3d device ID */
static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };

36 37 38 39
/* Extension detection */
static const struct {
    const char *extension_string;
    GL_SupportedExt extension;
40
    DWORD version;
41 42
} EXTENSION_MAP[] = {
    /* APPLE */
43 44 45 46
    {"GL_APPLE_client_storage",             APPLE_CLIENT_STORAGE,           0                           },
    {"GL_APPLE_fence",                      APPLE_FENCE,                    0                           },
    {"GL_APPLE_flush_render",               APPLE_FLUSH_RENDER,             0                           },
    {"GL_APPLE_ycbcr_422",                  APPLE_YCBCR_422,                0                           },
47
    {"GL_APPLE_float_pixels",               APPLE_FLOAT_PIXELS,             0                           },
48 49

    /* ATI */
50 51 52
    {"GL_ATI_separate_stencil",             ATI_SEPARATE_STENCIL,           0                           },
    {"GL_ATI_texture_env_combine3",         ATI_TEXTURE_ENV_COMBINE3,       0                           },
    {"GL_ATI_texture_mirror_once",          ATI_TEXTURE_MIRROR_ONCE,        0                           },
53
    {"GL_ATI_fragment_shader",              ATI_FRAGMENT_SHADER,            0                           },
54
    {"GL_ATI_texture_compression_3dc",      ATI_TEXTURE_COMPRESSION_3DC,    0                           },
55 56

    /* ARB */
57
    {"GL_ARB_color_buffer_float",           ARB_COLOR_BUFFER_FLOAT,         0                           },
58
    {"GL_ARB_depth_buffer_float",           ARB_DEPTH_BUFFER_FLOAT,         0                           },
59
    {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE,              0                           },
60 61 62
    {"GL_ARB_draw_buffers",                 ARB_DRAW_BUFFERS,               0                           },
    {"GL_ARB_fragment_program",             ARB_FRAGMENT_PROGRAM,           0                           },
    {"GL_ARB_fragment_shader",              ARB_FRAGMENT_SHADER,            0                           },
63
    {"GL_ARB_geometry_shader4",             ARB_GEOMETRY_SHADER4,           0                           },
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    {"GL_ARB_half_float_pixel",             ARB_HALF_FLOAT_PIXEL,           0                           },
    {"GL_ARB_imaging",                      ARB_IMAGING,                    0                           },
    {"GL_ARB_multisample",                  ARB_MULTISAMPLE,                0                           }, /* needs GLX_ARB_MULTISAMPLE as well */
    {"GL_ARB_multitexture",                 ARB_MULTITEXTURE,               0                           },
    {"GL_ARB_occlusion_query",              ARB_OCCLUSION_QUERY,            0                           },
    {"GL_ARB_pixel_buffer_object",          ARB_PIXEL_BUFFER_OBJECT,        0                           },
    {"GL_ARB_point_parameters",             ARB_POINT_PARAMETERS,           0                           },
    {"GL_ARB_point_sprite",                 ARB_POINT_SPRITE,               0                           },
    {"GL_ARB_texture_border_clamp",         ARB_TEXTURE_BORDER_CLAMP,       0                           },
    {"GL_ARB_texture_compression",          ARB_TEXTURE_COMPRESSION,        0                           },
    {"GL_ARB_texture_cube_map",             ARB_TEXTURE_CUBE_MAP,           0                           },
    {"GL_ARB_texture_env_add",              ARB_TEXTURE_ENV_ADD,            0                           },
    {"GL_ARB_texture_env_combine",          ARB_TEXTURE_ENV_COMBINE,        0                           },
    {"GL_ARB_texture_env_dot3",             ARB_TEXTURE_ENV_DOT3,           0                           },
    {"GL_ARB_texture_float",                ARB_TEXTURE_FLOAT,              0                           },
    {"GL_ARB_texture_mirrored_repeat",      ARB_TEXTURE_MIRRORED_REPEAT,    0                           },
80
    {"GL_ARB_texture_non_power_of_two",     ARB_TEXTURE_NON_POWER_OF_TWO,   MAKEDWORD_VERSION(2, 0)     },
81
    {"GL_ARB_texture_rectangle",            ARB_TEXTURE_RECTANGLE,          0                           },
82
    {"GL_ARB_texture_rg",                   ARB_TEXTURE_RG,                 0                           },
83 84 85 86 87
    {"GL_ARB_vertex_blend",                 ARB_VERTEX_BLEND,               0                           },
    {"GL_ARB_vertex_buffer_object",         ARB_VERTEX_BUFFER_OBJECT,       0                           },
    {"GL_ARB_vertex_program",               ARB_VERTEX_PROGRAM,             0                           },
    {"GL_ARB_vertex_shader",                ARB_VERTEX_SHADER,              0                           },
    {"GL_ARB_shader_objects",               ARB_SHADER_OBJECTS,             0                           },
88
    {"GL_ARB_shader_texture_lod",           ARB_SHADER_TEXTURE_LOD,         0                           },
89
    {"GL_ARB_half_float_vertex",            ARB_HALF_FLOAT_VERTEX,          0                           },
90 91

    /* EXT */
92
    {"GL_EXT_blend_color",                  EXT_BLEND_COLOR,                0                           },
93
    {"GL_EXT_blend_minmax",                 EXT_BLEND_MINMAX,               0                           },
94 95
    {"GL_EXT_blend_equation_separate",      EXT_BLEND_EQUATION_SEPARATE,    0                           },
    {"GL_EXT_blend_func_separate",          EXT_BLEND_FUNC_SEPARATE,        0                           },
96 97
    {"GL_EXT_fog_coord",                    EXT_FOG_COORD,                  0                           },
    {"GL_EXT_framebuffer_blit",             EXT_FRAMEBUFFER_BLIT,           0                           },
98
    {"GL_EXT_framebuffer_multisample",      EXT_FRAMEBUFFER_MULTISAMPLE,    0                           },
99
    {"GL_EXT_framebuffer_object",           EXT_FRAMEBUFFER_OBJECT,         0                           },
100
    {"GL_EXT_packed_depth_stencil",         EXT_PACKED_DEPTH_STENCIL,       0                           },
101 102 103 104 105
    {"GL_EXT_paletted_texture",             EXT_PALETTED_TEXTURE,           0                           },
    {"GL_EXT_point_parameters",             EXT_POINT_PARAMETERS,           0                           },
    {"GL_EXT_secondary_color",              EXT_SECONDARY_COLOR,            0                           },
    {"GL_EXT_stencil_two_side",             EXT_STENCIL_TWO_SIDE,           0                           },
    {"GL_EXT_stencil_wrap",                 EXT_STENCIL_WRAP,               0                           },
106
    {"GL_EXT_texture3D",                    EXT_TEXTURE3D,                  MAKEDWORD_VERSION(1, 2)     },
107
    {"GL_EXT_texture_compression_s3tc",     EXT_TEXTURE_COMPRESSION_S3TC,   0                           },
108
    {"GL_EXT_texture_compression_rgtc",     EXT_TEXTURE_COMPRESSION_RGTC,   0                           },
109 110 111 112
    {"GL_EXT_texture_env_add",              EXT_TEXTURE_ENV_ADD,            0                           },
    {"GL_EXT_texture_env_combine",          EXT_TEXTURE_ENV_COMBINE,        0                           },
    {"GL_EXT_texture_env_dot3",             EXT_TEXTURE_ENV_DOT3,           0                           },
    {"GL_EXT_texture_sRGB",                 EXT_TEXTURE_SRGB,               0                           },
113
    {"GL_EXT_texture_swizzle",              EXT_TEXTURE_SWIZZLE,            0                           },
114 115 116
    {"GL_EXT_texture_filter_anisotropic",   EXT_TEXTURE_FILTER_ANISOTROPIC, 0                           },
    {"GL_EXT_texture_lod",                  EXT_TEXTURE_LOD,                0                           },
    {"GL_EXT_texture_lod_bias",             EXT_TEXTURE_LOD_BIAS,           0                           },
117
    {"GL_EXT_vertex_array_bgra",            EXT_VERTEX_ARRAY_BGRA,          0                           },
118
    {"GL_EXT_vertex_shader",                EXT_VERTEX_SHADER,              0                           },
119
    {"GL_EXT_gpu_program_parameters",       EXT_GPU_PROGRAM_PARAMETERS,     0                           },
120 121

    /* NV */
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    {"GL_NV_half_float",                    NV_HALF_FLOAT,                  0                           },
    {"GL_NV_fence",                         NV_FENCE,                       0                           },
    {"GL_NV_fog_distance",                  NV_FOG_DISTANCE,                0                           },
    {"GL_NV_fragment_program",              NV_FRAGMENT_PROGRAM,            0                           },
    {"GL_NV_fragment_program2",             NV_FRAGMENT_PROGRAM2,           0                           },
    {"GL_NV_register_combiners",            NV_REGISTER_COMBINERS,          0                           },
    {"GL_NV_register_combiners2",           NV_REGISTER_COMBINERS2,         0                           },
    {"GL_NV_texgen_reflection",             NV_TEXGEN_REFLECTION,           0                           },
    {"GL_NV_texture_env_combine4",          NV_TEXTURE_ENV_COMBINE4,        0                           },
    {"GL_NV_texture_shader",                NV_TEXTURE_SHADER,              0                           },
    {"GL_NV_texture_shader2",               NV_TEXTURE_SHADER2,             0                           },
    {"GL_NV_texture_shader3",               NV_TEXTURE_SHADER3,             0                           },
    {"GL_NV_occlusion_query",               NV_OCCLUSION_QUERY,             0                           },
    {"GL_NV_vertex_program",                NV_VERTEX_PROGRAM,              0                           },
    {"GL_NV_vertex_program1_1",             NV_VERTEX_PROGRAM1_1,           0                           },
    {"GL_NV_vertex_program2",               NV_VERTEX_PROGRAM2,             0                           },
138
    {"GL_NV_vertex_program2_option",        NV_VERTEX_PROGRAM2_OPTION,      0                           },
139
    {"GL_NV_vertex_program3",               NV_VERTEX_PROGRAM3,             0                           },
140
    {"GL_NV_fragment_program_option",       NV_FRAGMENT_PROGRAM_OPTION,     0                           },
141
    {"GL_NV_depth_clamp",                   NV_DEPTH_CLAMP,                 0                           },
142
    {"GL_NV_light_max_exponent",            NV_LIGHT_MAX_EXPONENT,          0                           },
143 144

    /* SGI */
145
    {"GL_SGIS_generate_mipmap",             SGIS_GENERATE_MIPMAP,           0                           },
146 147
};

148 149 150 151
/**********************************************************
 * Utility functions follow
 **********************************************************/

152
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
153 154 155 156
static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
        WINED3DDEVTYPE DeviceType);
static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
157

158
/* lookup tables */
159 160 161 162 163 164 165 166 167 168
const int minLookup[MAX_LOOKUPS] =
{
    WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
};

const int maxLookup[MAX_LOOKUPS] =
{
    WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
};

169 170
DWORD *stateLookup[MAX_LOOKUPS];

171 172 173 174 175 176 177
struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
{
    {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
    {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
    {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
    {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
178
};
179

180 181 182
GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
{
183 184
    GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
};
185

186
/* drawStridedSlow attributes */
187 188
glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
189
glAttribFunc specular_func_3ubv;
190 191 192
glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
193

194
/**
Austin English's avatar
Austin English committed
195 196 197
 * 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.
198
 */
199

200 201 202 203 204 205
struct wined3d_fake_gl_ctx
{
    HDC dc;
    HWND wnd;
    HGLRC gl_ctx;
};
206

207 208 209
static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
{
    TRACE_(d3d_caps)("Destroying fake GL context.\n");
210

211
    if (!pwglMakeCurrent(NULL, NULL))
212
    {
213
        ERR_(d3d_caps)("Failed to disable fake GL context.\n");
214
    }
215 216 217 218

    pwglDeleteContext(ctx->gl_ctx);
    ReleaseDC(ctx->wnd, ctx->dc);
    DestroyWindow(ctx->wnd);
219 220
}

221 222
static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
{
223 224
    PIXELFORMATDESCRIPTOR pfd;
    int iPixelFormat;
225

226
    TRACE("getting context...\n");
227

228
    /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
229
    ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
230
            WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
231
    if (!ctx->wnd)
232
    {
233
        ERR_(d3d_caps)("Failed to create a window.\n");
234 235
        goto fail;
    }
236

237 238
    ctx->dc = GetDC(ctx->wnd);
    if (!ctx->dc)
239
    {
240
        ERR_(d3d_caps)("Failed to get a DC.\n");
241 242
        goto fail;
    }
243

244 245 246 247 248 249 250 251 252
    /* PixelFormat selection */
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

253
    iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
254 255 256
    if (!iPixelFormat)
    {
        /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
257
        ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
258 259
        goto fail;
    }
260 261
    DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
    SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
262 263

    /* Create a GL context. */
264 265
    ctx->gl_ctx = pwglCreateContext(ctx->dc);
    if (!ctx->gl_ctx)
266 267 268 269
    {
        WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
        goto fail;
    }
270

271
    /* Make it the current GL context. */
272
    if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
273 274 275
    {
        ERR_(d3d_caps)("Failed to make fake GL context current.\n");
        goto fail;
276
    }
277
    context_set_last_device(NULL);
278 279

    return TRUE;
280 281 282 283 284 285 286 287 288

fail:
    if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
    ctx->gl_ctx = NULL;
    if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
    ctx->dc = NULL;
    if (ctx->wnd) DestroyWindow(ctx->wnd);
    ctx->wnd = NULL;

289
    return FALSE;
290 291
}

292 293
/* Adjust the amount of used texture memory */
long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
294
    struct WineD3DAdapter *adapter = D3DDevice->adapter;
295

296 297 298
    adapter->UsedTextureRam += glram;
    TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
    return adapter->UsedTextureRam;
299
}
300

301 302 303 304
/**********************************************************
 * IUnknown parts follows
 **********************************************************/

305
static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
306 307
{
    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
308

309
    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
310
    if (IsEqualGUID(riid, &IID_IUnknown)
311
        || IsEqualGUID(riid, &IID_IWineD3DBase)
312 313 314
        || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
        IUnknown_AddRef(iface);
        *ppobj = This;
315
        return S_OK;
316
    }
317
    *ppobj = NULL;
318 319 320
    return E_NOINTERFACE;
}

321
static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
322 323 324
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    ULONG refCount = InterlockedIncrement(&This->ref);

325
    TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
326 327 328
    return refCount;
}

329
static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
330 331
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    ULONG ref;
332
    TRACE("(%p) : Releasing from %d\n", This, This->ref);
333 334
    ref = InterlockedDecrement(&This->ref);
    if (ref == 0) {
335 336 337 338 339 340
        unsigned int i;

        for (i = 0; i < This->adapter_count; ++i)
        {
            HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
        }
341 342
        HeapFree(GetProcessHeap(), 0, This);
    }
343

344 345 346
    return ref;
}

347 348 349
/* Set the shader type for this device, depending on the given capabilities,
 * the device type, and the user preferences in wined3d_settings */

350
static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
351
{
352
    if (wined3d_settings.vs_mode == VS_NONE) {
353
        *vs_selected = SHADER_NONE;
354
    } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
355 356 357
        /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
         * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
         * shaders only on this card. */
358
        if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
359 360 361
            *vs_selected = SHADER_ARB;
        else
            *vs_selected = SHADER_GLSL;
362
    } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
363
        *vs_selected = SHADER_ARB;
364
    } else {
365
        *vs_selected = SHADER_NONE;
366
    }
367

368
    if (wined3d_settings.ps_mode == PS_NONE) {
369
        *ps_selected = SHADER_NONE;
370
    } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
371
        *ps_selected = SHADER_GLSL;
372
    } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
373
        *ps_selected = SHADER_ARB;
374 375
    } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
        *ps_selected = SHADER_ATI;
376
    } else {
377
        *ps_selected = SHADER_NONE;
378
    }
379 380
}

381
/** Select the number of report maximum shader constants based on the selected shader modes */
382
static void select_shader_max_constants(
383 384 385
    int ps_selected_mode,
    int vs_selected_mode,
    WineD3D_GL_Info *gl_info) {
386

387
    switch (vs_selected_mode) {
388
        case SHADER_GLSL:
389
            gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
390 391
            break;
        case SHADER_ARB:
392
            gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
393 394 395 396 397 398
            break;
        default:
            gl_info->max_vshader_constantsF = 0;
            break;
    }

399
    switch (ps_selected_mode) {
400
        case SHADER_GLSL:
401
            gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
402 403
            break;
        case SHADER_ARB:
404
            gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
405 406 407 408 409 410 411
            break;
        default:
            gl_info->max_pshader_constantsF = 0;
            break;
    }
}

412 413 414 415
/**********************************************************
 * IWineD3D parts follows
 **********************************************************/

416
/* GL locking is done by the caller */
417 418
static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
{
419 420 421 422 423 424
    GLuint prog;
    BOOL ret = FALSE;
    const char *testcode =
        "!!ARBvp1.0\n"
        "PARAM C[66] = { program.env[0..65] };\n"
        "ADDRESS A0;"
425 426
        "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
        "ARL A0.x, zero.x;\n"
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
        "MOV result.position, C[A0.x + 65];\n"
        "END\n";

    while(glGetError());
    GL_EXTCALL(glGenProgramsARB(1, &prog));
    if(!prog) {
        ERR("Failed to create an ARB offset limit test program\n");
    }
    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
    GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
                                  strlen(testcode), testcode));
    if(glGetError() != 0) {
        TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
        TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
        ret = TRUE;
    } else TRACE("OpenGL implementation allows offsets > 63\n");

    GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
    GL_EXTCALL(glDeleteProgramsARB(1, &prog));
446
    checkGLcall("ARB vp offset limit test cleanup");
447 448 449 450

    return ret;
}

451 452 453 454 455 456 457 458 459 460 461
static DWORD ver_for_ext(GL_SupportedExt ext)
{
    unsigned int i;
    for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
        if(EXTENSION_MAP[i].extension == ext) {
            return EXTENSION_MAP[i].version;
        }
    }
    return 0;
}

462 463 464 465 466 467 468 469
static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
    if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
    if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
    if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
    return FALSE;
}
470

471 472 473
static BOOL match_geforce5(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    if (gl_info->gl_vendor == VENDOR_NVIDIA)
474
    {
475 476 477 478
        if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600)
        {
            return TRUE;
        }
479
    }
480 481
    return FALSE;
}
482

483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
static BOOL match_apple(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
     * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
     * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
     *
     * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
     * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
     * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
     * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
     * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
     * the chance that other implementations support them is rather small since Win32 QuickTime uses
     * DirectDraw, not OpenGL. */
    if (gl_info->supported[APPLE_FENCE]
            && gl_info->supported[APPLE_CLIENT_STORAGE]
            && gl_info->supported[APPLE_FLUSH_RENDER]
            && gl_info->supported[APPLE_YCBCR_422])
500
    {
501 502 503
        TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported.\n");
        TRACE_(d3d_caps)("Activating MacOS fixups.\n");
        return TRUE;
504 505 506
    }
    else
    {
507 508 509
        TRACE_(d3d_caps)("Apple extensions are not supported.\n");
        TRACE_(d3d_caps)("Not activating MacOS fixups.\n");
        return FALSE;
510
    }
511
}
512

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
/* Context activation is done by the caller. */
static void test_pbo_functionality(WineD3D_GL_Info *gl_info)
{
    /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
     * but glTexSubImage from a PBO fails miserably, with the first line repeated over
     * all the texture. This function detects this bug by its symptom and disables PBOs
     * if the test fails.
     *
     * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
     * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
     * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
     * read back is compared to the original. If they are equal PBOs are assumed to work,
     * otherwise the PBO extension is disabled. */
    GLuint texture, pbo;
    static const unsigned int pattern[] =
528
    {
529 530 531 532 533 534
        0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
        0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
        0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
        0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
    };
    unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
535

536 537
    /* No PBO -> No point in testing them. */
    if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
538

539
    ENTER_GL();
540

541 542 543
    while (glGetError());
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
544

545 546
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
547
    checkGLcall("Specifying the PBO test texture");
548

549 550 551
    GL_EXTCALL(glGenBuffersARB(1, &pbo));
    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
    GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
552
    checkGLcall("Specifying the PBO test pbo");
553

554
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
555
    checkGLcall("Loading the PBO test texture");
556

557 558
    GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
    glFinish(); /* just to be sure */
559

560 561
    memset(check, 0, sizeof(check));
    glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
562
    checkGLcall("Reading back the PBO test texture");
563

564 565
    glDeleteTextures(1, &texture);
    GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
566
    checkGLcall("PBO test cleanup");
567

568
    LEAVE_GL();
569

570 571 572 573 574 575 576 577 578 579 580
    if (memcmp(check, pattern, sizeof(check)))
    {
        WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
        WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
        gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
    }
    else
    {
        TRACE_(d3d_caps)("PBO test successful.\n");
    }
}
581

582 583 584 585
static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer);
}
586

587 588 589 590 591 592 593
static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    if (!match_apple(gl_info, gl_renderer)) return FALSE;
    if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
    if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
    return TRUE;
}
594

595 596 597 598 599 600 601
static BOOL match_fglrx(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
    if (match_apple(gl_info, gl_renderer)) return FALSE;
    if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
    return TRUE;
}
602

603 604 605 606 607 608 609 610 611 612 613
static BOOL match_dx10_capable(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    /* 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
     * hardcoded
     *
     * dx10 cards usually have 64 varyings */
    return gl_info->max_glsl_varyings > 44;
}
614

615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
/* A GL context is provided by the caller */
static BOOL match_allows_spec_alpha(const WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    GLenum error;
    DWORD data[16];

    if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE;

    ENTER_GL();
    while(glGetError());
    GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
    error = glGetError();
    LEAVE_GL();

    if(error == GL_NO_ERROR)
    {
        TRACE("GL Implementation accepts 4 component specular color pointers\n");
        return TRUE;
    }
    else
    {
        TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
              debug_glerror(error));
        return FALSE;
    }
}

642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
static void quirk_arb_constants(WineD3D_GL_Info *gl_info)
{
    TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF);
    gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
    TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF);
    gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
}

static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info)
{
    quirk_arb_constants(gl_info);
    /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
     * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
     * allow 48 different offsets or other helper immediate values. */
    TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
    gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
}

/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
 * most games, but avoids the crash
 *
 * A more sophisticated way would be to find all units that need texture coordinates and enable
 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
 *
 * Note that disabling the extension entirely does not gain predictability because there is no point
 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info)
{
    if (gl_info->supported[ARB_POINT_SPRITE])
    {
        TRACE("Limiting point sprites to one texture unit.\n");
        gl_info->max_point_sprite_units = 1;
    }
}

static void quirk_ati_dx9(WineD3D_GL_Info *gl_info)
{
    quirk_arb_constants(gl_info);

    /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
     * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
     * If real NP2 textures are used, the driver falls back to software. We could just remove the
     * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
     * due to the non-normalized texture coordinates. Thus set an internal extension flag,
     * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
     * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
     *
     * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
     * has this extension promoted to core. The extension loading code sets this extension supported
     * due to that, so this code works on fglrx as well. */
    TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
    gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
    gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;

    /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
     * it is generally more efficient. Reserve just 8 constants. */
    TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
    gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
}

static void quirk_no_np2(WineD3D_GL_Info *gl_info)
{
    /*  The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
     *  doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
     *  This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
     *  within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
     *  FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
     *  We therefore completely remove ARB_tex_npot from the list of supported extensions.
     *
     *  Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
     *  triggering the software fallback. There is not much we can do here apart from disabling the
     *  software-emulated extension and reenable ARB_tex_rect (which was previously disabled
     *  in IWineD3DImpl_FillGLCaps).
     *  This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
     *  post-processing effects in the game "Max Payne 2").
     *  The behaviour can be verified through a simple test app attached in bugreport #14724. */
    TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
    gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
    gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
}

static void quirk_texcoord_w(WineD3D_GL_Info *gl_info)
{
    /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
     * with fixed function fragment processing. Ideally this flag should be detected with a test shader
     * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
     * do not like vertex shaders in feedback mode and return an error, even though it should be valid
     * according to the spec.
     *
     * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
     * makes the shader slower and eats instruction slots which should be available to the d3d app.
     *
     * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
     * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
     * this workaround is activated on cards that do not need it, it won't break things, just affect
     * performance negatively. */
    TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
    gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
}

static void quirk_clip_varying(WineD3D_GL_Info *gl_info)
{
    gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
}

751 752 753 754 755
static void quirk_allows_specular_alpha(WineD3D_GL_Info *gl_info)
{
    gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
}

756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
struct driver_quirk
{
    BOOL (*match)(const WineD3D_GL_Info *gl_info, const char *gl_renderer);
    void (*apply)(WineD3D_GL_Info *gl_info);
    const char *description;
};

struct driver_quirk quirk_table[] =
{
    {
        match_ati_r300_to_500,
        quirk_ati_dx9,
        "ATI GLSL constant and normalized texrect quirk"
    },
    /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
     * used it falls back to software. While the compiler can detect if the shader uses all declared
     * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
     * using relative addressing falls back to software.
     *
     * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
    {
        match_apple,
        quirk_apple_glsl_constants,
        "Apple GLSL uniform override"
    },
    {
        match_geforce5,
        quirk_no_np2,
        "Geforce 5 NP2 disable"
    },
    {
        match_apple_intel,
        quirk_texcoord_w,
        "Init texcoord .w for Apple Intel GPU driver"
    },
    {
        match_apple_nonr500ati,
        quirk_texcoord_w,
        "Init texcoord .w for Apple ATI >= r600 GPU driver"
    },
    {
        match_fglrx,
        quirk_one_point_sprite,
        "Fglrx point sprite crash workaround"
    },
    {
        match_dx10_capable,
        quirk_clip_varying,
        "Reserved varying for gl_ClipPos"
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
    },
    {
        /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
         * GL implementations accept it. The Mac GL is the only implementation known to
         * reject it.
         *
         * If we can pass 4 component specular colors, do it, because (a) we don't have
         * to screw around with the data, and (b) the D3D fixed function vertex pipeline
         * passes specular alpha to the pixel shader if any is used. Otherwise the
         * specular alpha is used to pass the fog coordinate, which we pass to opengl
         * via GL_EXT_fog_coord.
         */
        match_allows_spec_alpha,
        quirk_allows_specular_alpha,
        "Allow specular alpha quirk"
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
    }
};

/* Certain applications (Steam) complain if we report an outdated driver version. In general,
 * reporting a driver version is moot because we are not the Windows driver, and we have different
 * bugs, features, etc.
 *
 * If a card is not found in this table, the GL driver version is reported. */
struct driver_version_information
{
    WORD vendor;                    /* reported PCI card vendor ID  */
    WORD card;                      /* reported PCI card device ID  */
    const char *description;        /* Description of the card e.g. NVIDIA RIVA TNT */
    WORD hipart_hi, hipart_lo;      /* driver hiword to report      */
    WORD lopart_hi, lopart_lo;      /* driver loword to report      */
};

static const struct driver_version_information driver_version_table[] =
{
    /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
     * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown
     * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
     * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
     *
     * All version numbers used below are from the Linux nvidia drivers. */
    {VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT,           "NVIDIA RIVA TNT",                  7,  1,  8,  6      },
    {VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT2,          "NVIDIA RIVA TNT2/TNT2 Pro",        7,  1,  8,  6      },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE,            "NVIDIA GeForce 256",               7,  1,  8,  6      },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2_MX,        "NVIDIA GeForce2 MX/MX 400",        9,  6,  4,  3      },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2,           "NVIDIA GeForce2 GTS/GeForce2 Pro", 7,  1,  8,  6      },
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE3,           "NVIDIA GeForce3",                  9,  6,  10, 9371   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_MX,        "NVIDIA GeForce4 MX 460",           9,  6,  10, 9371   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_TI4200,    "NVIDIA GeForce4 Ti 4200",          9,  6,  10, 9371   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5200,     "NVIDIA GeForce FX 5200",           7,  15, 11, 7516   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5600,     "NVIDIA GeForce FX 5600",           7,  15, 11, 7516   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5800,     "NVIDIA GeForce FX 5800",           7,  15, 11, 7516   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6200,       "NVIDIA GeForce 6200",              7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6600GT,     "NVIDIA GeForce 6600 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6800,       "NVIDIA GeForce 6800",              7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7300,       "NVIDIA GeForce Go 7300",           7,  15, 11, 8585   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7400,       "NVIDIA GeForce Go 7400",           7,  15, 11, 8585   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7600,       "NVIDIA GeForce 7600 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7800GT,     "NVIDIA GeForce 7800 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8300GS,     "NVIDIA GeForce 8300 GS",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600GT,     "NVIDIA GeForce 8600 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600MGT,    "NVIDIA GeForce 8600M GT",          7,  15, 11, 8585   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8800GTS,    "NVIDIA GeForce 8800 GTS",          7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9200,       "NVIDIA GeForce 9200",              7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9400GT,     "NVIDIA GeForce 9400 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9500GT,     "NVIDIA GeForce 9500 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9600GT,     "NVIDIA GeForce 9600 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9800GT,     "NVIDIA GeForce 9800 GT",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX260,     "NVIDIA GeForce GTX 260",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX275,     "NVIDIA GeForce GTX 275",           7,  15, 11, 8618   },
    {VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX280,     "NVIDIA GeForce GTX 280",           7,  15, 11, 8618   },
875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918

    /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
    {VENDOR_ATI,        CARD_ATI_RADEON_9500,           "ATI Radeon 9500",                  6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_X700,           "ATI Radeon X700 SE",               6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_X1600,          "ATI Radeon X1600 Series",          6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD2300,         "ATI Mobility Radeon HD 2300",      6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD4350,         "ATI Radeon HD 4350",               6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD4700,         "ATI Radeon HD 4700 Series",        6,  14, 10, 6764    },
    {VENDOR_ATI,        CARD_ATI_RADEON_HD4800,         "ATI Radeon HD 4800 Series",        6,  14, 10, 6764    },

    /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
};

/* Context activation is done by the caller. */
static void fixup_extensions(WineD3D_GL_Info *gl_info, const char *gl_renderer)
{
    unsigned int i;

    for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
    {
        if (!quirk_table[i].match(gl_info, gl_renderer)) continue;
        TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
        quirk_table[i].apply(gl_info);
    }

    /* Find out if PBOs work as they are supposed to. */
    test_pbo_functionality(gl_info);

    /* Fixup the driver version */
    for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
    {
        if (gl_info->gl_vendor == driver_version_table[i].vendor
                && gl_info->gl_card == driver_version_table[i].card)
        {
            TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB.\n",
                    gl_info->gl_vendor, gl_info->gl_card);

            gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
                    driver_version_table[i].lopart_lo);
            gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
                    driver_version_table[i].hipart_lo);
919
            gl_info->driver_description = driver_version_table[i].description;
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
            break;
        }
    }
}

/* Context activation is done by the caller. */
static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
    const char *GL_Extensions    = NULL;
    const char *WGL_Extensions   = NULL;
    const char *gl_string        = NULL;
    const char *gl_string_cursor = NULL;
    GLint       gl_max;
    GLfloat     gl_floatv[2];
    int         major = 1, minor = 0;
    unsigned    i;
    HDC         hdc;
    unsigned int vidmem=0;
    char *gl_renderer;
    DWORD gl_version;
    size_t len;

    TRACE_(d3d_caps)("(%p)\n", gl_info);

    ENTER_GL();

    gl_string = (const char *)glGetString(GL_RENDERER);
    TRACE_(d3d_caps)("GL_RENDERER: %s.\n", gl_string);
    if (!gl_string)
    {
        ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
        return FALSE;
    }

    len = strlen(gl_string) + 1;
    gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
    if (!gl_renderer)
    {
        ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
        return FALSE;
    }
    memcpy(gl_renderer, gl_string, len);

    gl_string = (const char *)glGetString(GL_VENDOR);
    TRACE_(d3d_caps)("GL_VENDOR: %s.\n", gl_string);
    if (!gl_string)
    {
        ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
        HeapFree(GetProcessHeap(), 0, gl_renderer);
        return FALSE;
    }

    /* Fill in the GL vendor */
    if (strstr(gl_string, "NVIDIA"))
    {
        gl_info->gl_vendor = VENDOR_NVIDIA;
    }
    else if (strstr(gl_string, "ATI"))
    {
        gl_info->gl_vendor = VENDOR_ATI;
    }
    else if (strstr(gl_string, "Intel(R)")
            || strstr(gl_renderer, "Intel(R)")
            || strstr(gl_string, "Intel Inc."))
    {
        gl_info->gl_vendor = VENDOR_INTEL;
    }
    else if (strstr(gl_string, "Mesa"))
    {
        gl_info->gl_vendor = VENDOR_MESA;
    }
    else
    {
        FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Setting VENDOR_WINE.\n", gl_string);
        gl_info->gl_vendor = VENDOR_WINE;
    }
    TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);

    /* Parse the GL_VERSION field into major and minor information */
    gl_string = (const char *)glGetString(GL_VERSION);
    TRACE_(d3d_caps)("GL_VERSION: %s.\n", gl_string);
    if (!gl_string)
    {
        ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
        HeapFree(GetProcessHeap(), 0, gl_renderer);
        return FALSE;
    }

    /* First, parse the generic opengl version. This is supposed not to be
     * convoluted with driver specific information. */
    gl_string_cursor = gl_string;

    major = atoi(gl_string_cursor);
    if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
    while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
    if (*gl_string_cursor++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_string));

    minor = atoi(gl_string_cursor);
    TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
    gl_version = MAKEDWORD_VERSION(major, minor);

    /* Now parse the driver specific string which we'll report to the app. */
    switch (gl_info->gl_vendor)
    {
        case VENDOR_NVIDIA:
            gl_string_cursor = strstr(gl_string, "NVIDIA");
            if (!gl_string_cursor)
            {
                ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
                break;
            }

            gl_string_cursor = strstr(gl_string_cursor, " ");
            if (!gl_string_cursor)
            {
                ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
                break;
            }

            while (*gl_string_cursor == ' ') ++gl_string_cursor;

            if (!*gl_string_cursor)
            {
                ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
                break;
            }

            major = atoi(gl_string_cursor);
            while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;

            if (*gl_string_cursor++ != '.')
            {
                ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
                break;
            }

            minor = atoi(gl_string_cursor);
            minor = major * 100 + minor;
            major = 10;
            break;

        case VENDOR_ATI:
            major = minor = 0;
            gl_string_cursor = strchr(gl_string, '-');
            if (gl_string_cursor)
            {
                ++gl_string_cursor;

                /* Check if version number is of the form x.y.z. */
                if (*gl_string_cursor < '0' || *gl_string_cursor > '9'
                        || gl_string_cursor[1] != '.'
                        || gl_string_cursor[2] < '0' || gl_string_cursor[2] > '9'
                        || gl_string_cursor[3] != '.'
                        || gl_string_cursor[4] < '0' || gl_string_cursor[4] > '9')
                    /* Mark version number as malformed. */
                    gl_string_cursor = 0;
            }

            if (!gl_string_cursor)
            {
                WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
            }
            else
            {
                major = *gl_string_cursor - '0';
                minor = (gl_string_cursor[2] - '0') * 256 + (gl_string_cursor[4] - '0');
            }
            break;

        case VENDOR_INTEL:
            /* Apple and Mesa version strings look differently, but both provide intel drivers. */
            if (strstr(gl_string, "APPLE"))
            {
                /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
                 * We only need the first part, and use the APPLE as identification
                 * "1.2 APPLE-1.4.56". */
                gl_string_cursor = gl_string;
                major = atoi(gl_string_cursor);
                while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;

                if (*gl_string_cursor++ != '.')
                {
                    ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s.\n", debugstr_a(gl_string));
                    break;
                }

                minor = atoi(gl_string_cursor);
                break;
            }
            /* Fallthrough */
1109

1110 1111 1112 1113
        case VENDOR_MESA:
            gl_string_cursor = strstr(gl_string, "Mesa");
            gl_string_cursor = strstr(gl_string_cursor, " ");
            while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
1114 1115
            if (*gl_string_cursor)
            {
1116 1117 1118
                char tmp[16];
                int cursor = 0;

1119 1120
                while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
                {
1121 1122 1123 1124 1125 1126
                    tmp[cursor++] = *gl_string_cursor;
                    ++gl_string_cursor;
                }
                tmp[cursor] = 0;
                major = atoi(tmp);

1127
                if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
1128 1129 1130
                ++gl_string_cursor;

                cursor = 0;
1131 1132
                while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
                {
1133 1134 1135 1136 1137 1138 1139 1140
                    tmp[cursor++] = *gl_string_cursor;
                    ++gl_string_cursor;
                }
                tmp[cursor] = 0;
                minor = atoi(tmp);
            }
            break;

1141 1142 1143
        default:
            major = 0;
            minor = 9;
1144
            break;
1145 1146
    }

1147 1148 1149 1150 1151 1152
    gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
    TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x).\n",
            debugstr_a(gl_string), major, minor, gl_info->driver_version);
    /* Current Windows drivers have versions like 6.14.... (some older have an earlier version). */
    gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);

1153 1154 1155 1156
    /*
     * Initialize openGL extension related variables
     *  with Default values
     */
1157
    memset(gl_info->supported, 0, sizeof(gl_info->supported));
1158
    gl_info->max_buffers        = 1;
1159 1160
    gl_info->max_textures       = 1;
    gl_info->max_texture_stages = 1;
1161
    gl_info->max_fragment_samplers = 1;
1162
    gl_info->max_vertex_samplers = 0;
1163
    gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
1164
    gl_info->max_sampler_stages = 1;
1165
    gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
1166 1167
    gl_info->ps_arb_max_temps = 0;
    gl_info->ps_arb_max_instructions = 0;
1168
    gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
1169 1170
    gl_info->vs_arb_max_temps = 0;
    gl_info->vs_arb_max_instructions = 0;
1171 1172
    gl_info->vs_nv_version  = VS_VERSION_NOT_SUPPORTED;
    gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
1173 1174 1175 1176
    gl_info->vs_glsl_constantsF = 0;
    gl_info->ps_glsl_constantsF = 0;
    gl_info->vs_arb_constantsF = 0;
    gl_info->ps_arb_constantsF = 0;
1177
    gl_info->ps_arb_max_local_constants = 0;
1178 1179 1180

    /* Retrieve opengl defaults */
    glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1181
    gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1182 1183 1184 1185 1186 1187
    TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);

    glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
    gl_info->max_lights = gl_max;
    TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);

1188 1189 1190 1191
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
    gl_info->max_texture_size = gl_max;
    TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);

1192
    glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1193
    gl_info->max_pointsizemin = gl_floatv[0];
1194 1195
    gl_info->max_pointsize = gl_floatv[1];
    TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1196

1197 1198 1199 1200 1201
    /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
    GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
    if (!GL_Extensions)
    {
        ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1202
        HeapFree(GetProcessHeap(), 0, gl_renderer);
1203 1204 1205
        return FALSE;
    }

1206 1207
    TRACE_(d3d_caps)("GL_Extensions reported:\n");

1208
    gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1209

1210 1211 1212 1213
    while (*GL_Extensions)
    {
        const char *start;
        char current_ext[256];
1214

1215 1216 1217
        while (isspace(*GL_Extensions)) ++GL_Extensions;
        start = GL_Extensions;
        while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1218

1219 1220
        len = GL_Extensions - start;
        if (!len || len >= sizeof(current_ext)) continue;
1221

1222 1223 1224
        memcpy(current_ext, start, len);
        current_ext[len] = '\0';
        TRACE_(d3d_caps)("- %s\n", current_ext);
1225

1226 1227 1228 1229 1230 1231 1232
        for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
        {
            if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
            {
                TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
                gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
                break;
1233 1234
            }
        }
1235
    }
1236

1237
    LEAVE_GL();
1238

1239 1240 1241 1242 1243
    /* Now work out what GL support this card really has */
#define USE_GL_FUNC(type, pfn, ext, replace) \
{ \
    DWORD ver = ver_for_ext(ext); \
    if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1244
    else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1245 1246 1247
    else gl_info->pfn = NULL; \
}
    GL_EXT_FUNCS_GEN;
1248 1249
#undef USE_GL_FUNC

1250 1251
#define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
    WGL_EXT_FUNCS_GEN;
1252
#undef USE_GL_FUNC
1253

1254
    ENTER_GL();
1255

1256 1257 1258 1259 1260 1261
    /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
     * loading the functions, otherwise the code above will load the extension entry points instead of the
     * core functions, which may not work. */
    for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
    {
        if (!gl_info->supported[EXTENSION_MAP[i].extension]
1262
                && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1263 1264 1265
        {
            TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
            gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1266
        }
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
    }

    if (gl_info->supported[APPLE_FENCE])
    {
        /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
         * The apple extension interacts with some other apple exts. Disable the NV
         * extension if the apple one is support to prevent confusion in other parts
         * of the code. */
        gl_info->supported[NV_FENCE] = FALSE;
    }
    if (gl_info->supported[APPLE_FLOAT_PIXELS])
    {
        /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
         *
         * The enums are the same:
         * GL_RGBA16F_ARB     = GL_RGBA_FLOAT16_APPLE = 0x881A
         * GL_RGB16F_ARB      = GL_RGB_FLOAT16_APPLE  = 0x881B
         * GL_RGBA32F_ARB     = GL_RGBA_FLOAT32_APPLE = 0x8814
         * GL_RGB32F_ARB      = GL_RGB_FLOAT32_APPLE  = 0x8815
         * GL_HALF_FLOAT_ARB  = GL_HALF_APPLE         = 0x140B
         */
        if (!gl_info->supported[ARB_TEXTURE_FLOAT])
        {
            TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
            gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1292
        }
1293 1294 1295 1296
        if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
        {
            TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
            gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1297
        }
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
    }
    if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
    {
        TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
        gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
    }
    if (gl_info->supported[NV_TEXTURE_SHADER2])
    {
        if (gl_info->supported[NV_REGISTER_COMBINERS])
        {
            /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
             * are supported. The nv extensions provide the same functionality as the
             * ATI one, and a bit more(signed pixelformats). */
            gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1312
        }
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
    }
    if (gl_info->supported[ARB_DRAW_BUFFERS])
    {
        glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
        gl_info->max_buffers = gl_max;
        TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
    }
    if (gl_info->supported[ARB_MULTITEXTURE])
    {
        glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
        gl_info->max_textures = min(MAX_TEXTURES, gl_max);
        TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures);

        if (gl_info->supported[NV_REGISTER_COMBINERS])
        {
            GLint tmp;
            glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
            gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
1331
        }
1332 1333 1334
        else
        {
            gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
1335
        }
1336 1337 1338 1339 1340 1341 1342
        TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages);

        if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
        {
            GLint tmp;
            glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
            gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1343
        }
1344 1345 1346
        else
        {
            gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
1347
        }
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382
        TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers);

        if (gl_info->supported[ARB_VERTEX_SHADER])
        {
            GLint tmp;
            glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
            gl_info->max_vertex_samplers = tmp;
            glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
            gl_info->max_combined_samplers = tmp;

            /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
             * is known at shader link time. In a vertex shader + pixel shader combination this isn't
             * an issue because then the sampler setup only depends on the two shaders. If a pixel
             * shader is used with fixed function vertex processing we're fine too because fixed function
             * vertex processing doesn't use any samplers. If fixed function fragment processing is
             * used we have to make sure that all vertex sampler setups are valid together with all
             * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
             * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
             * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
             * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
             * a fixed function pipeline anymore.
             *
             * So this is just a check to check that our assumption holds true. If not, write a warning
             * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
            if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12
                    && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers)
            {
                FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
                        gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
                FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
                if (gl_info->max_combined_samplers > MAX_TEXTURES)
                    gl_info->max_vertex_samplers = gl_info->max_combined_samplers - MAX_TEXTURES;
                else
                    gl_info->max_vertex_samplers = 0;
            }
1383
        }
1384 1385 1386
        else
        {
            gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
1387
        }
1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
        TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers);
        TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers);
    }
    if (gl_info->supported[ARB_VERTEX_BLEND])
    {
        glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
        gl_info->max_blends = gl_max;
        TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends);
    }
    if (gl_info->supported[EXT_TEXTURE3D])
    {
        glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
        gl_info->max_texture3d_size = gl_max;
        TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size);
    }
    if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
    {
        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
        gl_info->max_anisotropy = gl_max;
        TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy);
    }
    if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
    {
        gl_info->ps_arb_version = PS_VERSION_11;
        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
        gl_info->ps_arb_constantsF = gl_max;
        TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF);
        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
        gl_info->ps_arb_max_temps = gl_max;
        TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps);
        GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
        gl_info->ps_arb_max_instructions = gl_max;
        TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions);
    }
    if (gl_info->supported[ARB_VERTEX_PROGRAM])
    {
        gl_info->vs_arb_version = VS_VERSION_11;
        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
        gl_info->vs_arb_constantsF = gl_max;
        TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF);
        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
        gl_info->vs_arb_max_temps = gl_max;
        TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps);
        GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
        gl_info->vs_arb_max_instructions = gl_max;
        TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions);

        if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
    }
    if (gl_info->supported[ARB_VERTEX_SHADER])
    {
        glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
        gl_info->vs_glsl_constantsF = gl_max / 4;
        TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF);
    }
    if (gl_info->supported[ARB_FRAGMENT_SHADER])
    {
        glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
        gl_info->ps_glsl_constantsF = gl_max / 4;
        TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF);
        glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
        gl_info->max_glsl_varyings = gl_max;
        TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
    }
    if (gl_info->supported[EXT_VERTEX_SHADER])
    {
        gl_info->vs_ati_version = VS_VERSION_11;
    }
    if (gl_info->supported[NV_VERTEX_PROGRAM3])
    {
        gl_info->vs_nv_version = VS_VERSION_30;
    }
    else if (gl_info->supported[NV_VERTEX_PROGRAM2])
    {
        gl_info->vs_nv_version = VS_VERSION_20;
    }
    else if (gl_info->supported[NV_VERTEX_PROGRAM1_1])
    {
        gl_info->vs_nv_version = VS_VERSION_11;
    }
    else if (gl_info->supported[NV_VERTEX_PROGRAM])
    {
        gl_info->vs_nv_version = VS_VERSION_10;
    }
    if (gl_info->supported[NV_FRAGMENT_PROGRAM2])
    {
        gl_info->ps_nv_version = PS_VERSION_30;
    }
    else if (gl_info->supported[NV_FRAGMENT_PROGRAM])
    {
        gl_info->ps_nv_version = PS_VERSION_20;
    }
    if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
    {
        glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
    }
    else
    {
1486
        gl_info->max_shininess = 128.0f;
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519
    }
    if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
    {
        /* If we have full NP2 texture support, disable
         * GL_ARB_texture_rectangle because we will never use it.
         * This saves a few redundant glDisable calls. */
        gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
    }
    if (gl_info->supported[ATI_FRAGMENT_SHADER])
    {
        /* Disable NV_register_combiners and fragment shader if this is supported.
         * generally the NV extensions are preferred over the ATI ones, and this
         * extension is disabled if register_combiners and texture_shader2 are both
         * supported. So we reach this place only if we have incomplete NV dxlevel 8
         * fragment processing support. */
        gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
        gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
        gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
        gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
        gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
    }
    if (gl_info->supported[NV_HALF_FLOAT])
    {
        /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
        gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
    }
    if (gl_info->supported[ARB_POINT_SPRITE])
    {
        gl_info->max_point_sprite_units = gl_info->max_textures;
    }
    else
    {
        gl_info->max_point_sprite_units = 0;
1520
    }
1521
    checkGLcall("extension detection");
1522

1523 1524 1525
    /* In some cases the number of texture stages can be larger than the number
     * of samplers. The GF4 for example can use only 2 samplers (no fragment
     * shaders), but 8 texture stages (register combiners). */
1526
    gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1527

1528 1529
    /* We can only use ORM_FBO when the hardware supports it. */
    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1530 1531
        WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
        wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1532 1533
    }

1534 1535 1536 1537 1538
    /* MRTs are currently only supported when FBOs are used. */
    if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
        gl_info->max_buffers = 1;
    }

1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554
    /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
     * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
     * in case of the latest videocards in the number of pixel/vertex pipelines.
     *
     * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
     * rendering. Various games use this information to get a rough estimation of the features of the card
     * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
     * games might even use it to work around bugs which happen on certain videocards/driver combinations.
     * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
     * not the PCI id.
     *
     * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
     * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
     * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
     * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
     * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1555 1556
     * is used for rendering which is not always the case). This would work but it is not very portable. Second
     * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1557 1558 1559 1560 1561 1562 1563 1564
     * is limited.
     *
     * As said most games only use the PCI id to get an indication of the capabilities of the card.
     * It doesn't really matter if the given id is the correct one if we return the id of a card with
     * similar 3d features.
     *
     * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
     * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1565
     * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1566 1567 1568 1569
     * won't pass we return a default card. This way is better than maintaining a full card database as even
     * without a full database we can return a card with similar features. Second the 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
1570 1571 1572 1573 1574 1575 1576 1577 1578
     * to distinguishes between different models from that family.
     *
     * The code also selects a default amount of video memory which we will use for an estimation of the amount
     * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
     * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
     * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
     * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
     * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
     * memory behind our backs if really needed.
1579
     * Note that the amount of video memory can be overruled using a registry setting.
1580 1581 1582
     */
    switch (gl_info->gl_vendor) {
        case VENDOR_NVIDIA:
1583 1584
            /* 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.
1585 1586
             */
            if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1587
                /* Geforce 200 - highend */
1588 1589 1590
                if (strstr(gl_renderer, "GTX 280")
                        || strstr(gl_renderer, "GTX 285")
                        || strstr(gl_renderer, "GTX 295"))
1591
                {
1592 1593 1594
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
                    vidmem = 1024;
                }
1595
                /* Geforce 200 - midend high */
1596
                else if (strstr(gl_renderer, "GTX 275"))
1597
                {
1598 1599 1600 1601
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
                    vidmem = 896;
                }
                /* Geforce 200 - midend */
1602
                else if (strstr(gl_renderer, "GTX 260"))
1603
                {
1604 1605 1606 1607
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
                    vidmem = 1024;
                }
                /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1608 1609 1610
                else if (strstr(gl_renderer, "9800")
                        || strstr(gl_renderer, "GTS 150")
                        || strstr(gl_renderer, "GTS 250"))
1611
                {
1612 1613 1614 1615
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
                    vidmem = 512;
                }
                /* Geforce9 - midend */
1616 1617
                else if (strstr(gl_renderer, "9600"))
                {
1618 1619 1620
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
                    vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
                }
1621
                /* Geforce9 - midend low / Geforce 200 - low*/
1622 1623 1624
                else if (strstr(gl_renderer, "9500")
                        || strstr(gl_renderer, "GT 120")
                        || strstr(gl_renderer, "GT 130"))
1625 1626 1627 1628 1629
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
                    vidmem = 256; /* The 9500GT has 256-1024MB */
                }
                /* Geforce9 - lowend */
1630 1631
                else if (strstr(gl_renderer, "9400"))
                {
1632 1633 1634 1635
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
                    vidmem = 256; /* The 9400GT has 256-1024MB */
                }
                /* Geforce9 - lowend low */
1636 1637 1638 1639
                else if (strstr(gl_renderer, "9100")
                        || strstr(gl_renderer, "9200")
                        || strstr(gl_renderer, "9300")
                        || strstr(gl_renderer, "G 100"))
1640 1641 1642 1643
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
                    vidmem = 256; /* The 9100-9300 cards have 256MB */
                }
1644
                /* Geforce8 - highend */
1645 1646
                else if (strstr(gl_renderer, "8800"))
                {
1647
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1648 1649
                    vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
                }
1650
                /* Geforce8 - midend mobile */
1651 1652
                else if (strstr(gl_renderer, "8600 M"))
                {
1653 1654 1655
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
                    vidmem = 512;
                }
1656
                /* Geforce8 - midend */
1657 1658
                else if (strstr(gl_renderer, "8600")
                        || strstr(gl_renderer, "8700"))
1659 1660 1661 1662 1663
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
                    vidmem = 256;
                }
                /* Geforce8 - lowend */
1664 1665 1666
                else if (strstr(gl_renderer, "8300")
                        || strstr(gl_renderer, "8400")
                        || strstr(gl_renderer, "8500"))
1667 1668 1669 1670 1671
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
                    vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
                }
                /* Geforce7 - highend */
1672 1673 1674 1675 1676
                else if (strstr(gl_renderer, "7800")
                        || strstr(gl_renderer, "7900")
                        || strstr(gl_renderer, "7950")
                        || strstr(gl_renderer, "Quadro FX 4")
                        || strstr(gl_renderer, "Quadro FX 5"))
1677 1678 1679 1680
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
                    vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
                }
1681
                /* Geforce7 midend */
1682 1683 1684
                else if (strstr(gl_renderer, "7600")
                        || strstr(gl_renderer, "7700"))
                {
1685 1686 1687
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
                    vidmem = 256; /* The 7600 uses 256-512MB */
                /* Geforce7 lower medium */
1688 1689 1690
                }
                else if (strstr(gl_renderer, "7400"))
                {
1691 1692 1693
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
                    vidmem = 256; /* The 7400 uses 256-512MB */
                }
1694
                /* Geforce7 lowend */
1695 1696
                else if (strstr(gl_renderer, "7300"))
                {
1697 1698 1699
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
                    vidmem = 256; /* Mac Pros with this card have 256 MB */
                }
1700
                /* Geforce6 highend */
1701
                else if (strstr(gl_renderer, "6800"))
1702 1703 1704 1705 1706
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
                    vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
                }
                /* Geforce6 - midend */
1707 1708 1709
                else if (strstr(gl_renderer, "6600")
                        || strstr(gl_renderer, "6610")
                        || strstr(gl_renderer, "6700"))
1710 1711 1712 1713 1714 1715
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
                    vidmem = 128; /* A 6600GT has 128-256MB */
                }
                /* Geforce6/7 lowend */
                else {
1716
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1717 1718
                    vidmem = 64; /* */
                }
1719
            } else if(WINE_D3D9_CAPABLE(gl_info)) {
1720
                /* GeforceFX - highend */
1721 1722 1723 1724
                if (strstr(gl_renderer, "5800")
                        || strstr(gl_renderer, "5900")
                        || strstr(gl_renderer, "5950")
                        || strstr(gl_renderer, "Quadro FX"))
1725 1726 1727 1728 1729
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
                    vidmem = 256; /* 5800-5900 cards use 256MB */
                }
                /* GeforceFX - midend */
1730 1731 1732 1733
                else if (strstr(gl_renderer, "5600")
                        || strstr(gl_renderer, "5650")
                        || strstr(gl_renderer, "5700")
                        || strstr(gl_renderer, "5750"))
1734 1735 1736 1737 1738 1739
                {
                    gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
                    vidmem = 128; /* A 5600 uses 128-256MB */
                }
                /* GeforceFX - lowend */
                else {
1740
                    gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1741 1742
                    vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
                }
1743
            } else if(WINE_D3D8_CAPABLE(gl_info)) {
1744 1745
                if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
                {
1746
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1747 1748
                    vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
                }
1749 1750
                else
                {
1751
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1752 1753
                    vidmem = 64; /* Geforce3 cards have 64-128MB */
                }
1754
            } else if(WINE_D3D7_CAPABLE(gl_info)) {
1755 1756
                if (strstr(gl_renderer, "GeForce4 MX"))
                {
1757
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1758 1759
                    vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
                }
1760 1761
                else if(strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
                {
1762
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1763 1764
                    vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
                }
1765 1766
                else if(strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
                {
1767
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1768 1769
                    vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
                }
1770 1771
                else
                {
1772
                    gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1773 1774
                    vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
                }
1775
            } else {
1776 1777
                if (strstr(gl_renderer, "TNT2"))
                {
1778
                    gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1779 1780
                    vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
                }
1781 1782
                else
                {
1783
                    gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1784 1785
                    vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
                }
1786 1787 1788
            }
            break;
        case VENDOR_ATI:
1789 1790 1791 1792 1793
            /* 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 card, even for RV790 based one
             */
1794
            if(WINE_D3D9_CAPABLE(gl_info)) {
1795
                /* Radeon R7xx HD4800 - highend */
1796 1797 1798 1799 1800
                if (strstr(gl_renderer, "HD 4800")          /* Radeon RV7xx HD48xx generic renderer string */
                        || strstr(gl_renderer, "HD 4830")   /* Radeon RV770 */
                        || strstr(gl_renderer, "HD 4850")   /* Radeon RV770 */
                        || strstr(gl_renderer, "HD 4870")   /* Radeon RV770 */
                        || strstr(gl_renderer, "HD 4890"))  /* Radeon RV790 */
1801 1802
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD4800;
1803 1804 1805
                    vidmem = 512; /* note: HD4890 cards use 1024MB */
                }
                /* Radeon R740 HD4700 - midend */
1806 1807
                else if (strstr(gl_renderer, "HD 4700")     /* Radeon RV770 */
                        || strstr(gl_renderer, "HD 4770"))  /* Radeon RV740 */
1808 1809 1810 1811 1812
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD4700;
                    vidmem = 512;
                }
                /* Radeon R730 HD4600 - midend */
1813 1814 1815
                else if (strstr(gl_renderer, "HD 4600")     /* Radeon RV730 */
                        || strstr(gl_renderer, "HD 4650")   /* Radeon RV730 */
                        || strstr(gl_renderer, "HD 4670"))  /* Radeon RV730 */
1816 1817 1818 1819 1820
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD4600;
                    vidmem = 512;
                }
                /* Radeon R710 HD4500/HD4350 - lowend */
1821 1822
                else if (strstr(gl_renderer, "HD 4350")     /* Radeon RV710 */
                        || strstr(gl_renderer, "HD 4550"))  /* Radeon RV710 */
1823 1824 1825
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD4350;
                    vidmem = 256;
1826
                }
1827
                /* Radeon R6xx HD2900/HD3800 - highend */
1828 1829 1830
                else if (strstr(gl_renderer, "HD 2900")
                        || strstr(gl_renderer, "HD 3870")
                        || strstr(gl_renderer, "HD 3850"))
1831
                {
1832
                    gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1833
                    vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1834
                }
1835
                /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1836 1837 1838 1839
                else if (strstr(gl_renderer, "HD 2600")
                        || strstr(gl_renderer, "HD 3830")
                        || strstr(gl_renderer, "HD 3690")
                        || strstr(gl_renderer, "HD 3650"))
1840
                {
1841
                    gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1842
                    vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1843
                }
1844
                /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1845 1846 1847 1848 1849 1850
                else if (strstr(gl_renderer, "HD 2300")
                        || strstr(gl_renderer, "HD 2400")
                        || strstr(gl_renderer, "HD 3470")
                        || strstr(gl_renderer, "HD 3450")
                        || strstr(gl_renderer, "HD 3430")
                        || strstr(gl_renderer, "HD 3400"))
1851 1852 1853 1854
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD2300;
                    vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
                }
1855
                /* Radeon R6xx/R7xx integrated */
1856 1857 1858
                else if (strstr(gl_renderer, "HD 3100")
                        || strstr(gl_renderer, "HD 3200")
                        || strstr(gl_renderer, "HD 3300"))
1859 1860 1861 1862
                {
                    gl_info->gl_card = CARD_ATI_RADEON_HD3200;
                    vidmem = 128; /* 128MB */
                }
1863
                /* Radeon R5xx */
1864 1865 1866 1867 1868
                else if (strstr(gl_renderer, "X1600")
                        || strstr(gl_renderer, "X1650")
                        || strstr(gl_renderer, "X1800")
                        || strstr(gl_renderer, "X1900")
                        || strstr(gl_renderer, "X1950"))
1869 1870 1871 1872
                {
                    gl_info->gl_card = CARD_ATI_RADEON_X1600;
                    vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
                }
1873
                /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1874 1875 1876 1877 1878 1879 1880
                else 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"))
1881 1882 1883 1884
                {
                    gl_info->gl_card = CARD_ATI_RADEON_X700;
                    vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
                }
1885
                /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1886
                else if(strstr(gl_renderer, "Radeon Xpress"))
1887 1888 1889 1890
                {
                    gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
                    vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
                }
1891
                /* Radeon R3xx */ 
1892
                else {
1893
                    gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1894
                    vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1895
                }
1896
            } else if(WINE_D3D8_CAPABLE(gl_info)) {
1897 1898
                gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
                vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1899
            } else if(WINE_D3D7_CAPABLE(gl_info)) {
1900
                gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1901
                vidmem = 32; /* There are models with up to 64MB */
1902
            } else {
1903
                gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1904
                vidmem = 16; /* There are 16-32MB models */
1905
            }
1906 1907
            break;
        case VENDOR_INTEL:
1908 1909 1910 1911 1912 1913 1914
            if(strstr(gl_renderer, "X3100"))
            {
                /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
                gl_info->gl_card = CARD_INTEL_X3100;
                vidmem = 128;
            }
            else if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1915
            {
1916 1917 1918
                /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
                gl_info->gl_card = CARD_INTEL_I945GM;
                vidmem = 64;
1919 1920 1921
            }
            else if (strstr(gl_renderer, "915GM"))
            {
1922
                gl_info->gl_card = CARD_INTEL_I915GM;
1923 1924 1925
            }
            else if (strstr(gl_renderer, "915G"))
            {
1926
                gl_info->gl_card = CARD_INTEL_I915G;
1927 1928 1929
            }
            else if (strstr(gl_renderer, "865G"))
            {
1930
                gl_info->gl_card = CARD_INTEL_I865G;
1931 1932 1933
            }
            else if (strstr(gl_renderer, "855G"))
            {
1934
                gl_info->gl_card = CARD_INTEL_I855G;
1935 1936 1937
            }
            else if (strstr(gl_renderer, "830G"))
            {
1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
                gl_info->gl_card = CARD_INTEL_I830G;
            } else {
                gl_info->gl_card = CARD_INTEL_I915G;
            }
            break;
        case VENDOR_MESA:
        case VENDOR_WINE:
        default:
            /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice 
             * for Nvidia was because the hardware and drivers they make are of good quality. This makes
             * them a good generic choice.
             */
            gl_info->gl_vendor = VENDOR_NVIDIA;
            if(WINE_D3D9_CAPABLE(gl_info))
                gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
            else if(WINE_D3D8_CAPABLE(gl_info))
1954
                gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1955 1956 1957 1958 1959 1960 1961
            else if(WINE_D3D7_CAPABLE(gl_info))
                gl_info->gl_card = CARD_NVIDIA_GEFORCE;
            else if(WINE_D3D6_CAPABLE(gl_info))
                gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
            else
                gl_info->gl_card = CARD_NVIDIA_RIVA_128;
    }
1962
    TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1963

1964 1965 1966 1967 1968
    /* If we have an estimate use it, else default to 64MB;  */
    if(vidmem)
        gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
    else
        gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1969

1970
    /* Load all the lookup tables */
1971
    for (i = 0; i < MAX_LOOKUPS; i++) {
1972
        stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1973 1974
    }

1975 1976 1977
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP   - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP  - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1978
             gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1979
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1980
             gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1981
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1982
             gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1983
    stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1984 1985
             gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;

1986 1987 1988 1989
    magLookup[WINED3DTEXF_NONE        - WINED3DTEXF_NONE]  = GL_NEAREST;
    magLookup[WINED3DTEXF_POINT       - WINED3DTEXF_NONE] = GL_NEAREST;
    magLookup[WINED3DTEXF_LINEAR      - WINED3DTEXF_NONE] = GL_LINEAR;
    magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1990 1991 1992
             gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;


1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007
    minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE]     = GL_LINEAR;
    minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT]    = GL_LINEAR;
    minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR]   = GL_LINEAR;
    minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE]    = GL_NEAREST;
    minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT]   = GL_NEAREST_MIPMAP_NEAREST;
    minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR]  = GL_NEAREST_MIPMAP_LINEAR;
    minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE]   = GL_LINEAR;
    minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT]  = GL_LINEAR_MIPMAP_NEAREST;
    minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
    minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
            = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
    minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
            = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
    minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
            = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
2008 2009 2010

/* TODO: config lookups */

2011
    /* Make sure there's an active HDC else the WGL extensions will fail */
2012
    hdc = pwglGetCurrentDC();
2013
    if (hdc) {
2014 2015 2016
        /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
        if(GL_EXTCALL(wglGetExtensionsStringARB))
            WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2017

2018 2019
        if (NULL == WGL_Extensions) {
            ERR("   WGL_Extensions returns NULL\n");
2020
        } else {
2021
            TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2022
            while (*WGL_Extensions != 0x00) {
2023
                const char *Start;
2024
                char ThisExtn[256];
2025

2026 2027 2028
                while (isspace(*WGL_Extensions)) WGL_Extensions++;
                Start = WGL_Extensions;
                while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2029
                    WGL_Extensions++;
2030
                }
2031 2032 2033 2034 2035 2036 2037

                len = WGL_Extensions - Start;
                if (len == 0 || len >= sizeof(ThisExtn))
                    continue;

                memcpy(ThisExtn, Start, len);
                ThisExtn[len] = '\0';
2038
                TRACE_(d3d_caps)("- %s\n", ThisExtn);
2039

2040
                if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2041 2042
                    gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
                    TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2043
                }
2044 2045 2046 2047
                if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
                    gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
                    TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
                }
2048 2049 2050 2051
                if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
                    gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
                    TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
                }
2052 2053 2054
            }
        }
    }
2055
    LEAVE_GL();
2056

2057 2058 2059 2060
    fixup_extensions(gl_info, gl_renderer);
    add_gl_compat_wrappers(gl_info);

    HeapFree(GetProcessHeap(), 0, gl_renderer);
2061
    return TRUE;
2062 2063 2064 2065 2066 2067
}

/**********************************************************
 * IWineD3D implementation follows
 **********************************************************/

2068
static UINT     WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2069 2070
    IWineD3DImpl *This = (IWineD3DImpl *)iface;

2071 2072 2073
    TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);

    return This->adapter_count;
2074 2075
}

2076
static HRESULT  WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
2077 2078
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
2079
    return WINED3D_OK;
2080 2081
}

2082
static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2083
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
2084

2085 2086
    TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);

2087 2088 2089
    if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
        return NULL;
    }
2090

2091
    return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2092 2093
}

2094
/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2095 2096
     of the same bpp but different resolutions                                  */

2097
/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2098
static UINT     WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2099 2100 2101 2102 2103 2104 2105
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
        return 0;
    }

2106
    /* TODO: Store modes per adapter and read it from the adapter structure */
2107
    if (Adapter == 0) { /* Display */
2108 2109 2110
        unsigned int i = 0;
        unsigned int j = 0;
        DEVMODEW mode;
2111

2112 2113
        memset(&mode, 0, sizeof(mode));
        mode.dmSize = sizeof(mode);
2114

2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139
        while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
        {
            ++j;
            switch (Format)
            {
                case WINED3DFMT_UNKNOWN:
                    /* This is for D3D8, do not enumerate P8 here */
                    if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
                    break;

                case WINED3DFMT_X8R8G8B8:
                    if (mode.dmBitsPerPel == 32) ++i;
                    break;

                case WINED3DFMT_R5G6B5:
                    if (mode.dmBitsPerPel == 16) ++i;
                    break;

                case WINED3DFMT_P8:
                    if (mode.dmBitsPerPel == 8) ++i;
                    break;

                default:
                    /* Skip other modes as they do not match the requested format */
                    break;
2140 2141
            }
        }
2142

2143 2144 2145 2146 2147 2148 2149 2150
        TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
        return i;
    } else {
        FIXME_(d3d_caps)("Adapter not primary display\n");
    }
    return 0;
}

2151
/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2152
static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2153 2154 2155 2156
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));

    /* Validate the parameters as much as possible */
2157
    if (NULL == pMode ||
2158 2159
        Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
        Mode    >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2160
        return WINED3DERR_INVALIDCALL;
2161 2162
    }

2163
    /* TODO: Store modes per adapter and read it from the adapter structure */
2164 2165
    if (Adapter == 0)
    {
2166 2167
        DEVMODEW DevModeW;
        int ModeIdx = 0;
2168
        UINT i = 0;
2169
        int j = 0;
2170

2171 2172 2173
        ZeroMemory(&DevModeW, sizeof(DevModeW));
        DevModeW.dmSize = sizeof(DevModeW);

2174 2175 2176 2177 2178 2179
        /* If we are filtering to a specific format (D3D9), then need to skip
           all unrelated modes, but if mode is irrelevant (D3D8), then we can
           just count through the ones with valid bit depths */
        while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
            switch (Format)
            {
2180
                case WINED3DFMT_UNKNOWN:
2181
                    /* This is D3D8. Do not enumerate P8 here */
2182 2183 2184
                    if (DevModeW.dmBitsPerPel == 32 ||
                        DevModeW.dmBitsPerPel == 16) i++;
                    break;
2185
                case WINED3DFMT_X8R8G8B8:
2186 2187
                    if (DevModeW.dmBitsPerPel == 32) i++;
                    break;
2188
                case WINED3DFMT_R5G6B5:
2189 2190
                    if (DevModeW.dmBitsPerPel == 16) i++;
                    break;
2191 2192 2193
                case WINED3DFMT_P8:
                    if (DevModeW.dmBitsPerPel == 8) i++;
                    break;
2194
                default:
2195 2196 2197
                    /* Modes that don't match what we support can get an early-out */
                    TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
                    return WINED3DERR_INVALIDCALL;
2198 2199 2200
            }
        }

2201 2202 2203 2204 2205 2206
        if (i == 0) {
            TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
            return WINED3DERR_INVALIDCALL;
        }
        ModeIdx = j - 1;

2207
        /* Now get the display mode via the calculated index */
2208
        if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2209 2210
            pMode->Width        = DevModeW.dmPelsWidth;
            pMode->Height       = DevModeW.dmPelsHeight;
2211
            pMode->RefreshRate  = WINED3DADAPTER_DEFAULT;
2212
            if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2213 2214
                pMode->RefreshRate = DevModeW.dmDisplayFrequency;

2215 2216
            if (Format == WINED3DFMT_UNKNOWN) {
                pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2217 2218 2219
            } else {
                pMode->Format = Format;
            }
2220
        } else {
2221
            TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2222
            return WINED3DERR_INVALIDCALL;
2223 2224
        }

2225 2226 2227 2228
        TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
                pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
                DevModeW.dmBitsPerPel);

2229 2230 2231
    }
    else
    {
2232 2233 2234
        FIXME_(d3d_caps)("Adapter not primary display\n");
    }

2235
    return WINED3D_OK;
2236 2237
}

2238
static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2239 2240 2241
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);

2242
    if (NULL == pMode ||
2243
        Adapter >= IWineD3D_GetAdapterCount(iface)) {
2244
        return WINED3DERR_INVALIDCALL;
2245 2246 2247 2248 2249 2250
    }

    if (Adapter == 0) { /* Display */
        int bpp = 0;
        DEVMODEW DevModeW;

2251 2252 2253
        ZeroMemory(&DevModeW, sizeof(DevModeW));
        DevModeW.dmSize = sizeof(DevModeW);

2254
        EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2255 2256 2257
        pMode->Width        = DevModeW.dmPelsWidth;
        pMode->Height       = DevModeW.dmPelsHeight;
        bpp                 = DevModeW.dmBitsPerPel;
2258
        pMode->RefreshRate  = WINED3DADAPTER_DEFAULT;
2259 2260 2261 2262 2263
        if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
        {
            pMode->RefreshRate = DevModeW.dmDisplayFrequency;
        }

2264
        pMode->Format = pixelformat_for_depth(bpp);
2265 2266 2267 2268 2269 2270
    } else {
        FIXME_(d3d_caps)("Adapter not primary display\n");
    }

    TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
          pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2271
    return WINED3D_OK;
2272
}
2273

2274
/* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2275
   and fields being inserted in the middle, a new structure is used in place    */
2276
static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2277 2278
                                                   WINED3DADAPTER_IDENTIFIER* pIdentifier) {
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
2279
    size_t len;
2280

2281
    TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2282 2283

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2284
        return WINED3DERR_INVALIDCALL;
2285 2286
    }

2287 2288
    /* Return the information requested */
    TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333

    if (pIdentifier->driver_size)
    {
        len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1);
        memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len);
        pIdentifier->driver[len] = '\0';
    }

    if (pIdentifier->description_size)
    {
        const char *description;

        if (This->adapters[Adapter].gl_info.driver_description)
            description = This->adapters[Adapter].gl_info.driver_description;
        else
            description = This->adapters[Adapter].description;

        len = min(strlen(description), pIdentifier->description_size - 1);
        memcpy(pIdentifier->description, description, len);
        pIdentifier->description[len] = '\0';
    }

    /* Note that d3d8 doesn't supply a device name. */
    if (pIdentifier->device_name_size)
    {
        static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */

        len = strlen(device_name);
        if (len >= pIdentifier->device_name_size)
        {
            ERR("Device name size too small.\n");
            return WINED3DERR_INVALIDCALL;
        }

        memcpy(pIdentifier->device_name, device_name, len);
        pIdentifier->device_name[len] = '\0';
    }

    pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
    pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version;
    pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor;
    pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card;
    pIdentifier->subsystem_id = 0;
    pIdentifier->revision = 0;
    memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2334

2335 2336 2337
    if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
    {
        TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
2338
        pIdentifier->device_id = wined3d_settings.pci_device_id;
2339 2340
    }

2341 2342 2343
    if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
    {
        TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
2344
        pIdentifier->vendor_id = wined3d_settings.pci_vendor_id;
2345 2346
    }

2347
    pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2348

2349
    return WINED3D_OK;
2350 2351
}

2352
static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info,
2353
        const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2354
{
2355 2356 2357 2358 2359
    short redSize, greenSize, blueSize, alphaSize, colorBits;

    if(!cfg)
        return FALSE;

2360
    if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2361
        if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2362
        {
2363
            ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2364 2365
            return FALSE;
        }
2366

2367 2368
        if(cfg->redSize < redSize)
            return FALSE;
2369

2370 2371
        if(cfg->greenSize < greenSize)
            return FALSE;
2372

2373 2374
        if(cfg->blueSize < blueSize)
            return FALSE;
2375

2376 2377 2378 2379 2380
        if(cfg->alphaSize < alphaSize)
            return FALSE;

        return TRUE;
    } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2381
        if (format_desc->format == WINED3DFMT_R16_FLOAT)
2382
            return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2383
        if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2384
            return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2385
        if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2386
            return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2387
        if (format_desc->format == WINED3DFMT_R32_FLOAT)
2388
            return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2389
        if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2390
            return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2391
        if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2392 2393 2394
            return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
    } else {
        /* Probably a color index mode */
2395
        return FALSE;
2396
    }
2397

2398
    return FALSE;
2399 2400
}

2401
static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info,
2402
        const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2403
{
2404
    short depthSize, stencilSize;
2405
    BOOL lockable = FALSE;
2406 2407 2408 2409

    if(!cfg)
        return FALSE;

2410
    if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2411
    {
2412
        ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2413 2414 2415
        return FALSE;
    }

2416
    if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
2417 2418 2419 2420 2421 2422
        lockable = TRUE;

    /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
     * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
     * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
    if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2423 2424
        return FALSE;

2425 2426 2427
    /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
     * allow more stencil bits than requested. */
    if(cfg->stencilSize < stencilSize)
2428 2429
        return FALSE;

2430
    return TRUE;
2431 2432
}

2433
static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2434 2435 2436
                                                   WINED3DFORMAT AdapterFormat,
                                                   WINED3DFORMAT RenderTargetFormat,
                                                   WINED3DFORMAT DepthStencilFormat) {
2437
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
2438
    int nCfgs;
2439
    const WineD3D_PixelFormat *cfgs;
2440
    const struct WineD3DAdapter *adapter;
2441 2442
    const struct GlPixelFormatDesc *rt_format_desc;
    const struct GlPixelFormatDesc *ds_format_desc;
2443 2444
    int it;

2445 2446
    WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
           This, Adapter,
2447 2448
           DeviceType, debug_d3ddevicetype(DeviceType),
           AdapterFormat, debug_d3dformat(AdapterFormat),
2449
           RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2450 2451 2452
           DepthStencilFormat, debug_d3dformat(DepthStencilFormat));

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2453 2454
        TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
        return WINED3DERR_INVALIDCALL;
2455
    }
2456

2457
    adapter = &This->adapters[Adapter];
2458 2459
    rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
    ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2460 2461
    cfgs = adapter->cfgs;
    nCfgs = adapter->nCfgs;
2462
    for (it = 0; it < nCfgs; ++it) {
2463
        if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2464
        {
2465
            if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2466
            {
2467 2468
                TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
                return WINED3D_OK;
2469 2470
            }
        }
2471
    }
2472
    WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2473

2474
    return WINED3DERR_NOTAVAILABLE;
2475 2476
}

2477
static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
2478
                                                       WINED3DFORMAT SurfaceFormat,
2479
                                                       BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD*   pQualityLevels) {
2480

2481
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
2482
    const struct GlPixelFormatDesc *glDesc;
2483
    const struct WineD3DAdapter *adapter;
2484 2485

    TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2486 2487
          This,
          Adapter,
2488 2489
          DeviceType, debug_d3ddevicetype(DeviceType),
          SurfaceFormat, debug_d3dformat(SurfaceFormat),
2490
          Windowed,
2491 2492
          MultiSampleType,
          pQualityLevels);
2493

2494
    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2495
        return WINED3DERR_INVALIDCALL;
2496 2497
    }

2498 2499
    /* TODO: handle Windowed, add more quality levels */

2500 2501 2502 2503
    if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
        if(pQualityLevels) *pQualityLevels = 1;
        return WINED3D_OK;
    }
2504

2505 2506 2507 2508 2509 2510
    /* By default multisampling is disabled right now as it causes issues
     * on some Nvidia driver versions and it doesn't work well in combination
     * with FBOs yet. */
    if(!wined3d_settings.allow_multisampling)
        return WINED3DERR_NOTAVAILABLE;

2511 2512 2513
    adapter = &This->adapters[Adapter];
    glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
    if (!glDesc) return WINED3DERR_INVALIDCALL;
2514 2515 2516

    if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
        int i, nCfgs;
2517
        const WineD3D_PixelFormat *cfgs;
2518

2519 2520
        cfgs = adapter->cfgs;
        nCfgs = adapter->nCfgs;
2521 2522 2523 2524
        for(i=0; i<nCfgs; i++) {
            if(cfgs[i].numSamples != MultiSampleType)
                continue;

2525
            if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2526 2527 2528 2529 2530 2531 2532
                continue;

            TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));

            if(pQualityLevels)
                *pQualityLevels = 1; /* Guess at a value! */
            return WINED3D_OK;
2533
        }
2534
    }
2535 2536 2537
    else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
        short redSize, greenSize, blueSize, alphaSize, colorBits;
        int i, nCfgs;
2538
        const WineD3D_PixelFormat *cfgs;
2539

2540
        if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2541
        {
2542 2543 2544 2545
            ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
            return WINED3DERR_NOTAVAILABLE;
        }

2546 2547
        cfgs = adapter->cfgs;
        nCfgs = adapter->nCfgs;
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566
        for(i=0; i<nCfgs; i++) {
            if(cfgs[i].numSamples != MultiSampleType)
                continue;
            if(cfgs[i].redSize != redSize)
                continue;
            if(cfgs[i].greenSize != greenSize)
                continue;
            if(cfgs[i].blueSize != blueSize)
                continue;
            if(cfgs[i].alphaSize != alphaSize)
                continue;

            TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));

            if(pQualityLevels)
                *pQualityLevels = 1; /* Guess at a value! */
            return WINED3D_OK;
        }
    }
2567
    return WINED3DERR_NOTAVAILABLE;
2568 2569
}

2570
static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2571
                                            WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2572 2573

    IWineD3DImpl *This = (IWineD3DImpl *)iface;
2574
    HRESULT hr = WINED3DERR_NOTAVAILABLE;
2575
    UINT nmodes;
2576

2577 2578 2579
    TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
          This,
          Adapter,
2580
          DeviceType, debug_d3ddevicetype(DeviceType),
2581 2582 2583 2584 2585
          DisplayFormat, debug_d3dformat(DisplayFormat),
          BackBufferFormat, debug_d3dformat(BackBufferFormat),
          Windowed);

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2586
        WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2587
        return WINED3DERR_INVALIDCALL;
2588 2589
    }

2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613
    /* The task of this function is to check whether a certain display / backbuffer format
     * 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 */

    /* There are only 4 display formats */
    if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
         (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
         (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
         (DisplayFormat == WINED3DFMT_A2R10G10B10)))
    {
        TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
        return WINED3DERR_NOTAVAILABLE;
    }

    /* If the requested DisplayFormat is not available, don't continue */
    nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
    if(!nmodes) {
        TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
        return WINED3DERR_NOTAVAILABLE;
2614
    }
2615

2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644
    /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
    if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
        TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
        return WINED3DERR_NOTAVAILABLE;
    }

    /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
    if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
        TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
        return WINED3DERR_NOTAVAILABLE;
    }

    /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
    if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
        TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
        return WINED3DERR_NOTAVAILABLE;
    }

    /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
    if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
        TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
        return WINED3DERR_NOTAVAILABLE;
    }

    /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
    if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
        TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
        return WINED3DERR_NOTAVAILABLE;
    }
2645

2646
    /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2647
    hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2648 2649
    if(FAILED(hr))
        TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2650 2651

    return hr;
2652 2653
}

2654

2655
/* Check if we support bumpmapping for a format */
2656
static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2657
        WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2658
{
2659 2660
    const struct fragment_pipeline *fp;

2661 2662
    switch(format_desc->format)
    {
2663 2664
        case WINED3DFMT_R8G8_SNORM:
        case WINED3DFMT_R16G16_SNORM:
2665 2666
        case WINED3DFMT_L6V5U5:
        case WINED3DFMT_X8L8V8U8:
2667
        case WINED3DFMT_R8G8B8A8_SNORM:
2668 2669 2670
            /* Ask the fixed function pipeline implementation if it can deal
             * with the conversion. If we've got a GL extension giving native
             * support this will be an identity conversion. */
2671
            fp = select_fragment_implementation(adapter, DeviceType);
2672
            if (fp->color_fixup_supported(format_desc->color_fixup))
2673
            {
2674 2675
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
2676
            }
2677 2678
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
2679 2680 2681 2682

        default:
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
2683
    }
2684 2685
}

2686
/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2687
static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2688
        const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2689 2690 2691
{
    int it=0;

2692
    /* Only allow depth/stencil formats */
2693
    if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE;
2694 2695

    /* Walk through all WGL pixel formats to find a match */
2696 2697 2698
    for (it = 0; it < adapter->nCfgs; ++it)
    {
        WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2699
        if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2700
        {
2701
            if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2702
            {
2703 2704 2705 2706 2707 2708 2709 2710
                return TRUE;
            }
        }
    }

    return FALSE;
}

2711
static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2712
{
2713
    /* The flags entry of a format contains the filtering capability */
2714
    if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2715 2716

    return FALSE;
2717 2718
}

2719
/* Check the render target capabilities of a format */
2720
static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2721
        const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2722 2723
{
    /* Filter out non-RT formats */
2724
    if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2725 2726

    if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2727
        WineD3D_PixelFormat *cfgs = adapter->cfgs;
2728 2729 2730 2731
        int it;
        short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
        short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;

2732 2733
        getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
        getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2734 2735 2736 2737 2738 2739 2740 2741 2742 2743

        /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
         * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
        if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
        }

        /* Check if there is a WGL pixel format matching the requirements, the format should also be window
         * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2744 2745
        for (it = 0; it < adapter->nCfgs; ++it)
        {
2746
            if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2747
                    &cfgs[it], check_format_desc))
2748
            {
2749 2750
                TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
                        cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2751 2752 2753 2754
                return TRUE;
            }
        }
    } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2755
        /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2756
        WineD3D_PixelFormat *cfgs = adapter->cfgs;
2757 2758 2759
        int it;

        /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2760 2761
        for (it = 0; it < adapter->nCfgs; ++it)
        {
2762
            if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2763
                    &cfgs[it], check_format_desc))
2764
            {
2765 2766
                TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
                        cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777
                return TRUE;
            }
        }
    } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
        /* For now return TRUE for FBOs until we have some proper checks.
         * Note that this function will only be called when the format is around for texturing. */
        return TRUE;
    }
    return FALSE;
}

2778
static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2779
{
2780 2781
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;

2782 2783 2784 2785 2786 2787
    /* Check for supported sRGB formats (Texture loading and framebuffer) */
    if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
        TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
        return FALSE;
    }

2788 2789
    switch (format_desc->format)
    {
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803
        case WINED3DFMT_A8R8G8B8:
        case WINED3DFMT_X8R8G8B8:
        case WINED3DFMT_A4R4G4B4:
        case WINED3DFMT_L8:
        case WINED3DFMT_A8L8:
        case WINED3DFMT_DXT1:
        case WINED3DFMT_DXT2:
        case WINED3DFMT_DXT3:
        case WINED3DFMT_DXT4:
        case WINED3DFMT_DXT5:
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;

        default:
2804
            TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2805 2806 2807 2808 2809
            return FALSE;
    }
    return FALSE;
}

2810
static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2811
        WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2812 2813 2814 2815
{
    /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
     * doing the color fixup in shaders.
     * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2816 2817
    if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
    {
2818 2819
        int vs_selected_mode;
        int ps_selected_mode;
2820
        select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2821 2822 2823 2824 2825 2826 2827

        if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;
        }
    }

2828
    TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2829 2830 2831
    return FALSE;
}

2832
/* Check if a format support blending in combination with pixel shaders */
2833 2834
static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
        const struct GlPixelFormatDesc *format_desc)
2835 2836
{
    /* The flags entry of a format contains the post pixel shader blending capability */
2837
    if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2838 2839 2840 2841

    return FALSE;
}

2842 2843
static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
{
2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855
    /* OpenGL supports mipmapping on all formats basically. 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 games need that
     */
    return TRUE;
}

2856
/* Check if a texture format is supported on the given adapter */
2857
static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2858
        WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2859
{
2860
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;
2861 2862
    const shader_backend_t *shader_backend;
    const struct fragment_pipeline *fp;
2863

2864 2865
    switch (format_desc->format)
    {
2866 2867 2868 2869 2870 2871 2872 2873 2874 2875
        /*****
         *  supported: RGB(A) formats
         */
        case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
        case WINED3DFMT_A8R8G8B8:
        case WINED3DFMT_X8R8G8B8:
        case WINED3DFMT_R5G6B5:
        case WINED3DFMT_X1R5G5B5:
        case WINED3DFMT_A1R5G5B5:
        case WINED3DFMT_A4R4G4B4:
2876
        case WINED3DFMT_A8_UNORM:
2877
        case WINED3DFMT_X4R4G4B4:
2878
        case WINED3DFMT_R8G8B8A8_UNORM:
2879 2880
        case WINED3DFMT_X8B8G8R8:
        case WINED3DFMT_A2R10G10B10:
2881 2882
        case WINED3DFMT_R10G10B10A2_UNORM:
        case WINED3DFMT_R16G16_UNORM:
2883 2884 2885
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;

2886 2887 2888 2889
        case WINED3DFMT_R3G3B2:
            TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
            return FALSE;

2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
        /*****
         *  supported: Palettized
         */
        case WINED3DFMT_P8:
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;
        /* No Windows driver offers A8P8, so don't offer it either */
        case WINED3DFMT_A8P8:
            return FALSE;

        /*****
         *  Supported: (Alpha)-Luminance
         */
        case WINED3DFMT_L8:
        case WINED3DFMT_A8L8:
        case WINED3DFMT_L16:
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;

2909 2910 2911 2912 2913
        /* Not supported on Windows, thus disabled */
        case WINED3DFMT_A4L4:
            TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
            return FALSE;

2914 2915 2916
        /*****
         *  Supported: Depth/Stencil formats
         */
2917
        case WINED3DFMT_D16_LOCKABLE:
2918
        case WINED3DFMT_D16_UNORM:
2919 2920 2921 2922 2923 2924 2925
        case WINED3DFMT_D15S1:
        case WINED3DFMT_D24X8:
        case WINED3DFMT_D24X4S4:
        case WINED3DFMT_D24S8:
        case WINED3DFMT_D24FS8:
        case WINED3DFMT_D32:
        case WINED3DFMT_D32F_LOCKABLE:
2926
            return TRUE;
2927 2928 2929

        /*****
         *  Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2930
         *  GL_NV_texture_shader). Emulated by shaders
2931
         */
2932
        case WINED3DFMT_R8G8_SNORM:
2933 2934
        case WINED3DFMT_X8L8V8U8:
        case WINED3DFMT_L6V5U5:
2935 2936
        case WINED3DFMT_R8G8B8A8_SNORM:
        case WINED3DFMT_R16G16_SNORM:
2937 2938 2939
            /* Ask the shader backend if it can deal with the conversion. If
             * we've got a GL extension giving native support this will be an
             * identity conversion. */
2940
            shader_backend = select_shader_backend(adapter, DeviceType);
2941
            if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2942
            {
2943
                TRACE_(d3d_caps)("[OK]\n");
2944 2945
                return TRUE;
            }
2946 2947
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965

        case WINED3DFMT_DXT1:
        case WINED3DFMT_DXT2:
        case WINED3DFMT_DXT3:
        case WINED3DFMT_DXT4:
        case WINED3DFMT_DXT5:
            if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;


        /*****
         *  Odd formats - not supported
         */
        case WINED3DFMT_VERTEXDATA:
2966 2967 2968
        case WINED3DFMT_R16_UINT:
        case WINED3DFMT_R32_UINT:
        case WINED3DFMT_R16G16B16A16_SNORM:
2969
        case WINED3DFMT_A2W10V10U10:
2970
        case WINED3DFMT_W11V11U10:
2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
            TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
            return FALSE;

        /*****
         *  WINED3DFMT_CxV8U8: Not supported right now
         */
        case WINED3DFMT_CxV8U8:
            TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
            return FALSE;

2981
        /* YUV formats */
2982 2983
        case WINED3DFMT_UYVY:
        case WINED3DFMT_YUY2:
2984 2985 2986 2987 2988
            if(GL_SUPPORT(APPLE_YCBCR_422)) {
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
2989
            return FALSE;
2990 2991 2992
        case WINED3DFMT_YV12:
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
2993 2994

            /* Not supported */
2995
        case WINED3DFMT_R16G16B16A16_UNORM:
2996 2997 2998 2999 3000
        case WINED3DFMT_A8R3G3B2:
            TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
            return FALSE;

            /* Floating point formats */
3001
        case WINED3DFMT_R16_FLOAT:
3002
        case WINED3DFMT_R16G16_FLOAT:
3003
        case WINED3DFMT_R16G16B16A16_FLOAT:
3004
            if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
3005 3006 3007 3008 3009 3010
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

3011
        case WINED3DFMT_R32_FLOAT:
3012
        case WINED3DFMT_R32G32_FLOAT:
3013
        case WINED3DFMT_R32G32B32A32_FLOAT:
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
            if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

        /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
         * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
         * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
         * We can do instancing with all shader versions, but we need vertex shaders.
         *
3026
         * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
         * to enable instancing. WineD3D doesn't need that and just ignores it.
         *
         * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
         */
        case WINEMAKEFOURCC('I','N','S','T'):
            TRACE("ATI Instancing check hack\n");
            if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

        /* Some weird FOURCC formats */
        case WINED3DFMT_R8G8_B8G8:
        case WINED3DFMT_G8R8_G8B8:
        case WINED3DFMT_MULTI2_ARGB8:
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

3047 3048
        /* Vendor specific formats */
        case WINED3DFMT_ATI2N:
3049
            if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
3050 3051
                shader_backend = select_shader_backend(adapter, DeviceType);
                fp = select_fragment_implementation(adapter, DeviceType);
3052 3053
                if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
                        && fp->color_fixup_supported(format_desc->color_fixup))
3054
                {
3055 3056 3057 3058
                    TRACE_(d3d_caps)("[OK]\n");
                    return TRUE;
                }

3059 3060 3061 3062 3063 3064
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            }
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075
        case WINED3DFMT_NVHU:
        case WINED3DFMT_NVHS:
            /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
             * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
             * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
             * ATI refused to support formats which can easilly be emulated with pixel shaders, so
             * Applications have to deal with not having NVHS and NVHU.
             */
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;

3076 3077 3078 3079
        case WINED3DFMT_UNKNOWN:
            return FALSE;

        default:
3080
            ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3081 3082 3083 3084 3085
            break;
    }
    return FALSE;
}

3086 3087
static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
        WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3088
{
3089 3090
    const struct blit_shader *blitter;

3091
    if(SurfaceType == SURFACE_GDI) {
3092 3093
        switch(check_format_desc->format)
        {
3094 3095 3096 3097 3098 3099 3100 3101
            case WINED3DFMT_R8G8B8:
            case WINED3DFMT_A8R8G8B8:
            case WINED3DFMT_X8R8G8B8:
            case WINED3DFMT_R5G6B5:
            case WINED3DFMT_X1R5G5B5:
            case WINED3DFMT_A1R5G5B5:
            case WINED3DFMT_A4R4G4B4:
            case WINED3DFMT_R3G3B2:
3102
            case WINED3DFMT_A8_UNORM:
3103 3104
            case WINED3DFMT_A8R3G3B2:
            case WINED3DFMT_X4R4G4B4:
3105 3106
            case WINED3DFMT_R10G10B10A2_UNORM:
            case WINED3DFMT_R8G8B8A8_UNORM:
3107
            case WINED3DFMT_X8B8G8R8:
3108
            case WINED3DFMT_R16G16_UNORM:
3109
            case WINED3DFMT_A2R10G10B10:
3110
            case WINED3DFMT_R16G16B16A16_UNORM:
3111 3112 3113 3114 3115 3116 3117 3118 3119
            case WINED3DFMT_P8:
                TRACE_(d3d_caps)("[OK]\n");
                return TRUE;
            default:
                TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
                return FALSE;
        }
    }

3120
    /* All format that are supported for textures are supported for surfaces as well */
3121
    if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3122
    /* All depth stencil formats are supported on surfaces */
3123
    if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3124

3125
    /* If opengl can't process the format natively, the blitter may be able to convert it */
3126
    blitter = select_blit_implementation(adapter, DeviceType);
3127
    if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3128
    {
3129 3130 3131 3132
        TRACE_(d3d_caps)("[OK]\n");
        return TRUE;
    }

3133 3134 3135 3136 3137
    /* Reject other formats */
    TRACE_(d3d_caps)("[FAILED]\n");
    return FALSE;
}

3138
static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
3139
{
3140 3141
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;

3142 3143 3144 3145 3146
    if (!GL_LIMITS(vertex_samplers)) {
        TRACE_(d3d_caps)("[FAILED]\n");
        return FALSE;
    }

3147 3148
    switch (format_desc->format)
    {
3149
        case WINED3DFMT_R32G32B32A32_FLOAT:
3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163
            if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
                TRACE_(d3d_caps)("[FAILED]\n");
                return FALSE;
            }
            TRACE_(d3d_caps)("[OK]\n");
            return TRUE;

        default:
            TRACE_(d3d_caps)("[FAILED]\n");
            return FALSE;
    }
    return FALSE;
}

3164
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, 
3165 3166
        WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
        WINED3DSURFTYPE SurfaceType) {
3167
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
3168 3169
    struct WineD3DAdapter *adapter = &This->adapters[Adapter];
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3170 3171
    const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
    const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3172 3173
    DWORD UsageCaps = 0;

3174
    TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3175 3176 3177 3178
          This,
          Adapter,
          DeviceType, debug_d3ddevicetype(DeviceType),
          AdapterFormat, debug_d3dformat(AdapterFormat),
3179
          Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3180
          RType, debug_d3dresourcetype(RType),
3181 3182 3183
          CheckFormat, debug_d3dformat(CheckFormat));

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3184
        return WINED3DERR_INVALIDCALL;
3185 3186
    }

3187
    if(RType == WINED3DRTYPE_CUBETEXTURE) {
3188 3189 3190 3191 3192 3193

        if(SurfaceType != SURFACE_OPENGL) {
            TRACE("[FAILED]\n");
            return WINED3DERR_NOTAVAILABLE;
        }

3194 3195 3196 3197 3198 3199 3200
        /* Cubetexture allows:
         *                    - D3DUSAGE_AUTOGENMIPMAP
         *                    - D3DUSAGE_DEPTHSTENCIL
         *                    - D3DUSAGE_DYNAMIC
         *                    - D3DUSAGE_NONSECURE (d3d9ex)
         *                    - D3DUSAGE_RENDERTARGET
         *                    - D3DUSAGE_SOFTWAREPROCESSING
3201
         *                    - D3DUSAGE_QUERY_WRAPANDMIP
3202 3203 3204
         */
        if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
            /* Check if the texture format is around */
3205
            if (CheckTextureCapability(adapter, DeviceType, format_desc))
3206
            {
3207 3208 3209 3210 3211
                if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
                    /* Check for automatic mipmap generation support */
                    if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
                        UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
                    } else {
Austin English's avatar
Austin English committed
3212
                        /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3213 3214 3215 3216
                        TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
                    }
                }

3217 3218 3219 3220
                /* Always report dynamic locking */
                if(Usage & WINED3DUSAGE_DYNAMIC)
                    UsageCaps |= WINED3DUSAGE_DYNAMIC;

3221
                if(Usage & WINED3DUSAGE_RENDERTARGET) {
3222
                    if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3223
                    {
3224 3225 3226 3227 3228 3229
                        UsageCaps |= WINED3DUSAGE_RENDERTARGET;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }
3230

3231 3232 3233 3234
                /* Always report software processing */
                if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
                    UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;

3235 3236
                /* Check QUERY_FILTER support */
                if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3237
                    if (CheckFilterCapability(adapter, format_desc))
3238
                    {
3239 3240 3241 3242 3243 3244 3245
                        UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }

3246 3247
                /* Check QUERY_POSTPIXELSHADER_BLENDING support */
                if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3248
                    if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3249
                    {
3250 3251 3252 3253 3254 3255 3256
                        UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }

3257 3258
                /* Check QUERY_SRGBREAD support */
                if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3259
                    if (CheckSrgbReadCapability(adapter, format_desc))
3260
                    {
3261 3262 3263 3264 3265 3266
                        UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }
3267

3268 3269
                /* Check QUERY_SRGBWRITE support */
                if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3270
                    if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3271
                    {
3272 3273 3274 3275 3276 3277 3278
                        UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }

3279 3280
                /* Check QUERY_VERTEXTEXTURE support */
                if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3281
                    if (CheckVertexTextureCapability(adapter, format_desc))
3282
                    {
3283 3284 3285 3286 3287 3288
                        UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }
3289 3290 3291

                /* Check QUERY_WRAPANDMIP support */
                if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3292 3293
                    if (CheckWrapAndMipCapability(adapter, format_desc))
                    {
3294 3295 3296 3297 3298 3299
                        UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
                    } else {
                        TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
                        return WINED3DERR_NOTAVAILABLE;
                    }
                }
3300 3301 3302
            } else {
                TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
                return WINED3DERR_NOTAVAILABLE;
3303
            }
3304 3305 3306
        } else {
            TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
            return WINED3DERR_NOTAVAILABLE;
3307 3308
        }
    } else if(RType == WINED3DRTYPE_SURFACE) {
3309 3310 3311 3312 3313 3314
        /* Surface allows:
         *                - D3DUSAGE_DEPTHSTENCIL
         *                - D3DUSAGE_NONSECURE (d3d9ex)
         *                - D3DUSAGE_RENDERTARGET
         */

3315
        if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3316
        {
3317
            if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3318
                if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3319
                {
3320 3321 3322 3323 3324
                    UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
3325
            }
3326

3327
            if(Usage & WINED3DUSAGE_RENDERTARGET) {
3328
                if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3329
                {
3330 3331 3332 3333 3334
                    UsageCaps |= WINED3DUSAGE_RENDERTARGET;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
3335
            }
3336

3337 3338
            /* Check QUERY_POSTPIXELSHADER_BLENDING support */
            if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3339
                if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3340
                {
3341 3342 3343 3344 3345
                    UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
3346
            }
3347 3348 3349
        } else {
            TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
            return WINED3DERR_NOTAVAILABLE;
3350
        }
3351

3352 3353 3354 3355 3356 3357 3358 3359 3360 3361
    } else if(RType == WINED3DRTYPE_TEXTURE) {
        /* Texture allows:
         *                - D3DUSAGE_AUTOGENMIPMAP
         *                - D3DUSAGE_DEPTHSTENCIL
         *                - D3DUSAGE_DMAP
         *                - D3DUSAGE_DYNAMIC
         *                - D3DUSAGE_NONSECURE (d3d9ex)
         *                - D3DUSAGE_RENDERTARGET
         *                - D3DUSAGE_SOFTWAREPROCESSING
         *                - D3DUSAGE_TEXTAPI (d3d9ex)
3362
         *                - D3DUSAGE_QUERY_WRAPANDMIP
3363 3364
         */

3365 3366 3367 3368 3369
        if(SurfaceType != SURFACE_OPENGL) {
            TRACE("[FAILED]\n");
            return WINED3DERR_NOTAVAILABLE;
        }

3370
        /* Check if the texture format is around */
3371
        if (CheckTextureCapability(adapter, DeviceType, format_desc))
3372
        {
3373 3374 3375 3376 3377
            if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
                /* Check for automatic mipmap generation support */
                if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
                    UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
                } else {
Austin English's avatar
Austin English committed
3378
                    /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3379 3380 3381 3382
                    TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
                }
            }

3383 3384 3385 3386
            /* Always report dynamic locking */
            if(Usage & WINED3DUSAGE_DYNAMIC)
                UsageCaps |= WINED3DUSAGE_DYNAMIC;

3387
            if(Usage & WINED3DUSAGE_RENDERTARGET) {
3388
                if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3389
                {
3390 3391 3392 3393 3394 3395
                    UsageCaps |= WINED3DUSAGE_RENDERTARGET;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
                     return WINED3DERR_NOTAVAILABLE;
                 }
            }
3396

3397 3398 3399 3400
            /* Always report software processing */
            if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
                UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;

3401 3402
            /* Check QUERY_FILTER support */
            if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3403
                if (CheckFilterCapability(adapter, format_desc))
3404
                {
3405 3406 3407 3408 3409 3410 3411
                    UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3412 3413
            /* Check QUERY_LEGACYBUMPMAP support */
            if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3414
                if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3415
                {
3416 3417 3418 3419 3420 3421
                    UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3422

3423 3424
            /* Check QUERY_POSTPIXELSHADER_BLENDING support */
            if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3425
                if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3426
                {
3427 3428 3429 3430 3431 3432 3433
                    UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3434 3435
            /* Check QUERY_SRGBREAD support */
            if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3436
                if (CheckSrgbReadCapability(adapter, format_desc))
3437
                {
3438 3439 3440 3441 3442 3443
                    UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3444

3445 3446
            /* Check QUERY_SRGBWRITE support */
            if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3447
                if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3448
                {
3449 3450 3451 3452 3453 3454 3455
                    UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3456 3457
            /* Check QUERY_VERTEXTEXTURE support */
            if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3458
                if (CheckVertexTextureCapability(adapter, format_desc))
3459
                {
3460 3461 3462 3463 3464 3465
                    UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3466 3467 3468

            /* Check QUERY_WRAPANDMIP support */
            if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3469 3470
                if (CheckWrapAndMipCapability(adapter, format_desc))
                {
3471 3472 3473 3474 3475 3476
                    UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3477 3478

            if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3479
                if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3480
                {
3481 3482 3483 3484 3485 3486
                    UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3487 3488 3489
        } else {
            TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
            return WINED3DERR_NOTAVAILABLE;
3490
        }
3491 3492 3493 3494 3495
    } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
        /* 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:
3496 3497 3498
         *                      - D3DUSAGE_DYNAMIC
         *                      - D3DUSAGE_NONSECURE (d3d9ex)
         *                      - D3DUSAGE_SOFTWAREPROCESSING
3499
         *                      - D3DUSAGE_QUERY_WRAPANDMIP
3500 3501
         */

3502 3503 3504 3505 3506
        if(SurfaceType != SURFACE_OPENGL) {
            TRACE("[FAILED]\n");
            return WINED3DERR_NOTAVAILABLE;
        }

3507 3508
        /* Check volume texture and volume usage caps */
        if(GL_SUPPORT(EXT_TEXTURE3D)) {
3509
            if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3510
            {
3511 3512 3513
                TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
                return WINED3DERR_NOTAVAILABLE;
            }
3514

3515 3516 3517 3518
            /* Always report dynamic locking */
            if(Usage & WINED3DUSAGE_DYNAMIC)
                UsageCaps |= WINED3DUSAGE_DYNAMIC;

3519 3520 3521 3522
            /* Always report software processing */
            if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
                UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;

3523 3524
            /* Check QUERY_FILTER support */
            if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3525
                if (CheckFilterCapability(adapter, format_desc))
3526
                {
3527 3528 3529 3530 3531 3532 3533
                    UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3534 3535
            /* Check QUERY_POSTPIXELSHADER_BLENDING support */
            if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3536
                if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3537
                {
3538 3539 3540 3541 3542 3543 3544
                    UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3545 3546
            /* Check QUERY_SRGBREAD support */
            if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3547
                if (CheckSrgbReadCapability(adapter, format_desc))
3548
                {
3549 3550 3551 3552 3553 3554
                    UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3555

3556 3557
            /* Check QUERY_SRGBWRITE support */
            if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3558
                if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3559
                {
3560 3561 3562 3563 3564 3565 3566
                    UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }

3567 3568
            /* Check QUERY_VERTEXTEXTURE support */
            if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3569
                if (CheckVertexTextureCapability(adapter, format_desc))
3570
                {
3571 3572 3573 3574 3575 3576
                    UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3577 3578 3579

            /* Check QUERY_WRAPANDMIP support */
            if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3580 3581
                if (CheckWrapAndMipCapability(adapter, format_desc))
                {
3582 3583 3584 3585 3586 3587
                    UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
                } else {
                    TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
                    return WINED3DERR_NOTAVAILABLE;
                }
            }
3588 3589 3590
        } else {
            TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
            return WINED3DERR_NOTAVAILABLE;
3591
        }
3592

3593 3594 3595 3596 3597 3598 3599 3600 3601
        /* 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
         * app needing one of those formats, don't advertize them to avoid leading apps into
         * temptation. The windows drivers don't support most of those formats on volumes anyway,
         * except of R32F.
         */
        switch(CheckFormat) {
            case WINED3DFMT_P8:
            case WINED3DFMT_A4L4:
3602 3603
            case WINED3DFMT_R32_FLOAT:
            case WINED3DFMT_R16_FLOAT:
3604 3605
            case WINED3DFMT_X8L8V8U8:
            case WINED3DFMT_L6V5U5:
3606
            case WINED3DFMT_R16G16_UNORM:
3607 3608 3609
                TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
                return WINED3DERR_NOTAVAILABLE;

3610 3611
            case WINED3DFMT_R8G8B8A8_SNORM:
            case WINED3DFMT_R16G16_SNORM:
3612 3613 3614 3615 3616 3617
            if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
                TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
                return WINED3DERR_NOTAVAILABLE;
            }
            break;

3618
            case WINED3DFMT_R8G8_SNORM:
3619
            if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641
                TRACE_(d3d_caps)("[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_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
                return WINED3DERR_NOTAVAILABLE;

            default:
                /* Do nothing, continue with checking the format below */
                break;
        }
3642
    } else if(RType == WINED3DRTYPE_BUFFER){
3643 3644 3645
        /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
        TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
        return WINED3DERR_NOTAVAILABLE;
3646
    }
3647

3648
    /* This format is nothing special and it is supported perfectly.
3649 3650 3651
     * However, ati and nvidia driver on windows do not mark this format as
     * supported (tested with the dxCapsViewer) and pretending to
     * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
3652 3653 3654 3655 3656 3657 3658 3659
     * So do the same as Windows drivers and pretend not to support it on dx8 and 9
     * Enable it on dx7. It will need additional checking on dx10 when we support it.
     */
    if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
        TRACE_(d3d_caps)("[FAILED]\n");
        return WINED3DERR_NOTAVAILABLE;
    }

3660 3661 3662 3663 3664 3665 3666 3667
    /* When the UsageCaps 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(UsageCaps == Usage) {
        return WINED3D_OK;
    } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
        return WINED3DOK_NOAUTOGEN;
    } else {
3668
        TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
3669 3670
        return WINED3DERR_NOTAVAILABLE;
    }
3671 3672
}

3673
static HRESULT  WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3674
                                                          WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3675 3676
    IWineD3DImpl *This = (IWineD3DImpl *)iface;

3677
    FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3678 3679 3680 3681
          This,
          Adapter,
          DeviceType, debug_d3ddevicetype(DeviceType),
          SourceFormat, debug_d3dformat(SourceFormat),
3682
          TargetFormat, debug_d3dformat(TargetFormat));
3683
    return WINED3D_OK;
3684 3685
}

3686 3687
static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
{
3688 3689 3690 3691
    const shader_backend_t *ret;
    int vs_selected_mode;
    int ps_selected_mode;

3692
    select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3693 3694 3695 3696 3697 3698 3699 3700 3701 3702
    if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
        ret = &glsl_shader_backend;
    } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
        ret = &arb_program_shader_backend;
    } else {
        ret = &none_shader_backend;
    }
    return ret;
}

3703 3704 3705 3706
static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
        WINED3DDEVTYPE DeviceType)
{
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3707 3708 3709
    int vs_selected_mode;
    int ps_selected_mode;

3710
    select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3711 3712 3713
    if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
        return &arbfp_fragment_pipeline;
    } else if(ps_selected_mode == SHADER_ATI) {
3714
        return &atifs_fragment_pipeline;
3715 3716 3717 3718 3719 3720
    } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
        return &nvts_fragment_pipeline;
    } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
        return &nvrc_fragment_pipeline;
    } else {
        return &ffp_fragment_pipeline;
3721 3722 3723
    }
}

3724 3725 3726
static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
{
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3727 3728 3729
    int vs_selected_mode;
    int ps_selected_mode;

3730
    select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3731 3732 3733 3734 3735
    if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
        return &arbfp_blit;
    } else {
        return &ffp_blit;
    }
3736 3737
}

3738 3739
/* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
      subset of a D3DCAPS9 structure. However, it has to come via a void *
3740
      as the d3d8 interface cannot import the d3d9 header                  */
3741
static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3742 3743

    IWineD3DImpl    *This = (IWineD3DImpl *)iface;
3744 3745
    struct WineD3DAdapter *adapter = &This->adapters[Adapter];
    const WineD3D_GL_Info *gl_info = &adapter->gl_info;
3746 3747
    int vs_selected_mode;
    int ps_selected_mode;
3748
    struct shader_caps shader_caps;
3749
    struct fragment_caps fragment_caps;
3750
    const shader_backend_t *shader_backend;
3751
    const struct fragment_pipeline *frag_pipeline = NULL;
3752
    DWORD ckey_caps, blit_caps, fx_caps;
3753 3754 3755 3756

    TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);

    if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3757
        return WINED3DERR_INVALIDCALL;
3758 3759
    }

3760
    select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3761 3762 3763

    /* This function should *not* be modifying GL caps
     * TODO: move the functionality where it belongs */
3764
    select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3765 3766 3767 3768

    /* ------------------------------------------------
       The following fields apply to both d3d8 and d3d9
       ------------------------------------------------ */
3769 3770
    pCaps->DeviceType              = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
    pCaps->AdapterOrdinal          = Adapter;
3771

3772 3773 3774 3775
    pCaps->Caps                    = 0;
    pCaps->Caps2                   = WINED3DCAPS2_CANRENDERWINDOWED |
                                     WINED3DCAPS2_FULLSCREENGAMMA |
                                     WINED3DCAPS2_DYNAMICTEXTURES;
3776
    if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3777 3778
        pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
    }
3779 3780 3781 3782 3783

    pCaps->Caps3                   = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
                                     WINED3DCAPS3_COPY_TO_VIDMEM                   |
                                     WINED3DCAPS3_COPY_TO_SYSTEMMEM;

3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812
    pCaps->PresentationIntervals   = WINED3DPRESENT_INTERVAL_IMMEDIATE  |
                                     WINED3DPRESENT_INTERVAL_ONE;

    pCaps->CursorCaps              = WINED3DCURSORCAPS_COLOR            |
                                     WINED3DCURSORCAPS_LOWRES;

    pCaps->DevCaps                 = WINED3DDEVCAPS_FLOATTLVERTEX       |
                                     WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
                                     WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
                                     WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
                                     WINED3DDEVCAPS_DRAWPRIMTLVERTEX    |
                                     WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
                                     WINED3DDEVCAPS_EXECUTEVIDEOMEMORY  |
                                     WINED3DDEVCAPS_PUREDEVICE          |
                                     WINED3DDEVCAPS_HWRASTERIZATION     |
                                     WINED3DDEVCAPS_TEXTUREVIDEOMEMORY  |
                                     WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
                                     WINED3DDEVCAPS_CANRENDERAFTERFLIP  |
                                     WINED3DDEVCAPS_DRAWPRIMITIVES2     |
                                     WINED3DDEVCAPS_DRAWPRIMITIVES2EX   |
                                     WINED3DDEVCAPS_RTPATCHES;

    pCaps->PrimitiveMiscCaps       = WINED3DPMISCCAPS_CULLNONE              |
                                     WINED3DPMISCCAPS_CULLCCW               |
                                     WINED3DPMISCCAPS_CULLCW                |
                                     WINED3DPMISCCAPS_COLORWRITEENABLE      |
                                     WINED3DPMISCCAPS_CLIPTLVERTS           |
                                     WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
                                     WINED3DPMISCCAPS_MASKZ                 |
3813 3814
                                     WINED3DPMISCCAPS_BLENDOP               |
                                     WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3815
                                    /* TODO:
3816 3817 3818 3819 3820
                                        WINED3DPMISCCAPS_NULLREFERENCE
                                        WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
                                        WINED3DPMISCCAPS_FOGANDSPECULARALPHA
                                        WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
                                        WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3821

3822
    if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3823
        pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3824

3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836
    pCaps->RasterCaps              = WINED3DPRASTERCAPS_DITHER    |
                                     WINED3DPRASTERCAPS_PAT       |
                                     WINED3DPRASTERCAPS_WFOG      |
                                     WINED3DPRASTERCAPS_ZFOG      |
                                     WINED3DPRASTERCAPS_FOGVERTEX |
                                     WINED3DPRASTERCAPS_FOGTABLE  |
                                     WINED3DPRASTERCAPS_STIPPLE   |
                                     WINED3DPRASTERCAPS_SUBPIXEL  |
                                     WINED3DPRASTERCAPS_ZTEST     |
                                     WINED3DPRASTERCAPS_SCISSORTEST   |
                                     WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
                                     WINED3DPRASTERCAPS_DEPTHBIAS;
3837 3838

    if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3839 3840 3841
        pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY    |
                             WINED3DPRASTERCAPS_ZBIAS         |
                             WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3842 3843
    }
    if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3844
        pCaps->RasterCaps         |= WINED3DPRASTERCAPS_FOGRANGE;
3845 3846
    }
                        /* FIXME Add:
3847 3848 3849 3850 3851
                           WINED3DPRASTERCAPS_COLORPERSPECTIVE
                           WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
                           WINED3DPRASTERCAPS_ANTIALIASEDGES
                           WINED3DPRASTERCAPS_ZBUFFERLESSHSR
                           WINED3DPRASTERCAPS_WBUFFER */
3852

3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885
    pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS       |
                      WINED3DPCMPCAPS_EQUAL        |
                      WINED3DPCMPCAPS_GREATER      |
                      WINED3DPCMPCAPS_GREATEREQUAL |
                      WINED3DPCMPCAPS_LESS         |
                      WINED3DPCMPCAPS_LESSEQUAL    |
                      WINED3DPCMPCAPS_NEVER        |
                      WINED3DPCMPCAPS_NOTEQUAL;

    pCaps->SrcBlendCaps  = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
                           WINED3DPBLENDCAPS_BOTHSRCALPHA    |
                           WINED3DPBLENDCAPS_DESTALPHA       |
                           WINED3DPBLENDCAPS_DESTCOLOR       |
                           WINED3DPBLENDCAPS_INVDESTALPHA    |
                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
                           WINED3DPBLENDCAPS_INVSRCALPHA     |
                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
                           WINED3DPBLENDCAPS_ONE             |
                           WINED3DPBLENDCAPS_SRCALPHA        |
                           WINED3DPBLENDCAPS_SRCALPHASAT     |
                           WINED3DPBLENDCAPS_SRCCOLOR        |
                           WINED3DPBLENDCAPS_ZERO;

    pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA       |
                           WINED3DPBLENDCAPS_DESTCOLOR       |
                           WINED3DPBLENDCAPS_INVDESTALPHA    |
                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
                           WINED3DPBLENDCAPS_INVSRCALPHA     |
                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
                           WINED3DPBLENDCAPS_ONE             |
                           WINED3DPBLENDCAPS_SRCALPHA        |
                           WINED3DPBLENDCAPS_SRCCOLOR        |
                           WINED3DPBLENDCAPS_ZERO;
3886 3887
    /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
     * according to the glBlendFunc manpage
3888 3889 3890
     *
     * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
     * legacy settings for srcblend only
3891
     */
3892

3893
    if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918
        pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
        pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
    }


    pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS       |
                          WINED3DPCMPCAPS_EQUAL        |
                          WINED3DPCMPCAPS_GREATER      |
                          WINED3DPCMPCAPS_GREATEREQUAL |
                          WINED3DPCMPCAPS_LESS         |
                          WINED3DPCMPCAPS_LESSEQUAL    |
                          WINED3DPCMPCAPS_NEVER        |
                          WINED3DPCMPCAPS_NOTEQUAL;

    pCaps->ShadeCaps     = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
                           WINED3DPSHADECAPS_COLORGOURAUDRGB    |
                           WINED3DPSHADECAPS_ALPHAFLATBLEND     |
                           WINED3DPSHADECAPS_ALPHAGOURAUDBLEND  |
                           WINED3DPSHADECAPS_COLORFLATRGB       |
                           WINED3DPSHADECAPS_FOGFLAT            |
                           WINED3DPSHADECAPS_FOGGOURAUD         |
                           WINED3DPSHADECAPS_SPECULARFLATRGB;

    pCaps->TextureCaps =  WINED3DPTEXTURECAPS_ALPHA              |
                          WINED3DPTEXTURECAPS_ALPHAPALETTE       |
3919
                          WINED3DPTEXTURECAPS_TRANSPARENCY       |
3920 3921 3922 3923
                          WINED3DPTEXTURECAPS_BORDER             |
                          WINED3DPTEXTURECAPS_MIPMAP             |
                          WINED3DPTEXTURECAPS_PROJECTED          |
                          WINED3DPTEXTURECAPS_PERSPECTIVE;
3924 3925

    if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3926 3927
        pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
                              WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3928
    }
3929

3930
    if( GL_SUPPORT(EXT_TEXTURE3D)) {
3931 3932 3933
        pCaps->TextureCaps |=  WINED3DPTEXTURECAPS_VOLUMEMAP      |
                               WINED3DPTEXTURECAPS_MIPVOLUMEMAP   |
                               WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3934 3935
    }

3936
    if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3937 3938 3939
        pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP     |
                              WINED3DPTEXTURECAPS_MIPCUBEMAP    |
                              WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3940

3941 3942
    }

3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954
    pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
                               WINED3DPTFILTERCAPS_MAGFPOINT        |
                               WINED3DPTFILTERCAPS_MINFLINEAR       |
                               WINED3DPTFILTERCAPS_MINFPOINT        |
                               WINED3DPTFILTERCAPS_MIPFLINEAR       |
                               WINED3DPTFILTERCAPS_MIPFPOINT        |
                               WINED3DPTFILTERCAPS_LINEAR           |
                               WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
                               WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
                               WINED3DPTFILTERCAPS_MIPLINEAR        |
                               WINED3DPTFILTERCAPS_MIPNEAREST       |
                               WINED3DPTFILTERCAPS_NEAREST;
3955

3956
    if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3957 3958
        pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
                                    WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3959 3960 3961
    }

    if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973
        pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
                                       WINED3DPTFILTERCAPS_MAGFPOINT        |
                                       WINED3DPTFILTERCAPS_MINFLINEAR       |
                                       WINED3DPTFILTERCAPS_MINFPOINT        |
                                       WINED3DPTFILTERCAPS_MIPFLINEAR       |
                                       WINED3DPTFILTERCAPS_MIPFPOINT        |
                                       WINED3DPTFILTERCAPS_LINEAR           |
                                       WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
                                       WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
                                       WINED3DPTFILTERCAPS_MIPLINEAR        |
                                       WINED3DPTFILTERCAPS_MIPNEAREST       |
                                       WINED3DPTFILTERCAPS_NEAREST;
3974 3975

        if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3976
            pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3977 3978 3979
                                            WINED3DPTFILTERCAPS_MINFANISOTROPIC;
        }
    } else
3980
        pCaps->CubeTextureFilterCaps = 0;
3981 3982

    if (GL_SUPPORT(EXT_TEXTURE3D)) {
3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994
        pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR       |
                                         WINED3DPTFILTERCAPS_MAGFPOINT        |
                                         WINED3DPTFILTERCAPS_MINFLINEAR       |
                                         WINED3DPTFILTERCAPS_MINFPOINT        |
                                         WINED3DPTFILTERCAPS_MIPFLINEAR       |
                                         WINED3DPTFILTERCAPS_MIPFPOINT        |
                                         WINED3DPTFILTERCAPS_LINEAR           |
                                         WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
                                         WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
                                         WINED3DPTFILTERCAPS_MIPLINEAR        |
                                         WINED3DPTFILTERCAPS_MIPNEAREST       |
                                         WINED3DPTFILTERCAPS_NEAREST;
3995
    } else
3996
        pCaps->VolumeTextureFilterCaps = 0;
3997

3998 3999 4000
    pCaps->TextureAddressCaps =  WINED3DPTADDRESSCAPS_INDEPENDENTUV |
                                 WINED3DPTADDRESSCAPS_CLAMP  |
                                 WINED3DPTADDRESSCAPS_WRAP;
4001 4002

    if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
4003
        pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4004 4005
    }
    if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
4006
        pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4007 4008
    }
    if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
4009
        pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4010 4011
    }

4012
    if (GL_SUPPORT(EXT_TEXTURE3D)) {
4013 4014 4015
        pCaps->VolumeTextureAddressCaps =  WINED3DPTADDRESSCAPS_INDEPENDENTUV |
                                           WINED3DPTADDRESSCAPS_CLAMP  |
                                           WINED3DPTADDRESSCAPS_WRAP;
4016
        if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
4017
            pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4018 4019
        }
        if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
4020
            pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4021 4022
        }
        if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
4023
            pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4024 4025
        }
    } else
4026
        pCaps->VolumeTextureAddressCaps = 0;
4027

4028 4029 4030 4031 4032 4033 4034 4035
    pCaps->LineCaps = WINED3DLINECAPS_TEXTURE       |
                      WINED3DLINECAPS_ZTEST         |
                      WINED3DLINECAPS_BLEND         |
                      WINED3DLINECAPS_ALPHACMP      |
                      WINED3DLINECAPS_FOG;
    /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
     * idea how generating the smoothing alpha values works; the result is different
     */
4036

4037 4038
    pCaps->MaxTextureWidth  = GL_LIMITS(texture_size);
    pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
4039

4040
    if(GL_SUPPORT(EXT_TEXTURE3D))
4041
        pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
4042
    else
4043
        pCaps->MaxVolumeExtent = 0;
4044

4045 4046
    pCaps->MaxTextureRepeat = 32768;
    pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
4047
    pCaps->MaxVertexW = 1.0f;
4048

4049 4050 4051 4052
    pCaps->GuardBandLeft = 0.0f;
    pCaps->GuardBandTop = 0.0f;
    pCaps->GuardBandRight = 0.0f;
    pCaps->GuardBandBottom = 0.0f;
4053

4054
    pCaps->ExtentsAdjust = 0.0f;
4055

4056 4057 4058 4059 4060 4061
    pCaps->StencilCaps =  WINED3DSTENCILCAPS_DECRSAT |
                          WINED3DSTENCILCAPS_INCRSAT |
                          WINED3DSTENCILCAPS_INVERT  |
                          WINED3DSTENCILCAPS_KEEP    |
                          WINED3DSTENCILCAPS_REPLACE |
                          WINED3DSTENCILCAPS_ZERO;
4062
    if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
4063 4064
        pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR  |
                              WINED3DSTENCILCAPS_INCR;
4065
    }
4066 4067 4068
    if ( This->dxVersion > 8 &&
        ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
            GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
4069
        pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4070
    }
4071

4072
    pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4073

4074 4075
    pCaps->MaxUserClipPlanes       = GL_LIMITS(clipplanes);
    pCaps->MaxActiveLights         = GL_LIMITS(lights);
4076

4077 4078
    pCaps->MaxVertexBlendMatrices      = GL_LIMITS(blends);
    pCaps->MaxVertexBlendMatrixIndex   = 0;
4079

4080 4081
    pCaps->MaxAnisotropy   = GL_LIMITS(anisotropy);
    pCaps->MaxPointSize    = GL_LIMITS(pointsize);
4082 4083


4084 4085 4086 4087 4088 4089
    pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
                                  WINED3DVTXPCAPS_MATERIALSOURCE7   |
                                  WINED3DVTXPCAPS_POSITIONALLIGHTS  |
                                  WINED3DVTXPCAPS_LOCALVIEWER       |
                                  WINED3DVTXPCAPS_VERTEXFOG         |
                                  WINED3DVTXPCAPS_TEXGEN;
4090
                                  /* FIXME: Add 
4091
                                     D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4092

4093 4094 4095 4096
    pCaps->MaxPrimitiveCount   = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
    pCaps->MaxVertexIndex      = 0xFFFFF;
    pCaps->MaxStreams          = MAX_STREAMS;
    pCaps->MaxStreamStride     = 1024;
4097

4098
    /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4099 4100
    pCaps->DevCaps2                          = WINED3DDEVCAPS2_STREAMOFFSET |
                                               WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4101 4102 4103 4104 4105
    pCaps->MaxNpatchTessellationLevel        = 0;
    pCaps->MasterAdapterOrdinal              = 0;
    pCaps->AdapterOrdinalInGroup             = 0;
    pCaps->NumberOfAdaptersInGroup           = 1;

4106 4107 4108 4109 4110 4111 4112 4113 4114
    pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);

    pCaps->StretchRectFilterCaps             = WINED3DPTFILTERCAPS_MINFPOINT  |
                                                WINED3DPTFILTERCAPS_MAGFPOINT  |
                                                WINED3DPTFILTERCAPS_MINFLINEAR |
                                                WINED3DPTFILTERCAPS_MAGFLINEAR;
    pCaps->VertexTextureFilterCaps           = 0;

    memset(&shader_caps, 0, sizeof(shader_caps));
4115 4116
    shader_backend = select_shader_backend(adapter, DeviceType);
    shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4117

4118
    memset(&fragment_caps, 0, sizeof(fragment_caps));
4119 4120
    frag_pipeline = select_fragment_implementation(adapter, DeviceType);
    frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4121

4122
    /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4123
    pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4124

4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139
    /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
     * Ignore shader model capabilities if disabled in config
     */
    if(vs_selected_mode == SHADER_NONE) {
        TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
        pCaps->VertexShaderVersion          = WINED3DVS_VERSION(0,0);
        pCaps->MaxVertexShaderConst         = 0;
    } else {
        pCaps->VertexShaderVersion          = shader_caps.VertexShaderVersion;
        pCaps->MaxVertexShaderConst         = shader_caps.MaxVertexShaderConst;
    }

    if(ps_selected_mode == SHADER_NONE) {
        TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
        pCaps->PixelShaderVersion           = WINED3DPS_VERSION(0,0);
4140
        pCaps->PixelShader1xMaxValue        = 0.0f;
4141 4142 4143 4144 4145
    } else {
        pCaps->PixelShaderVersion           = shader_caps.PixelShaderVersion;
        pCaps->PixelShader1xMaxValue        = shader_caps.PixelShader1xMaxValue;
    }

4146 4147 4148 4149
    pCaps->TextureOpCaps                    = fragment_caps.TextureOpCaps;
    pCaps->MaxTextureBlendStages            = fragment_caps.MaxTextureBlendStages;
    pCaps->MaxSimultaneousTextures          = fragment_caps.MaxSimultaneousTextures;

4150 4151 4152 4153 4154 4155 4156
    pCaps->VS20Caps                         = shader_caps.VS20Caps;
    pCaps->MaxVShaderInstructionsExecuted   = shader_caps.MaxVShaderInstructionsExecuted;
    pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
    pCaps->PS20Caps                         = shader_caps.PS20Caps;
    pCaps->MaxPShaderInstructionsExecuted   = shader_caps.MaxPShaderInstructionsExecuted;
    pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;

4157 4158 4159 4160 4161 4162 4163 4164 4165
    /* 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
     */
    if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
        /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
        use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
        pCaps->VS20Caps.Caps                     = WINED3DVS20CAPS_PREDICATION;
        pCaps->VS20Caps.DynamicFlowControlDepth  = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4166
        pCaps->VS20Caps.NumTemps                 = max(32, adapter->gl_info.vs_arb_max_temps);
4167 4168 4169
        pCaps->VS20Caps.StaticFlowControlDepth   = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */

        pCaps->MaxVShaderInstructionsExecuted    = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4170
        pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
4171 4172 4173
    } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
        pCaps->VS20Caps.Caps                     = 0;
        pCaps->VS20Caps.DynamicFlowControlDepth  = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4174
        pCaps->VS20Caps.NumTemps                 = max(12, adapter->gl_info.vs_arb_max_temps);
4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199
        pCaps->VS20Caps.StaticFlowControlDepth   = 1;

        pCaps->MaxVShaderInstructionsExecuted    = 65535;
        pCaps->MaxVertexShader30InstructionSlots = 0;
    } else { /* VS 1.x */
        pCaps->VS20Caps.Caps                     = 0;
        pCaps->VS20Caps.DynamicFlowControlDepth  = 0;
        pCaps->VS20Caps.NumTemps                 = 0;
        pCaps->VS20Caps.StaticFlowControlDepth   = 0;

        pCaps->MaxVShaderInstructionsExecuted    = 0;
        pCaps->MaxVertexShader30InstructionSlots = 0;
    }

    if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
        /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
        use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */

        /* Caps is more or less undocumented on MSDN but it appears to be used for PS20Caps based on results from R9600/FX5900/Geforce6800 cards from Windows */
        pCaps->PS20Caps.Caps                     = WINED3DPS20CAPS_ARBITRARYSWIZZLE     |
                WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
                WINED3DPS20CAPS_PREDICATION          |
                WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
                WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
        pCaps->PS20Caps.DynamicFlowControlDepth  = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4200
        pCaps->PS20Caps.NumTemps                 = max(32, adapter->gl_info.ps_arb_max_temps);
4201 4202 4203 4204
        pCaps->PS20Caps.StaticFlowControlDepth   = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
        pCaps->PS20Caps.NumInstructionSlots      = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */

        pCaps->MaxPShaderInstructionsExecuted    = 65535;
4205
        pCaps->MaxPixelShader30InstructionSlots  = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
4206 4207 4208 4209
    } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
        /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
        pCaps->PS20Caps.Caps                     = 0;
        pCaps->PS20Caps.DynamicFlowControlDepth  = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4210
        pCaps->PS20Caps.NumTemps                 = max(12, adapter->gl_info.ps_arb_max_temps);
4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226
        pCaps->PS20Caps.StaticFlowControlDepth   = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
        pCaps->PS20Caps.NumInstructionSlots      = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */

        pCaps->MaxPShaderInstructionsExecuted    = 512; /* Minimum value, a GeforceFX uses 1024 */
        pCaps->MaxPixelShader30InstructionSlots  = 0;
    } else { /* PS 1.x */
        pCaps->PS20Caps.Caps                     = 0;
        pCaps->PS20Caps.DynamicFlowControlDepth  = 0;
        pCaps->PS20Caps.NumTemps                 = 0;
        pCaps->PS20Caps.StaticFlowControlDepth   = 0;
        pCaps->PS20Caps.NumInstructionSlots      = 0;

        pCaps->MaxPShaderInstructionsExecuted    = 0;
        pCaps->MaxPixelShader30InstructionSlots  = 0;
    }

4227 4228 4229 4230 4231 4232 4233 4234 4235
    if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
        /* OpenGL supports all the formats below, perhaps not always
         * without conversion, but it supports them.
         * Further GLSL doesn't seem to have an official unsigned type so
         * don't advertise it yet as I'm not sure how we handle it.
         * We might need to add some clamping in the shader engine to
         * support it.
         * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
        pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4    |
4236 4237 4238
                           WINED3DDTCAPS_UBYTE4N   |
                           WINED3DDTCAPS_SHORT2N   |
                           WINED3DDTCAPS_SHORT4N;
4239
        if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
4240 4241
            pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
                                WINED3DDTCAPS_FLOAT16_4;
4242
        }
4243 4244 4245
    } else
        pCaps->DeclTypes                         = 0;

4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274
    /* Set DirectDraw helper Caps */
    ckey_caps =                         WINEDDCKEYCAPS_DESTBLT              |
                                        WINEDDCKEYCAPS_SRCBLT;
    fx_caps =                           WINEDDFXCAPS_BLTALPHA               |
                                        WINEDDFXCAPS_BLTMIRRORLEFTRIGHT     |
                                        WINEDDFXCAPS_BLTMIRRORUPDOWN        |
                                        WINEDDFXCAPS_BLTROTATION90          |
                                        WINEDDFXCAPS_BLTSHRINKX             |
                                        WINEDDFXCAPS_BLTSHRINKXN            |
                                        WINEDDFXCAPS_BLTSHRINKY             |
                                        WINEDDFXCAPS_BLTSHRINKXN            |
                                        WINEDDFXCAPS_BLTSTRETCHX            |
                                        WINEDDFXCAPS_BLTSTRETCHXN           |
                                        WINEDDFXCAPS_BLTSTRETCHY            |
                                        WINEDDFXCAPS_BLTSTRETCHYN;
    blit_caps =                         WINEDDCAPS_BLT                      |
                                        WINEDDCAPS_BLTCOLORFILL             |
                                        WINEDDCAPS_BLTDEPTHFILL             |
                                        WINEDDCAPS_BLTSTRETCH               |
                                        WINEDDCAPS_CANBLTSYSMEM             |
                                        WINEDDCAPS_CANCLIP                  |
                                        WINEDDCAPS_CANCLIPSTRETCHED         |
                                        WINEDDCAPS_COLORKEY                 |
                                        WINEDDCAPS_COLORKEYHWASSIST         |
                                        WINEDDCAPS_ALIGNBOUNDARYSRC;

    /* Fill the ddraw caps structure */
    pCaps->DirectDrawCaps.Caps =        WINEDDCAPS_GDI                      |
                                        WINEDDCAPS_PALETTE                  |
4275
                                        blit_caps;
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299
    pCaps->DirectDrawCaps.Caps2 =       WINEDDCAPS2_CERTIFIED                |
                                        WINEDDCAPS2_NOPAGELOCKREQUIRED       |
                                        WINEDDCAPS2_PRIMARYGAMMA             |
                                        WINEDDCAPS2_WIDESURFACES             |
                                        WINEDDCAPS2_CANRENDERWINDOWED;
    pCaps->DirectDrawCaps.SVBCaps =     blit_caps;
    pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
    pCaps->DirectDrawCaps.SVBFXCaps =   fx_caps;
    pCaps->DirectDrawCaps.VSBCaps =     blit_caps;
    pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
    pCaps->DirectDrawCaps.VSBFXCaps =   fx_caps;
    pCaps->DirectDrawCaps.SSBCaps =     blit_caps;
    pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
    pCaps->DirectDrawCaps.SSBFXCaps =   fx_caps;

    pCaps->DirectDrawCaps.ddsCaps =     WINEDDSCAPS_ALPHA                   |
                                        WINEDDSCAPS_BACKBUFFER              |
                                        WINEDDSCAPS_FLIP                    |
                                        WINEDDSCAPS_FRONTBUFFER             |
                                        WINEDDSCAPS_OFFSCREENPLAIN          |
                                        WINEDDSCAPS_PALETTE                 |
                                        WINEDDSCAPS_PRIMARYSURFACE          |
                                        WINEDDSCAPS_SYSTEMMEMORY            |
                                        WINEDDSCAPS_VIDEOMEMORY             |
4300
                                        WINEDDSCAPS_VISIBLE;
4301
    pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4302 4303

    /* Set D3D caps if OpenGL is available. */
4304 4305
    if (adapter->opengl)
    {
4306 4307 4308 4309 4310 4311 4312
        pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE                |
                                        WINEDDSCAPS_MIPMAP                  |
                                        WINEDDSCAPS_TEXTURE                 |
                                        WINEDDSCAPS_ZBUFFER;
        pCaps->DirectDrawCaps.Caps |=   WINEDDCAPS_3D;
    }

4313
    return WINED3D_OK;
4314 4315
}

4316 4317
/* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
   and fields being inserted in the middle, a new structure is used in place    */
4318 4319 4320 4321
static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
        WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
        IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
{
4322 4323
    IWineD3DDeviceImpl *object  = NULL;
    IWineD3DImpl       *This    = (IWineD3DImpl *)iface;
4324
    struct WineD3DAdapter *adapter = &This->adapters[Adapter];
4325
    WINED3DDISPLAYMODE  mode;
4326
    const struct fragment_pipeline *frag_pipeline = NULL;
4327
    int i;
4328
    struct fragment_caps ffp_caps;
4329
    struct shader_caps shader_caps;
4330
    HRESULT hr;
4331

4332 4333 4334 4335
    /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
     * number and create a device without a 3D adapter for 2D only operation.
     */
    if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4336
        return WINED3DERR_INVALIDCALL;
4337 4338
    }

4339
    /* Create a WineD3DDevice object */
4340 4341
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
    *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4342
    TRACE("Created WineD3DDevice object @ %p\n", object);
4343
    if (NULL == object) {
4344
      return WINED3DERR_OUTOFVIDEOMEMORY;
4345
    }
4346

4347 4348 4349 4350 4351 4352 4353 4354 4355 4356
    /* Set up initial COM information */
    object->lpVtbl  = &IWineD3DDevice_Vtbl;
    object->ref     = 1;
    object->wineD3D = iface;
    object->adapter = This->adapter_count ? adapter : NULL;
    IWineD3D_AddRef(object->wineD3D);
    object->parent  = parent;
    object->device_parent = device_parent;
    list_init(&object->resources);
    list_init(&object->shaders);
4357

4358 4359 4360 4361
    if(This->dxVersion == 7) {
        object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
    } else {
        object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4362
    }
4363
    object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4364

4365 4366
    /* Set the state up as invalid until the device is fully created */
    object->state   = WINED3DERR_DRIVERINTERNALERROR;
4367

4368 4369
    TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
          hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4370

4371 4372 4373 4374 4375
    /* Save the creation parameters */
    object->createParms.AdapterOrdinal = Adapter;
    object->createParms.DeviceType     = DeviceType;
    object->createParms.hFocusWindow   = hFocusWindow;
    object->createParms.BehaviorFlags  = BehaviourFlags;
4376

4377 4378 4379
    /* Initialize other useful values */
    object->adapterNo                    = Adapter;
    object->devType                      = DeviceType;
4380

4381 4382 4383
    select_shader_mode(&adapter->gl_info, DeviceType,
            &object->ps_selected_mode, &object->vs_selected_mode);
    object->shader_backend = select_shader_backend(adapter, DeviceType);
4384

4385 4386 4387 4388 4389
    memset(&shader_caps, 0, sizeof(shader_caps));
    object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
    object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
    object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
    object->vs_clipping = shader_caps.VSClipping;
4390

4391 4392 4393 4394 4395 4396 4397 4398
    memset(&ffp_caps, 0, sizeof(ffp_caps));
    frag_pipeline = select_fragment_implementation(adapter, DeviceType);
    object->frag_pipe = frag_pipeline;
    frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
    object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
    object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
    hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
                        ffp_vertexstate_template, frag_pipeline, misc_state_template);
4399

4400 4401 4402
    if (FAILED(hr)) {
        IWineD3D_Release(object->wineD3D);
        HeapFree(GetProcessHeap(), 0, object);
4403

4404 4405
        return hr;
    }
4406

4407
    object->blitter = select_blit_implementation(adapter, DeviceType);
4408

4409 4410
    /* set the state of the device to valid */
    object->state = WINED3D_OK;
4411

4412 4413
    /* Get the initial screen setup for ddraw */
    IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4414

4415 4416 4417
    object->ddraw_width = mode.Width;
    object->ddraw_height = mode.Height;
    object->ddraw_format = mode.Format;
4418

4419 4420
    for(i = 0; i < PATCHMAP_SIZE; i++) {
        list_init(&object->patches[i]);
4421 4422
    }

4423
    IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4424

4425 4426
    return WINED3D_OK;
}
4427

4428 4429 4430 4431 4432 4433
static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
    IWineD3DImpl *This = (IWineD3DImpl *)iface;
    IUnknown_AddRef(This->parent);
    *pParent = This->parent;
    return WINED3D_OK;
}
4434

4435 4436 4437
ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
    IUnknown* surfaceParent;
    TRACE("(%p) call back\n", pSurface);
4438

4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452
    /* Now, release the parent, which will take care of cleaning up the surface for us */
    IWineD3DSurface_GetParent(pSurface, &surfaceParent);
    IUnknown_Release(surfaceParent);
    return IUnknown_Release(surfaceParent);
}

ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
    IUnknown* volumeParent;
    TRACE("(%p) call back\n", pVolume);

    /* Now, release the parent, which will take care of cleaning up the volume for us */
    IWineD3DVolume_GetParent(pVolume, &volumeParent);
    IUnknown_Release(volumeParent);
    return IUnknown_Release(volumeParent);
4453 4454
}

4455 4456
static void WINE_GLAPI invalid_func(const void *data)
{
4457 4458 4459 4460
    ERR("Invalid vertex attribute function called\n");
    DebugBreak();
}

4461 4462
static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
{
4463 4464 4465 4466
    ERR("Invalid texcoord function called\n");
    DebugBreak();
}

4467 4468 4469
/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
 * the extension detection and are used in drawStridedSlow
 */
4470 4471 4472
static void WINE_GLAPI position_d3dcolor(const void *data)
{
    DWORD pos = *((const DWORD *)data);
4473 4474 4475 4476 4477 4478 4479

    FIXME("Add a test for fixed function position from d3dcolor type\n");
    glVertex4s(D3DCOLOR_B_R(pos),
               D3DCOLOR_B_G(pos),
               D3DCOLOR_B_B(pos),
               D3DCOLOR_B_A(pos));
}
4480 4481 4482 4483

static void WINE_GLAPI position_float4(const void *data)
{
    const GLfloat *pos = data;
4484

4485
    if (pos[3] != 0.0f && pos[3] != 1.0f)
4486
    {
4487
        float w = 1.0f / pos[3];
4488 4489 4490

        glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
    }
4491 4492 4493 4494
    else
    {
        glVertex3fv(pos);
    }
4495 4496
}

4497 4498 4499
static void WINE_GLAPI diffuse_d3dcolor(const void *data)
{
    DWORD diffuseColor = *((const DWORD *)data);
4500 4501 4502 4503 4504 4505 4506

    glColor4ub(D3DCOLOR_B_R(diffuseColor),
               D3DCOLOR_B_G(diffuseColor),
               D3DCOLOR_B_B(diffuseColor),
               D3DCOLOR_B_A(diffuseColor));
}

4507 4508 4509
static void WINE_GLAPI specular_d3dcolor(const void *data)
{
    DWORD specularColor = *((const DWORD *)data);
4510 4511 4512
    GLbyte d[] = {D3DCOLOR_B_R(specularColor),
            D3DCOLOR_B_G(specularColor),
            D3DCOLOR_B_B(specularColor)};
4513

4514
    specular_func_3ubv(d);
4515
}
4516 4517 4518

static void WINE_GLAPI warn_no_specular_func(const void *data)
{
4519 4520 4521
    WARN("GL_EXT_secondary_color not supported\n");
}

4522
static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4523
{
4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558
    position_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
    position_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
    position_funcs[WINED3D_FFP_EMIT_FLOAT3]      = (glAttribFunc)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)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)glColor3fv;
    diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4]       = (glAttribFunc)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)glColor4ubv;
    diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N]      = invalid_func;
    diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N]      = (glAttribFunc)glColor4sv;
    diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N]     = invalid_func;
    diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N]     = (glAttribFunc)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;
4559 4560

    /* No 4 component entry points here */
4561 4562
    specular_funcs[WINED3D_FFP_EMIT_FLOAT1]      = invalid_func;
    specular_funcs[WINED3D_FFP_EMIT_FLOAT2]      = invalid_func;
4563
    if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4564
        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4565
    } else {
4566
        specular_funcs[WINED3D_FFP_EMIT_FLOAT3]  = warn_no_specular_func;
4567
    }
4568
    specular_funcs[WINED3D_FFP_EMIT_FLOAT4]      = invalid_func;
4569
    if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4570
        specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4571
        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4572
    } else {
4573
        specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4574
    }
4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586
    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;
4587 4588 4589 4590

    /* 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.
     */
4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623
    normal_funcs[WINED3D_FFP_EMIT_FLOAT1]         = invalid_func;
    normal_funcs[WINED3D_FFP_EMIT_FLOAT2]         = invalid_func;
    normal_funcs[WINED3D_FFP_EMIT_FLOAT3]         = (glAttribFunc)glNormal3fv;
    normal_funcs[WINED3D_FFP_EMIT_FLOAT4]         = (glAttribFunc)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;
4624 4625
    if (GL_SUPPORT(NV_HALF_FLOAT))
    {
4626
        /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4627 4628
        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4629
    } else {
4630 4631
        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
        multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4632
    }
4633 4634
}

4635 4636
BOOL InitAdapters(IWineD3DImpl *This)
{
4637
    static HMODULE mod_gl;
4638
    BOOL ret;
4639
    int ps_selected_mode, vs_selected_mode;
4640 4641 4642 4643 4644 4645

    /* No need to hold any lock. The calling library makes sure only one thread calls
     * wined3d simultaneously
     */

    TRACE("Initializing adapters\n");
4646 4647 4648 4649 4650 4651 4652

    if(!mod_gl) {
#ifdef USE_WIN32_OPENGL
#define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
        mod_gl = LoadLibraryA("opengl32.dll");
        if(!mod_gl) {
            ERR("Can't load opengl32.dll!\n");
4653
            goto nogl_adapter;
4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668
        }
#else
#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
        /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
        mod_gl = GetModuleHandleA("gdi32.dll");
#endif
    }

/* Load WGL core functions from opengl32.dll */
#define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
    WGL_FUNCS_GEN;
#undef USE_WGL_FUNC

    if(!pwglGetProcAddress) {
        ERR("Unable to load wglGetProcAddress!\n");
4669
        goto nogl_adapter;
4670 4671
    }

4672
/* Dynamically load all GL core functions */
4673 4674 4675
    GL_FUNCS_GEN;
#undef USE_GL_FUNC

4676 4677 4678
    /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
     * otherwise because we have to use winex11.drv's override
     */
4679 4680 4681 4682 4683 4684 4685
#ifdef USE_WIN32_OPENGL
    glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
    glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
#else
    glFinish = (void*)pwglGetProcAddress("wglFinish");
    glFlush = (void*)pwglGetProcAddress("wglFlush");
#endif
4686

4687 4688 4689
    glEnableWINE = glEnable;
    glDisableWINE = glDisable;

4690 4691
    /* For now only one default adapter */
    {
4692 4693
        struct WineD3DAdapter *adapter = &This->adapters[0];
        const WineD3D_GL_Info *gl_info = &adapter->gl_info;
4694
        struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4695 4696
        int iPixelFormat;
        int res;
4697
        int i;
4698
        WineD3D_PixelFormat *cfgs;
4699
        DISPLAY_DEVICEW DisplayDevice;
4700
        HDC hdc;
4701

4702
        TRACE("Initializing default adapter\n");
4703 4704 4705
        adapter->num = 0;
        adapter->monitorPoint.x = -1;
        adapter->monitorPoint.y = -1;
4706

4707 4708
        if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
        {
4709
            ERR("Failed to get a gl context for default adapter\n");
4710
            goto nogl_adapter;
4711 4712
        }

4713
        ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4714
        if(!ret) {
4715
            ERR("Failed to initialize gl caps for default adapter\n");
4716
            WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4717
            goto nogl_adapter;
4718
        }
4719
        ret = initPixelFormats(&adapter->gl_info);
4720 4721
        if(!ret) {
            ERR("Failed to init gl formats\n");
4722
            WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4723
            goto nogl_adapter;
4724 4725
        }

4726
        hdc = fake_gl_ctx.dc;
4727

4728 4729
        adapter->driver = "Display";
        adapter->description = "Direct3D HAL";
4730

4731 4732
        /* Use the VideoRamSize registry setting when set */
        if(wined3d_settings.emulated_textureram)
4733
            adapter->TextureRam = wined3d_settings.emulated_textureram;
4734
        else
4735 4736 4737
            adapter->TextureRam = adapter->gl_info.vidmem;
        adapter->UsedTextureRam = 0;
        TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4738

4739 4740 4741 4742
        /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
        DisplayDevice.cb = sizeof(DisplayDevice);
        EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
        TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4743
        strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4744

4745
        if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4746
        {
4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770
            int attribute;
            int attribs[10];
            int values[10];
            int nAttribs = 0;

            attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
            GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));

            adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
            cfgs = adapter->cfgs;
            attribs[nAttribs++] = WGL_RED_BITS_ARB;
            attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
            attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
            attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
            attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
            attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
            attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
            attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
            attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
            attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;

            for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
            {
                res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4771

4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808
                if(!res)
                    continue;

                /* Cache the pixel format */
                cfgs->iPixelFormat = iPixelFormat;
                cfgs->redSize = values[0];
                cfgs->greenSize = values[1];
                cfgs->blueSize = values[2];
                cfgs->alphaSize = values[3];
                cfgs->depthSize = values[4];
                cfgs->stencilSize = values[5];
                cfgs->windowDrawable = values[6];
                cfgs->iPixelType = values[7];
                cfgs->doubleBuffer = values[8];
                cfgs->auxBuffers = values[9];

                cfgs->pbufferDrawable = FALSE;
                /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
                if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
                    int attrib = WGL_DRAW_TO_PBUFFER_ARB;
                    int value;
                    if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
                        cfgs->pbufferDrawable = value;
                }

                cfgs->numSamples = 0;
                /* Check multisample support */
                if(GL_SUPPORT(ARB_MULTISAMPLE)) {
                    int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
                    int value[2];
                    if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
                        /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
                        * value[1] = number of multi sample buffers*/
                        if(value[0])
                            cfgs->numSamples = value[1];
                    }
                }
4809

4810 4811
                TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
                cfgs++;
4812
            }
4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823
        }
        else
        {
            int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
            adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
            adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */

            cfgs = adapter->cfgs;
            for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
            {
                PIXELFORMATDESCRIPTOR ppfd;
4824

4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836
                res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
                if(!res)
                    continue;

                /* We only want HW acceleration using an OpenGL ICD driver.
                 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
                 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
                 */
                if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
                {
                    TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
                    continue;
4837
                }
4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855

                cfgs->iPixelFormat = iPixelFormat;
                cfgs->redSize = ppfd.cRedBits;
                cfgs->greenSize = ppfd.cGreenBits;
                cfgs->blueSize = ppfd.cBlueBits;
                cfgs->alphaSize = ppfd.cAlphaBits;
                cfgs->depthSize = ppfd.cDepthBits;
                cfgs->stencilSize = ppfd.cStencilBits;
                cfgs->pbufferDrawable = 0;
                cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
                cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
                cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
                cfgs->auxBuffers = ppfd.cAuxBuffers;
                cfgs->numSamples = 0;

                TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
                cfgs++;
                adapter->nCfgs++;
4856 4857
            }

4858 4859 4860 4861 4862
            /* Yikes we haven't found any suitable formats. This should only happen in case of GDI software rendering which we can't use anyway as its 3D functionality is very, very limited */
            if(!adapter->nCfgs)
            {
                ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");

4863
                WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4864 4865 4866
                HeapFree(GetProcessHeap(), 0, adapter->cfgs);
                goto nogl_adapter;
            }
4867 4868
        }

4869 4870 4871 4872 4873 4874 4875 4876 4877
        /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
         * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
         * but just fake it using D24(X8?) which is fine. D3D also allows that.
         * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
         * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
         * driver is allowed to consume more bits EXCEPT for stencil bits.
         *
         * Mark an adapter with this broken stencil behavior.
         */
4878 4879 4880
        adapter->brokenStencil = TRUE;
        for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
        {
4881 4882
            /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
            if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4883
                adapter->brokenStencil = FALSE;
4884 4885 4886 4887
                break;
            }
        }

4888
        WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4889

4890 4891 4892 4893
        select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
        select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
        fillGLAttribFuncs(&adapter->gl_info);
        adapter->opengl = TRUE;
4894
    }
4895 4896
    This->adapter_count = 1;
    TRACE("%u adapters successfully initialized\n", This->adapter_count);
4897 4898

    return TRUE;
4899 4900 4901

nogl_adapter:
    /* Initialize an adapter for ddraw-only memory counting */
4902 4903 4904 4905 4906 4907 4908 4909
    memset(This->adapters, 0, sizeof(This->adapters));
    This->adapters[0].num = 0;
    This->adapters[0].opengl = FALSE;
    This->adapters[0].monitorPoint.x = -1;
    This->adapters[0].monitorPoint.y = -1;

    This->adapters[0].driver = "Display";
    This->adapters[0].description = "WineD3D DirectDraw Emulation";
4910
    if(wined3d_settings.emulated_textureram) {
4911
        This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4912
    } else {
4913
        This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4914 4915
    }

4916 4917
    initPixelFormatsNoGL(&This->adapters[0].gl_info);

4918
    This->adapter_count = 1;
4919
    return FALSE;
4920 4921
}

4922 4923 4924 4925
/**********************************************************
 * IWineD3D VTbl follows
 **********************************************************/

4926
const IWineD3DVtbl IWineD3D_Vtbl =
4927
{
4928
    /* IUnknown */
4929 4930 4931
    IWineD3DImpl_QueryInterface,
    IWineD3DImpl_AddRef,
    IWineD3DImpl_Release,
4932
    /* IWineD3D */
4933
    IWineD3DImpl_GetParent,
4934 4935 4936 4937 4938
    IWineD3DImpl_GetAdapterCount,
    IWineD3DImpl_RegisterSoftwareDevice,
    IWineD3DImpl_GetAdapterMonitor,
    IWineD3DImpl_GetAdapterModeCount,
    IWineD3DImpl_EnumAdapterModes,
4939
    IWineD3DImpl_GetAdapterDisplayMode,
4940 4941 4942 4943
    IWineD3DImpl_GetAdapterIdentifier,
    IWineD3DImpl_CheckDeviceMultiSampleType,
    IWineD3DImpl_CheckDepthStencilMatch,
    IWineD3DImpl_CheckDeviceType,
4944 4945
    IWineD3DImpl_CheckDeviceFormat,
    IWineD3DImpl_CheckDeviceFormatConversion,
4946 4947
    IWineD3DImpl_GetDeviceCaps,
    IWineD3DImpl_CreateDevice
4948
};