directx.c 157 KB
Newer Older
1 2 3 4
/*
 * Copyright 2002-2004 Jason Edmeades
 * Copyright 2003-2004 Raphael Junqueira
 * Copyright 2004 Christian Costa
Oliver Stieber's avatar
Oliver Stieber committed
5
 * Copyright 2005 Oliver Stieber
6
 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
7
 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * 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
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 23 24
 */

#include "config.h"
25

26
#include "wined3d_private.h"
27
#include "winternl.h"
28 29

WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30
WINE_DECLARE_DEBUG_CHANNEL(winediag);
31

32
#define DEFAULT_REFRESH_RATE 0
33

34 35
enum wined3d_driver_model
{
36
    DRIVER_MODEL_GENERIC,
37 38 39 40 41 42
    DRIVER_MODEL_WIN9X,
    DRIVER_MODEL_NT40,
    DRIVER_MODEL_NT5X,
    DRIVER_MODEL_NT6X
};

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

46 47 48 49
/**********************************************************
 * Utility functions follow
 **********************************************************/

50
const struct min_lookup minMipLookup[] =
51
{
52
    /* NONE         POINT                       LINEAR */
53
    {{GL_NEAREST,   GL_NEAREST,                 GL_NEAREST}},               /* NONE */
54 55
    {{GL_NEAREST,   GL_NEAREST_MIPMAP_NEAREST,  GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
    {{GL_LINEAR,    GL_LINEAR_MIPMAP_NEAREST,   GL_LINEAR_MIPMAP_LINEAR}},  /* LINEAR */
56
};
57

58 59
const GLenum magLookup[] =
{
60 61
    /* NONE     POINT       LINEAR */
    GL_NEAREST, GL_NEAREST, GL_LINEAR,
62 63
};

64 65 66 67 68 69 70 71 72 73
void CDECL wined3d_output_release_ownership(const struct wined3d_output *output)
{
    D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0};

    TRACE("output %p.\n", output);

    set_owner_desc.hDevice = output->kmt_device;
    D3DKMTSetVidPnSourceOwner(&set_owner_desc);
}

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
HRESULT CDECL wined3d_output_take_ownership(const struct wined3d_output *output, BOOL exclusive)
{
    D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc;
    D3DKMT_VIDPNSOURCEOWNER_TYPE owner_type;
    NTSTATUS status;

    TRACE("output %p, exclusive %#x.\n", output, exclusive);

    owner_type = exclusive ? D3DKMT_VIDPNSOURCEOWNER_EXCLUSIVE : D3DKMT_VIDPNSOURCEOWNER_SHARED;
    set_owner_desc.pType = &owner_type;
    set_owner_desc.pVidPnSourceId = &output->vidpn_source_id;
    set_owner_desc.VidPnSourceCount = 1;
    set_owner_desc.hDevice = output->kmt_device;
    status = D3DKMTSetVidPnSourceOwner(&set_owner_desc);

    switch (status)
    {
        case STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE:
            return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
        case STATUS_INVALID_PARAMETER:
            return E_INVALIDARG;
        case STATUS_PROCEDURE_NOT_FOUND:
            return E_NOINTERFACE;
        case STATUS_SUCCESS:
            return S_OK;
        default:
            FIXME("Unhandled error %#x.\n", status);
            return E_FAIL;
    }
}

105 106 107 108 109 110 111 112 113 114 115 116 117
static void wined3d_output_cleanup(const struct wined3d_output *output)
{
    D3DKMT_DESTROYDEVICE destroy_device_desc;
    D3DKMT_CLOSEADAPTER close_adapter_desc;

    TRACE("output %p.\n", output);

    destroy_device_desc.hDevice = output->kmt_device;
    D3DKMTDestroyDevice(&destroy_device_desc);
    close_adapter_desc.hAdapter = output->kmt_adapter;
    D3DKMTCloseAdapter(&close_adapter_desc);
}

118 119
static HRESULT wined3d_output_init(struct wined3d_output *output, unsigned int ordinal,
        struct wined3d_adapter *adapter, const WCHAR *device_name)
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
{
    D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc;
    D3DKMT_CREATEDEVICE create_device_desc = {{0}};
    D3DKMT_CLOSEADAPTER close_adapter_desc;

    TRACE("output %p, device_name %s.\n", output, wine_dbgstr_w(device_name));

    lstrcpyW(open_adapter_desc.DeviceName, device_name);
    if (D3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_desc))
        return E_INVALIDARG;

    create_device_desc.u.hAdapter = open_adapter_desc.hAdapter;
    if (D3DKMTCreateDevice(&create_device_desc))
    {
        close_adapter_desc.hAdapter = open_adapter_desc.hAdapter;
        D3DKMTCloseAdapter(&close_adapter_desc);
        return E_FAIL;
    }

139
    output->ordinal = ordinal;
140 141
    lstrcpyW(output->device_name, device_name);
    output->adapter = adapter;
142
    output->screen_format = WINED3DFMT_UNKNOWN;
143 144 145 146 147 148 149
    output->kmt_adapter = open_adapter_desc.hAdapter;
    output->kmt_device = create_device_desc.hDevice;
    output->vidpn_source_id = open_adapter_desc.VidPnSourceId;

    return WINED3D_OK;
}

150
/* Adjust the amount of used texture memory */
151
UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount)
152
{
153 154 155 156 157
    adapter->vram_bytes_used += amount;
    TRACE("Adjusted used adapter memory by 0x%s to 0x%s.\n",
            wine_dbgstr_longlong(amount),
            wine_dbgstr_longlong(adapter->vram_bytes_used));
    return adapter->vram_bytes_used;
158
}
159

160 161 162 163 164 165 166 167 168
ssize_t adapter_adjust_mapped_memory(struct wined3d_adapter *adapter, ssize_t size)
{
    /* Note that this needs to be thread-safe; the Vulkan adapter may map from
     * client threads. */
    ssize_t ret = InterlockedExchangeAddSizeT(&adapter->mapped_size, size) + size;
    TRACE("Adjusted mapped adapter memory by %zd to %zd.\n", size, ret);
    return ret;
}

169
void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
170
{
171 172 173 174 175
    unsigned int output_idx;

    for (output_idx = 0; output_idx < adapter->output_count; ++output_idx)
        wined3d_output_cleanup(&adapter->outputs[output_idx]);
    heap_free(adapter->outputs);
176
    heap_free(adapter->formats);
177 178
}

179
ULONG CDECL wined3d_incref(struct wined3d *wined3d)
180
{
181
    ULONG refcount = InterlockedIncrement(&wined3d->ref);
182

183
    TRACE("%p increasing refcount to %u.\n", wined3d, refcount);
184

185
    return refcount;
186 187
}

188 189 190 191 192
ULONG CDECL wined3d_decref(struct wined3d *wined3d)
{
    ULONG refcount = InterlockedDecrement(&wined3d->ref);

    TRACE("%p decreasing refcount to %u.\n", wined3d, refcount);
193

194
    if (!refcount)
195
    {
196 197
        unsigned int i;

198
        wined3d_mutex_lock();
199
        for (i = 0; i < wined3d->adapter_count; ++i)
200
        {
201 202 203
            struct wined3d_adapter *adapter = wined3d->adapters[i];

            adapter->adapter_ops->adapter_destroy(adapter);
204
        }
205
        heap_free(wined3d);
206
        wined3d_mutex_unlock();
207
    }
208

209
    return refcount;
210 211
}

212 213
/* Certain applications (e.g. Steam) complain if we report an outdated driver
 * version.
214 215 216
 *
 * The driver version has the form "x.y.z.w".
 *
217
 * "x" is the Windows version / driver model the driver is meant for:
218 219
 *  4 -> 95/98/NT4
 *  5 -> 2000
220 221 222 223 224 225 226 227 228 229 230 231
 *  6 -> XP
 *  7 -> Vista - WDDM 1.0
 *  8 -> Windows 7 - WDDM 1.1
 *  9 -> Windows 8 - WDDM 1.2
 * 10 -> Windows 8.1 - WDDM 1.3
 * 20 -> Windows 10 - WDDM 2.0
 * 21 -> Windows 10 Anniversary Update - WDDM 2.1
 * 22 -> Windows 10 Creators Update - WDDM 2.2
 * 23 -> Windows 10 Fall Creators Update - WDDM 2.3
 * 24 -> Windows 10 April 2018 Update - WDDM 2.4
 * 25 -> Windows 10 October 2018 Update - WDDM 2.5
 * 26 -> Windows 10 May 2019 Update - WDDM 2.6
232
 *
233 234 235 236 237 238 239 240 241 242 243 244
 * "y" is the maximum Direct3D version / feature level the driver supports.
 * 11 -> 6
 * 12 -> 7
 * 13 -> 8
 * 14 -> 9
 * 15 -> 10_0
 * 16 -> 10_1
 * 17 -> 11_0
 * 18 -> 11_1
 * 19 -> 12_0
 * 20 -> 12_1
 * 21 -> 12_x
245 246 247 248
 *
 * "z" is the subversion number.
 *
 * "w" is the vendor specific driver build number.
249 250 251 252 253 254
 *
 * In practice the reported version is tied to the driver, not the actual
 * Windows version or feature level. E.g. NVIDIA driver 445.87 advertises the
 * exact same version 26.21.14.4587 on Windows 7 as it does on Windows 10
 * (it's in fact the same driver). Similarly for driver 310.90 that advertises
 * itself as 9.18.13.1090 on Windows Vista with a GeForce 9600M. */
255

256
struct driver_version_information
257
{
258 259 260 261 262 263
    enum wined3d_display_driver driver;
    enum wined3d_driver_model driver_model;
    const char *driver_name;            /* name of Windows driver */
    WORD subversion;                    /* subversion word ('z'), contained in high word of DriverVersion.LowPart */
    WORD build;                         /* build number ('w'), contained in low word of DriverVersion.LowPart */
};
264

265 266
/* The driver version table contains driver information for different devices on several OS versions. */
static const struct driver_version_information driver_version_table[] =
267
{
268 269 270 271 272
    /* AMD
     * - Radeon HD2x00 (R600) and up supported by current drivers.
     * - Radeon 9500 (R300) - X1*00 (R5xx) supported up to Catalyst 9.3 (Linux) and 10.2 (XP/Vista/Win7)
     * - Radeon 7xxx (R100) - 9250 (RV250) supported up to Catalyst 6.11 (XP)
     * - Rage 128 supported up to XP, latest official build 6.13.3279 dated October 2001 */
273 274 275 276 277 278
    {DRIVER_AMD_RAGE_128PRO,    DRIVER_MODEL_NT5X,  "ati2dvaa.dll",  3279,    0},
    {DRIVER_AMD_R100,           DRIVER_MODEL_NT5X,  "ati2dvag.dll",    10, 6614},
    {DRIVER_AMD_R300,           DRIVER_MODEL_NT5X,  "ati2dvag.dll",    10, 6764},
    {DRIVER_AMD_R600,           DRIVER_MODEL_NT5X,  "ati2dvag.dll",    10, 1280},
    {DRIVER_AMD_R300,           DRIVER_MODEL_NT6X,  "atiumdag.dll",    10, 741 },
    {DRIVER_AMD_R600,           DRIVER_MODEL_NT6X,  "atiumdag.dll",    10, 1280},
279
    {DRIVER_AMD_RX,             DRIVER_MODEL_NT6X,  "aticfx32.dll", 15002,   61},
280

281 282 283 284
    /* Intel
     * The drivers are unified but not all versions support all GPUs. At some point the 2k/xp
     * drivers used ialmrnt5.dll for GMA800/GMA900 but at some point the file was renamed to
     * igxprd32.dll but the GMA800 driver was never updated. */
285 286 287 288 289 290 291
    {DRIVER_INTEL_GMA800,       DRIVER_MODEL_NT5X,  "ialmrnt5.dll",    10, 3889},
    {DRIVER_INTEL_GMA900,       DRIVER_MODEL_NT5X,  "igxprd32.dll",    10, 4764},
    {DRIVER_INTEL_GMA950,       DRIVER_MODEL_NT5X,  "igxprd32.dll",    10, 4926},
    {DRIVER_INTEL_GMA3000,      DRIVER_MODEL_NT5X,  "igxprd32.dll",    10, 5218},
    {DRIVER_INTEL_GMA950,       DRIVER_MODEL_NT6X,  "igdumd32.dll",    10, 1504},
    {DRIVER_INTEL_GMA3000,      DRIVER_MODEL_NT6X,  "igdumd32.dll",    10, 1666},
    {DRIVER_INTEL_HD4000,       DRIVER_MODEL_NT6X,  "igdumdim32.dll",  15, 4352},
292

293 294 295 296 297 298 299
    /* Nvidia
     * - Geforce8 and newer is supported by the current 340.52 driver on XP-Win8
     * - Geforce6 and 7 support is up to 307.83 on XP-Win8
     * - GeforceFX support is up to 173.x on <= XP
     * - Geforce2MX/3/4 up to 96.x on <= XP
     * - TNT/Geforce1/2 up to 71.x on <= XP
     * All version numbers used below are from the Linux nvidia drivers. */
300 301 302 303 304 305 306
    {DRIVER_NVIDIA_TNT,         DRIVER_MODEL_NT5X,  "nv4_disp.dll",    10, 7186},
    {DRIVER_NVIDIA_GEFORCE2MX,  DRIVER_MODEL_NT5X,  "nv4_disp.dll",    10, 9371},
    {DRIVER_NVIDIA_GEFORCEFX,   DRIVER_MODEL_NT5X,  "nv4_disp.dll",    11, 7516},
    {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT5X,  "nv4_disp.dll",    13,  783},
    {DRIVER_NVIDIA_GEFORCE8,    DRIVER_MODEL_NT5X,  "nv4_disp.dll",    13, 4052},
    {DRIVER_NVIDIA_GEFORCE6,    DRIVER_MODEL_NT6X,  "nvd3dum.dll",     13,  783},
    {DRIVER_NVIDIA_GEFORCE8,    DRIVER_MODEL_NT6X,  "nvd3dum.dll",     13, 4052},
307 308
    {DRIVER_NVIDIA_FERMI,       DRIVER_MODEL_NT6X,  "nvd3dum.dll",     13, 9135},
    {DRIVER_NVIDIA_KEPLER,      DRIVER_MODEL_NT6X,  "nvd3dum.dll",     14, 4587},
309

310
    /* Red Hat */
311
    {DRIVER_REDHAT_VIRGL,       DRIVER_MODEL_GENERIC, "virgl.dll",      0,    0},
312

313
    /* VMware */
314
    {DRIVER_VMWARE,             DRIVER_MODEL_NT5X,  "vm3dum.dll",       1, 1134},
315 316

    /* Wine */
317
    {DRIVER_WINE,               DRIVER_MODEL_GENERIC, "wined3d.dll",    0,    0},
318
};
319

320 321 322
/* The amount of video memory stored in the gpu description table is the minimum amount of video memory
 * found on a board containing a specific GPU. */
static const struct wined3d_gpu_description gpu_description_table[] =
323
{
324
    /* Nvidia cards */
325
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_128,           "NVIDIA RIVA 128",                  DRIVER_NVIDIA_TNT,       4   },
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT,           "NVIDIA RIVA TNT",                  DRIVER_NVIDIA_TNT,       16  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_RIVA_TNT2,          "NVIDIA RIVA TNT2/TNT2 Pro",        DRIVER_NVIDIA_TNT,       32  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE,            "NVIDIA GeForce 256",               DRIVER_NVIDIA_TNT,       32  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2,           "NVIDIA GeForce2 GTS/GeForce2 Pro", DRIVER_NVIDIA_TNT,       32  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE2_MX,        "NVIDIA GeForce2 MX/MX 400",        DRIVER_NVIDIA_GEFORCE2MX,32  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE3,           "NVIDIA GeForce3",                  DRIVER_NVIDIA_GEFORCE2MX,64  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_MX,        "NVIDIA GeForce4 MX 460",           DRIVER_NVIDIA_GEFORCE2MX,64  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE4_TI4200,    "NVIDIA GeForce4 Ti 4200",          DRIVER_NVIDIA_GEFORCE2MX,64, },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5200,     "NVIDIA GeForce FX 5200",           DRIVER_NVIDIA_GEFORCEFX, 64  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5600,     "NVIDIA GeForce FX 5600",           DRIVER_NVIDIA_GEFORCEFX, 128 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCEFX_5800,     "NVIDIA GeForce FX 5800",           DRIVER_NVIDIA_GEFORCEFX, 256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6200,       "NVIDIA GeForce 6200",              DRIVER_NVIDIA_GEFORCE6,  64  },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6600GT,     "NVIDIA GeForce 6600 GT",           DRIVER_NVIDIA_GEFORCE6,  128 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_6800,       "NVIDIA GeForce 6800",              DRIVER_NVIDIA_GEFORCE6,  128 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7300,       "NVIDIA GeForce Go 7300",           DRIVER_NVIDIA_GEFORCE6,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7400,       "NVIDIA GeForce Go 7400",           DRIVER_NVIDIA_GEFORCE6,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7600,       "NVIDIA GeForce 7600 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_7800GT,     "NVIDIA GeForce 7800 GT",           DRIVER_NVIDIA_GEFORCE6,  256 },
344
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8200,       "NVIDIA GeForce 8200",              DRIVER_NVIDIA_GEFORCE8,  512 },
345 346
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8300GS,     "NVIDIA GeForce 8300 GS",           DRIVER_NVIDIA_GEFORCE8,  128 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8400GS,     "NVIDIA GeForce 8400 GS",           DRIVER_NVIDIA_GEFORCE8,  128 },
347
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8500GT,     "NVIDIA GeForce 8500 GT",           DRIVER_NVIDIA_GEFORCE8,  256 },
348 349 350 351 352 353 354 355 356
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600GT,     "NVIDIA GeForce 8600 GT",           DRIVER_NVIDIA_GEFORCE8,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8600MGT,    "NVIDIA GeForce 8600M GT",          DRIVER_NVIDIA_GEFORCE8,  512 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8800GTS,    "NVIDIA GeForce 8800 GTS",          DRIVER_NVIDIA_GEFORCE8,  320 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_8800GTX,    "NVIDIA GeForce 8800 GTX",          DRIVER_NVIDIA_GEFORCE8,  768 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9200,       "NVIDIA GeForce 9200",              DRIVER_NVIDIA_GEFORCE8,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9300,       "NVIDIA GeForce 9300",              DRIVER_NVIDIA_GEFORCE8,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9400M,      "NVIDIA GeForce 9400M",             DRIVER_NVIDIA_GEFORCE8,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9400GT,     "NVIDIA GeForce 9400 GT",           DRIVER_NVIDIA_GEFORCE8,  256 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9500GT,     "NVIDIA GeForce 9500 GT",           DRIVER_NVIDIA_GEFORCE8,  256 },
357
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9600GT,     "NVIDIA GeForce 9600 GT",           DRIVER_NVIDIA_GEFORCE8,  512 },
358
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9700MGT,    "NVIDIA GeForce 9700M GT",          DRIVER_NVIDIA_GEFORCE8,  512 },
359 360 361 362
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_9800GT,     "NVIDIA GeForce 9800 GT",           DRIVER_NVIDIA_GEFORCE8,  512 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_210,        "NVIDIA GeForce 210",               DRIVER_NVIDIA_GEFORCE8,  512 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT220,      "NVIDIA GeForce GT 220",            DRIVER_NVIDIA_GEFORCE8,  512 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT240,      "NVIDIA GeForce GT 240",            DRIVER_NVIDIA_GEFORCE8,  512 },
363
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS250,     "NVIDIA GeForce GTS 250",           DRIVER_NVIDIA_GEFORCE8,  1024},
364 365 366 367 368 369 370 371 372
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX260,     "NVIDIA GeForce GTX 260",           DRIVER_NVIDIA_GEFORCE8,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX275,     "NVIDIA GeForce GTX 275",           DRIVER_NVIDIA_GEFORCE8,  896 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX280,     "NVIDIA GeForce GTX 280",           DRIVER_NVIDIA_GEFORCE8,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_315M,       "NVIDIA GeForce 315M",              DRIVER_NVIDIA_GEFORCE8,  512 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_320M,       "NVIDIA GeForce 320M",              DRIVER_NVIDIA_GEFORCE8,  256},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT320M,     "NVIDIA GeForce GT 320M",           DRIVER_NVIDIA_GEFORCE8,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT325M,     "NVIDIA GeForce GT 325M",           DRIVER_NVIDIA_GEFORCE8,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT330,      "NVIDIA GeForce GT 330",            DRIVER_NVIDIA_GEFORCE8,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS350M,    "NVIDIA GeForce GTS 350M",          DRIVER_NVIDIA_GEFORCE8,  1024},
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_410M,       "NVIDIA GeForce 410M",              DRIVER_NVIDIA_FERMI,  512},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT420,      "NVIDIA GeForce GT 420",            DRIVER_NVIDIA_FERMI,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT425M,     "NVIDIA GeForce GT 425M",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT430,      "NVIDIA GeForce GT 430",            DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT440,      "NVIDIA GeForce GT 440",            DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTS450,     "NVIDIA GeForce GTS 450",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX460,     "NVIDIA GeForce GTX 460",           DRIVER_NVIDIA_FERMI,  768 },
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX460M,    "NVIDIA GeForce GTX 460M",          DRIVER_NVIDIA_FERMI,  1536},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX465,     "NVIDIA GeForce GTX 465",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX470,     "NVIDIA GeForce GTX 470",           DRIVER_NVIDIA_FERMI,  1280},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX480,     "NVIDIA GeForce GTX 480",           DRIVER_NVIDIA_FERMI,  1536},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT520,      "NVIDIA GeForce GT 520",            DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT525M,     "NVIDIA GeForce GT 525M",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT540M,     "NVIDIA GeForce GT 540M",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX550,     "NVIDIA GeForce GTX 550 Ti",        DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT555M,     "NVIDIA GeForce GT 555M",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX560TI,   "NVIDIA GeForce GTX 560 Ti",        DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX560M,    "NVIDIA GeForce GTX 560M",          DRIVER_NVIDIA_FERMI,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX560,     "NVIDIA GeForce GTX 560",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX570,     "NVIDIA GeForce GTX 570",           DRIVER_NVIDIA_FERMI,  1280},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX580,     "NVIDIA GeForce GTX 580",           DRIVER_NVIDIA_FERMI,  1536},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT610,      "NVIDIA GeForce GT 610",            DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630,      "NVIDIA GeForce GT 630",            DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT630M,     "NVIDIA GeForce GT 630M",           DRIVER_NVIDIA_FERMI,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT640,      "NVIDIA GeForce GT 640",            DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT640M,     "NVIDIA GeForce GT 640M",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT650M,     "NVIDIA GeForce GT 650M",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650,     "NVIDIA GeForce GTX 650",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX650TI,   "NVIDIA GeForce GTX 650 Ti",        DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660,     "NVIDIA GeForce GTX 660",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660M,    "NVIDIA GeForce GTX 660M",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX660TI,   "NVIDIA GeForce GTX 660 Ti",        DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670,     "NVIDIA GeForce GTX 670",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX670MX,   "NVIDIA GeForce GTX 670MX",         DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX675MX_1, "NVIDIA GeForce GTX 675MX",         DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX675MX_2, "NVIDIA GeForce GTX 675MX",         DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX680,     "NVIDIA GeForce GTX 680",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX690,     "NVIDIA GeForce GTX 690",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT720,      "NVIDIA GeForce GT 720",            DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT730,      "NVIDIA GeForce GT 730",            DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT730M,     "NVIDIA GeForce GT 730M",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT740M,     "NVIDIA GeForce GT 740M",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT750M,     "NVIDIA GeForce GT 750M",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT755M,     "NVIDIA GeForce GT 755M",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX750,     "NVIDIA GeForce GTX 750",           DRIVER_NVIDIA_KEPLER,  1024},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX750TI,   "NVIDIA GeForce GTX 750 Ti",        DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX760,     "NVIDIA GeForce GTX 760",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX760TI,   "NVIDIA GeForce GTX 760 Ti",        DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX765M,    "NVIDIA GeForce GTX 765M",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770M,    "NVIDIA GeForce GTX 770M",          DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX770,     "NVIDIA GeForce GTX 770",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX775M,    "NVIDIA GeForce GTX 775M",          DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780,     "NVIDIA GeForce GTX 780",           DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780M,    "NVIDIA GeForce GTX 780M",          DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX780TI,   "NVIDIA GeForce GTX 780 Ti",        DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTXTITAN,   "NVIDIA GeForce GTX TITAN",         DRIVER_NVIDIA_KEPLER,  6144},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTXTITANB,  "NVIDIA GeForce GTX TITAN Black",   DRIVER_NVIDIA_KEPLER,  6144},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTXTITANX,  "NVIDIA GeForce GTX TITAN X",       DRIVER_NVIDIA_KEPLER,  12288},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTXTITANZ,  "NVIDIA GeForce GTX TITAN Z",       DRIVER_NVIDIA_KEPLER,  12288},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_820M,       "NVIDIA GeForce 820M",              DRIVER_NVIDIA_FERMI,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_830M,       "NVIDIA GeForce 830M",              DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_840M,       "NVIDIA GeForce 840M",              DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_845M,       "NVIDIA GeForce 845M",              DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX850M,    "NVIDIA GeForce GTX 850M",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX860M,    "NVIDIA GeForce GTX 860M",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX870M,    "NVIDIA GeForce GTX 870M",          DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX880M,    "NVIDIA GeForce GTX 880M",          DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_940M,       "NVIDIA GeForce 940M",              DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX950,     "NVIDIA GeForce GTX 950",           DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX950M,    "NVIDIA GeForce GTX 950M",          DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX960,     "NVIDIA GeForce GTX 960",           DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX960M,    "NVIDIA GeForce GTX 960M",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX970,     "NVIDIA GeForce GTX 970",           DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX970M,    "NVIDIA GeForce GTX 970M",          DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980,     "NVIDIA GeForce GTX 980",           DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX980TI,   "NVIDIA GeForce GTX 980 Ti",        DRIVER_NVIDIA_KEPLER,  6144},
449
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GT1030,     "NVIDIA GeForce GT 1030",           DRIVER_NVIDIA_KEPLER,  2048},
450 451 452 453
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1050,    "NVIDIA GeForce GTX 1050",          DRIVER_NVIDIA_KEPLER,  2048},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1050TI,  "NVIDIA GeForce GTX 1050 Ti",       DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1060_3GB,"NVIDIA GeForce GTX 1060 3GB",      DRIVER_NVIDIA_KEPLER,  3072},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1060,    "NVIDIA GeForce GTX 1060",          DRIVER_NVIDIA_KEPLER,  6144},
454
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1060M,   "NVIDIA GeForce GTX 1060M",         DRIVER_NVIDIA_KEPLER,  6144},
455 456
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1070,    "NVIDIA GeForce GTX 1070",          DRIVER_NVIDIA_KEPLER,  8192},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080,    "NVIDIA GeForce GTX 1080",          DRIVER_NVIDIA_KEPLER,  8192},
457
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080M,   "NVIDIA GeForce GTX 1080M",         DRIVER_NVIDIA_KEPLER,  8192},
458 459 460 461 462 463 464 465 466 467
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1080TI,  "NVIDIA GeForce GTX 1080 Ti",       DRIVER_NVIDIA_KEPLER,  11264},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_TITANX_PASCAL,      "NVIDIA TITAN X (Pascal)",          DRIVER_NVIDIA_KEPLER,  12288},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_TITANV,             "NVIDIA TITAN V",                   DRIVER_NVIDIA_KEPLER,  12288},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1650SUPER,"NVIDIA GeForce GTX 1650 SUPER",   DRIVER_NVIDIA_KEPLER,  4096},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1660SUPER,"NVIDIA GeForce GTX 1660 SUPER",   DRIVER_NVIDIA_KEPLER,  6144},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_GTX1660TI,  "NVIDIA GeForce GTX 1660 Ti",       DRIVER_NVIDIA_KEPLER,  6144},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_RTX2060,    "NVIDIA GeForce RTX 2060",          DRIVER_NVIDIA_KEPLER,  6144},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_RTX2070,    "NVIDIA GeForce RTX 2070",          DRIVER_NVIDIA_KEPLER,  8192},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_RTX2080,    "NVIDIA GeForce RTX 2080",          DRIVER_NVIDIA_KEPLER,  8192},
    {HW_VENDOR_NVIDIA,     CARD_NVIDIA_GEFORCE_RTX2080TI,  "NVIDIA GeForce RTX 2080 Ti",       DRIVER_NVIDIA_KEPLER,  11264},
468

469 470 471 472 473 474 475 476 477 478 479 480
    /* AMD cards */
    {HW_VENDOR_AMD,        CARD_AMD_RAGE_128PRO,           "ATI Rage Fury",                    DRIVER_AMD_RAGE_128PRO,  16  },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_7200,           "ATI RADEON 7200 SERIES",           DRIVER_AMD_R100,         32  },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_8500,           "ATI RADEON 8500 SERIES",           DRIVER_AMD_R100,         64  },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_9500,           "ATI Radeon 9500",                  DRIVER_AMD_R300,         64  },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_XPRESS_200M,    "ATI RADEON XPRESS 200M Series",    DRIVER_AMD_R300,         64  },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_X700,           "ATI Radeon X700 SE",               DRIVER_AMD_R300,         128 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_X1600,          "ATI Radeon X1600 Series",          DRIVER_AMD_R300,         128 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2350,         "ATI Mobility Radeon HD 2350",      DRIVER_AMD_R600,         256 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2600,         "ATI Mobility Radeon HD 2600",      DRIVER_AMD_R600,         256 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD2900,         "ATI Radeon HD 2900 XT",            DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3200,         "ATI Radeon HD 3200 Graphics",      DRIVER_AMD_R600,         128 },
481
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD3850,         "ATI Radeon HD 3850 AGP",           DRIVER_AMD_R600,         512 },
482
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4200M,        "ATI Mobility Radeon HD 4200",      DRIVER_AMD_R600,         256 },
483 484 485 486 487 488 489 490 491
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4350,         "ATI Radeon HD 4350",               DRIVER_AMD_R600,         256 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4600,         "ATI Radeon HD 4600 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4700,         "ATI Radeon HD 4700 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD4800,         "ATI Radeon HD 4800 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5400,         "ATI Radeon HD 5400 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5600,         "ATI Radeon HD 5600 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5700,         "ATI Radeon HD 5700 Series",        DRIVER_AMD_R600,         512 },
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5800,         "ATI Radeon HD 5800 Series",        DRIVER_AMD_R600,         1024},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD5900,         "ATI Radeon HD 5900 Series",        DRIVER_AMD_R600,         1024},
492 493
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6300,         "AMD Radeon HD 6300 series Graphics", DRIVER_AMD_R600,       1024},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6400,         "AMD Radeon HD 6400 Series",        DRIVER_AMD_R600,         1024},
494
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6410D,        "AMD Radeon HD 6410D",              DRIVER_AMD_R600,         1024},
495
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6480G,        "AMD Radeon HD 6480G",              DRIVER_AMD_R600,         512 },
496
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6490M,        "AMD Radeon HD 6490M",              DRIVER_AMD_R600,         1024},
497
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6550D,        "AMD Radeon HD 6550D",              DRIVER_AMD_R600,         1024},
498
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6600,         "AMD Radeon HD 6600 Series",        DRIVER_AMD_R600,         1024},
499
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6600M,        "AMD Radeon HD 6600M Series",       DRIVER_AMD_R600,         512 },
500
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6700,         "AMD Radeon HD 6700 Series",        DRIVER_AMD_R600,         1024},
501 502
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6800,         "AMD Radeon HD 6800 Series",        DRIVER_AMD_R600,         1024},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD6900,         "AMD Radeon HD 6900 Series",        DRIVER_AMD_R600,         2048},
503
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7660D,        "AMD Radeon HD 7660D",              DRIVER_AMD_R600,         2048},
504 505
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7700,         "AMD Radeon HD 7700 Series",        DRIVER_AMD_R600,         1024},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7800,         "AMD Radeon HD 7800 Series",        DRIVER_AMD_R600,         2048},
506
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7870,         "AMD Radeon HD 7870 Series",        DRIVER_AMD_R600,         2048},
507
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD7900,         "AMD Radeon HD 7900 Series",        DRIVER_AMD_R600,         2048},
508 509 510 511 512
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8600M,        "AMD Radeon HD 8600M Series",       DRIVER_AMD_R600,         1024},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8670,         "AMD Radeon HD 8670",               DRIVER_AMD_R600,         2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_HD8770,         "AMD Radeon HD 8770",               DRIVER_AMD_R600,         2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R3,             "AMD Radeon HD 8400 / R3 Series",   DRIVER_AMD_R600,         2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R7,             "AMD Radeon(TM) R7 Graphics",       DRIVER_AMD_R600,         2048},
513 514
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_285,         "AMD Radeon R9 285",                DRIVER_AMD_RX,           2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_290,         "AMD Radeon R9 290",                DRIVER_AMD_RX,           4096},
515
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_290X,        "AMD Radeon R9 290X",               DRIVER_AMD_RX,           4096},
516
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_FURY,        "AMD Radeon (TM) R9 Fury Series",   DRIVER_AMD_RX,           4096},
517 518 519
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_M370X,       "AMD Radeon R9 M370X",              DRIVER_AMD_RX,           2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_M380,        "AMD Radeon R9 M380",               DRIVER_AMD_RX,           2048},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_R9_M395X,       "AMD Radeon R9 M395X",              DRIVER_AMD_RX,           4096},
520 521
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_460,         "Radeon(TM) RX 460 Graphics",       DRIVER_AMD_RX,           4096},
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_480,         "Radeon (TM) RX 480 Graphics",      DRIVER_AMD_RX,           4096},
522
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_VEGA_10,     "Radeon RX Vega",                   DRIVER_AMD_RX,           8192},
523
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_VEGA_12,     "Radeon Pro Vega 20",               DRIVER_AMD_RX,           4096},
524
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RAVEN,          "AMD Radeon(TM) Vega 10 Mobile Graphics", DRIVER_AMD_RX,     1024},
525
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_VEGA_20,     "Radeon RX Vega 20",                DRIVER_AMD_RX,           4096},
526
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_NAVI_10,     "Radeon RX 5700 / 5700 XT",         DRIVER_AMD_RX,           8192},
527
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_NAVI_14,     "Radeon RX 5500M",                  DRIVER_AMD_RX,           4096},
528
    {HW_VENDOR_AMD,        CARD_AMD_RADEON_RX_NAVI_21,     "Radeon RX 6800/6800 XT / 6900 XT", DRIVER_AMD_RX,          16384},
529
    {HW_VENDOR_AMD,        CARD_AMD_VANGOGH,               "AMD VANGOGH",                      DRIVER_AMD_RX,           4096},
530

531 532 533
    /* Red Hat */
    {HW_VENDOR_REDHAT,     CARD_REDHAT_VIRGL,              "Red Hat VirtIO GPU",                                        DRIVER_REDHAT_VIRGL,  1024},

534 535 536
    /* VMware */
    {HW_VENDOR_VMWARE,     CARD_VMWARE_SVGA3D,             "VMware SVGA 3D (Microsoft Corporation - WDDM)",             DRIVER_VMWARE,        1024},

537
    /* Intel cards */
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
    {HW_VENDOR_INTEL,      CARD_INTEL_830M,                "Intel(R) 82830M Graphics Controller",                       DRIVER_INTEL_GMA800,  32 },
    {HW_VENDOR_INTEL,      CARD_INTEL_855GM,               "Intel(R) 82852/82855 GM/GME Graphics Controller",           DRIVER_INTEL_GMA800,  32 },
    {HW_VENDOR_INTEL,      CARD_INTEL_845G,                "Intel(R) 845G",                                             DRIVER_INTEL_GMA800,  32 },
    {HW_VENDOR_INTEL,      CARD_INTEL_865G,                "Intel(R) 82865G Graphics Controller",                       DRIVER_INTEL_GMA800,  32 },
    {HW_VENDOR_INTEL,      CARD_INTEL_915G,                "Intel(R) 82915G/GV/910GL Express Chipset Family",           DRIVER_INTEL_GMA900,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_E7221G,              "Intel(R) E7221G",                                           DRIVER_INTEL_GMA900,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_915GM,               "Mobile Intel(R) 915GM/GMS,910GML Express Chipset Family",   DRIVER_INTEL_GMA900,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_945G,                "Intel(R) 945G",                                             DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_945GM,               "Mobile Intel(R) 945GM Express Chipset Family",              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_945GME,              "Intel(R) 945GME",                                           DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_Q35,                 "Intel(R) Q35",                                              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_G33,                 "Intel(R) G33",                                              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_Q33,                 "Intel(R) Q33",                                              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_PNVG,                "Intel(R) IGD",                                              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_PNVM,                "Intel(R) IGD",                                              DRIVER_INTEL_GMA950,  64 },
    {HW_VENDOR_INTEL,      CARD_INTEL_965Q,                "Intel(R) 965Q",                                             DRIVER_INTEL_GMA3000, 128},
    {HW_VENDOR_INTEL,      CARD_INTEL_965G,                "Intel(R) 965G",                                             DRIVER_INTEL_GMA3000, 128},
    {HW_VENDOR_INTEL,      CARD_INTEL_946GZ,               "Intel(R) 946GZ",                                            DRIVER_INTEL_GMA3000, 128},
    {HW_VENDOR_INTEL,      CARD_INTEL_965GM,               "Mobile Intel(R) 965 Express Chipset Family",                DRIVER_INTEL_GMA3000, 128},
    {HW_VENDOR_INTEL,      CARD_INTEL_965GME,              "Intel(R) 965GME",                                           DRIVER_INTEL_GMA3000, 128},
    {HW_VENDOR_INTEL,      CARD_INTEL_GM45,                "Mobile Intel(R) GM45 Express Chipset Family",               DRIVER_INTEL_GMA3000, 512},
    {HW_VENDOR_INTEL,      CARD_INTEL_IGD,                 "Intel(R) Integrated Graphics Device",                       DRIVER_INTEL_GMA3000, 512},
    {HW_VENDOR_INTEL,      CARD_INTEL_G45,                 "Intel(R) G45/G43",                                          DRIVER_INTEL_GMA3000, 512},
    {HW_VENDOR_INTEL,      CARD_INTEL_Q45,                 "Intel(R) Q45/Q43",                                          DRIVER_INTEL_GMA3000, 512},
    {HW_VENDOR_INTEL,      CARD_INTEL_G41,                 "Intel(R) G41",                                              DRIVER_INTEL_GMA3000, 512},
    {HW_VENDOR_INTEL,      CARD_INTEL_B43,                 "Intel(R) B43",                                              DRIVER_INTEL_GMA3000, 512},
564 565 566 567 568 569 570 571
    {HW_VENDOR_INTEL,      CARD_INTEL_ILKD,                "Intel(R) HD Graphics",                                      DRIVER_INTEL_GMA3000, 1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_ILKM,                "Intel(R) HD Graphics",                                      DRIVER_INTEL_GMA3000, 1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_SNBD,                "Intel(R) HD Graphics 3000",                                 DRIVER_INTEL_GMA3000, 1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_SNBM,                "Intel(R) HD Graphics 3000",                                 DRIVER_INTEL_GMA3000, 1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_SNBS,                "Intel(R) HD Graphics Family",                               DRIVER_INTEL_GMA3000, 1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IVBD,                "Intel(R) HD Graphics 4000",                                 DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IVBM,                "Intel(R) HD Graphics 4000",                                 DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IVBS,                "Intel(R) HD Graphics Family",                               DRIVER_INTEL_HD4000,  1536},
572
    {HW_VENDOR_INTEL,      CARD_INTEL_HWD,                 "Intel(R) HD Graphics 4600",                                 DRIVER_INTEL_HD4000,  1536},
573
    {HW_VENDOR_INTEL,      CARD_INTEL_HWM,                 "Intel(R) HD Graphics 4600",                                 DRIVER_INTEL_HD4000,  1536},
574 575
    {HW_VENDOR_INTEL,      CARD_INTEL_HD5000_1,            "Intel(R) HD Graphics 5000",                                 DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD5000_2,            "Intel(R) HD Graphics 5000",                                 DRIVER_INTEL_HD4000,  1536},
576 577 578 579 580 581 582 583 584
    {HW_VENDOR_INTEL,      CARD_INTEL_I5100_1,             "Intel(R) Iris(TM) Graphics 5100",                           DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_I5100_2,             "Intel(R) Iris(TM) Graphics 5100",                           DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_I5100_3,             "Intel(R) Iris(TM) Graphics 5100",                           DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_I5100_4,             "Intel(R) Iris(TM) Graphics 5100",                           DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_1,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_2,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_3,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_4,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  1536},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_5,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  1536},
585
    {HW_VENDOR_INTEL,      CARD_INTEL_IP5200_6,            "Intel(R) Iris(TM) Pro Graphics 5200",                       DRIVER_INTEL_HD4000,  2048},
586 587 588 589 590
    {HW_VENDOR_INTEL,      CARD_INTEL_HD5300,              "Intel(R) HD Graphics 5300",                                 DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD5500,              "Intel(R) HD Graphics 5500",                                 DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD5600,              "Intel(R) HD Graphics 5600",                                 DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD6000,              "Intel(R) HD Graphics 6000",                                 DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_I6100,               "Intel(R) Iris(TM) Graphics 6100",                           DRIVER_INTEL_HD4000,  2048},
591
    {HW_VENDOR_INTEL,      CARD_INTEL_IP6200,              "Intel(R) Iris(TM) Pro Graphics 6200",                       DRIVER_INTEL_HD4000,  2048},
592
    {HW_VENDOR_INTEL,      CARD_INTEL_IPP6300,             "Intel(R) Iris(TM) Pro Graphics P6300",                      DRIVER_INTEL_HD4000,  2048},
593 594 595 596 597 598
    {HW_VENDOR_INTEL,      CARD_INTEL_HD510_1,             "Intel(R) HD Graphics 510",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD510_2,             "Intel(R) HD Graphics 510",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD510_3,             "Intel(R) HD Graphics 510",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD515,               "Intel(R) HD Graphics 515",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD520_1,             "Intel(R) HD Graphics 520",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD520_2,             "Intel(R) HD Graphics 520",                                  DRIVER_INTEL_HD4000,  2048},
599 600
    {HW_VENDOR_INTEL,      CARD_INTEL_HD530_1,             "Intel(R) HD Graphics 530",                                  DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD530_2,             "Intel(R) HD Graphics 530",                                  DRIVER_INTEL_HD4000,  2048},
601 602 603 604 605 606 607 608 609
    {HW_VENDOR_INTEL,      CARD_INTEL_HDP530,              "Intel(R) HD Graphics P530",                                 DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_I540,                "Intel(R) Iris(TM) Graphics 540",                            DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_I550,                "Intel(R) Iris(TM) Graphics 550",                            DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_I555,                "Intel(R) Iris(TM) Graphics 555",                            DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP555,               "Intel(R) Iris(TM) Graphics P555",                           DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP580_1,             "Intel(R) Iris(TM) Pro Graphics 580",                        DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_IP580_2,             "Intel(R) Iris(TM) Pro Graphics 580",                        DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_IPP580_1,            "Intel(R) Iris(TM) Pro Graphics P580",                       DRIVER_INTEL_HD4000,  2048},
    {HW_VENDOR_INTEL,      CARD_INTEL_IPP580_2,            "Intel(R) Iris(TM) Pro Graphics P580",                       DRIVER_INTEL_HD4000,  2048},
610
    {HW_VENDOR_INTEL,      CARD_INTEL_UHD617,              "Intel(R) UHD Graphics 617",                                 DRIVER_INTEL_HD4000,  2048},
611
    {HW_VENDOR_INTEL,      CARD_INTEL_UHD620,              "Intel(R) UHD Graphics 620",                                 DRIVER_INTEL_HD4000,  3072},
612
    {HW_VENDOR_INTEL,      CARD_INTEL_HD615,               "Intel(R) HD Graphics 615",                                  DRIVER_INTEL_HD4000,  2048},
613
    {HW_VENDOR_INTEL,      CARD_INTEL_HD620,               "Intel(R) HD Graphics 620",                                  DRIVER_INTEL_HD4000,  3072},
614 615
    {HW_VENDOR_INTEL,      CARD_INTEL_HD630_1,             "Intel(R) HD Graphics 630",                                  DRIVER_INTEL_HD4000,  3072},
    {HW_VENDOR_INTEL,      CARD_INTEL_HD630_2,             "Intel(R) HD Graphics 630",                                  DRIVER_INTEL_HD4000,  3072},
616
    {HW_VENDOR_INTEL,      CARD_INTEL_UHD630,              "Intel(R) UHD Graphics 630",                                 DRIVER_INTEL_HD4000,  3072},
617 618
};

619 620 621 622 623
static const struct driver_version_information *get_driver_version_info(enum wined3d_display_driver driver,
        enum wined3d_driver_model driver_model)
{
    unsigned int i;

624 625
    TRACE("Looking up version info for driver %#x, driver_model %#x.\n", driver, driver_model);

626
    for (i = 0; i < ARRAY_SIZE(driver_version_table); ++i)
627 628 629
    {
        const struct driver_version_information *entry = &driver_version_table[i];

630 631
        if (entry->driver == driver && (driver_model == DRIVER_MODEL_GENERIC
                || entry->driver_model == driver_model))
632
        {
633 634
            TRACE("Found driver \"%s\", subversion %u, build %u.\n",
                    entry->driver_name, entry->subversion, entry->build);
635 636 637 638 639 640
            return entry;
        }
    }
    return NULL;
}

641
const struct wined3d_gpu_description *wined3d_get_gpu_description(enum wined3d_pci_vendor vendor,
642 643 644 645
        enum wined3d_pci_device device)
{
    unsigned int i;

646
    for (i = 0; i < ARRAY_SIZE(gpu_description_table); ++i)
647
    {
648
        if (vendor == gpu_description_table[i].vendor && device == gpu_description_table[i].device)
649 650 651 652 653 654
            return &gpu_description_table[i];
    }

    return NULL;
}

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
const struct wined3d_gpu_description *wined3d_get_user_override_gpu_description(enum wined3d_pci_vendor vendor,
        enum wined3d_pci_device device)
{
    const struct wined3d_gpu_description *gpu_desc;
    static unsigned int once;

    if (wined3d_settings.pci_vendor_id == PCI_VENDOR_NONE && wined3d_settings.pci_device_id == PCI_DEVICE_NONE)
        return NULL;

    if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
    {
        vendor = wined3d_settings.pci_vendor_id;
        TRACE("Overriding vendor PCI ID with 0x%04x.\n", vendor);
    }
    if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
    {
        device = wined3d_settings.pci_device_id;
        TRACE("Overriding device PCI ID with 0x%04x.\n", device);
    }

    if (!(gpu_desc = wined3d_get_gpu_description(vendor, device)) && !once++)
        ERR_(winediag)("Invalid GPU override %04x:%04x specified, ignoring.\n", vendor, device);

    return gpu_desc;
}

681 682 683 684 685 686 687 688 689 690 691 692
static void wined3d_copy_name(char *dst, const char *src, unsigned int dst_size)
{
    size_t len;

    if (dst_size)
    {
        len = min(strlen(src), dst_size - 1);
        memcpy(dst, src, len);
        memset(&dst[len], 0, dst_size - len);
    }
}

693
bool wined3d_driver_info_init(struct wined3d_driver_info *driver_info,
694 695
        const struct wined3d_gpu_description *gpu_desc, enum wined3d_feature_level feature_level,
        UINT64 vram_bytes, UINT64 sysmem_bytes)
696
{
697
    const struct driver_version_information *version_info;
698
    WORD driver_os_version, driver_feature_level = 10;
699 700 701
    enum wined3d_driver_model driver_model;
    enum wined3d_display_driver driver;
    MEMORYSTATUSEX memory_status;
702
    OSVERSIONINFOW os_version;
703

704 705 706 707 708 709
    memset(&os_version, 0, sizeof(os_version));
    os_version.dwOSVersionInfoSize = sizeof(os_version);
    if (!GetVersionExW(&os_version))
    {
        ERR("Failed to get OS version, reporting 2000/XP.\n");
        driver_os_version = 6;
710
        driver_model = DRIVER_MODEL_NT5X;
711 712 713 714 715 716
    }
    else
    {
        TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
        switch (os_version.dwMajorVersion)
        {
717 718
            case 2:
            case 3:
719
            case 4:
720 721 722
                /* If needed we could distinguish between 9x and NT4, but this code won't make
                 * sense for NT4 since it had no way to obtain this info through DirectDraw 3.0.
                 */
723
                driver_os_version = 4;
724
                driver_model = DRIVER_MODEL_WIN9X;
725 726 727 728
                break;

            case 5:
                driver_os_version = 6;
729
                driver_model = DRIVER_MODEL_NT5X;
730 731 732 733 734 735
                break;

            case 6:
                if (os_version.dwMinorVersion == 0)
                {
                    driver_os_version = 7;
736
                    driver_model = DRIVER_MODEL_NT6X;
737
                }
738 739
                else if (os_version.dwMinorVersion == 1)
                {
740 741 742
                    driver_os_version = 8;
                    driver_model = DRIVER_MODEL_NT6X;
                }
743 744 745 746 747
                else if (os_version.dwMinorVersion == 2)
                {
                    driver_os_version = 9;
                    driver_model = DRIVER_MODEL_NT6X;
                }
748 749
                else
                {
750
                    if (os_version.dwMinorVersion > 3)
751
                    {
752
                        FIXME("Unhandled OS version %u.%u, reporting Windows 8.1.\n",
753 754
                                os_version.dwMajorVersion, os_version.dwMinorVersion);
                    }
755
                    driver_os_version = 10;
756 757 758
                    driver_model = DRIVER_MODEL_NT6X;
                }
                break;
759

760
            case 10:
761
                driver_os_version = 26;
762 763
                driver_model = DRIVER_MODEL_NT6X;
                break;
764

765
            default:
766
                FIXME("Unhandled OS version %u.%u, reporting Windows 7.\n",
767
                        os_version.dwMajorVersion, os_version.dwMinorVersion);
768 769
                driver_os_version = 8;
                driver_model = DRIVER_MODEL_NT6X;
770 771
                break;
        }
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 805 806 807 808 809 810 811 812 813 814 815 816
    TRACE("GPU maximum feature level %#x.\n", feature_level);
    switch (feature_level)
    {
        case WINED3D_FEATURE_LEVEL_NONE:
        case WINED3D_FEATURE_LEVEL_5:
            if (driver_model == DRIVER_MODEL_WIN9X)
                driver_feature_level = 5;
            else
                driver_feature_level = 10;
            break;
        case WINED3D_FEATURE_LEVEL_6:
            driver_feature_level = 11;
            break;
        case WINED3D_FEATURE_LEVEL_7:
            driver_feature_level = 12;
            break;
        case WINED3D_FEATURE_LEVEL_8:
            driver_feature_level = 13;
            break;
        case WINED3D_FEATURE_LEVEL_9_1:
        case WINED3D_FEATURE_LEVEL_9_2:
        case WINED3D_FEATURE_LEVEL_9_3:
            driver_feature_level = 14;
            break;
        case WINED3D_FEATURE_LEVEL_10:
            driver_feature_level = 15;
            break;
        case WINED3D_FEATURE_LEVEL_10_1:
            driver_feature_level = 16;
            break;
        case WINED3D_FEATURE_LEVEL_11:
            driver_feature_level = 17;
            break;
        case WINED3D_FEATURE_LEVEL_11_1:
            /* Advertise support for everything up to FL 12_x. */
            driver_feature_level = 21;
            break;
    }
    if (os_version.dwMajorVersion == 6 && !os_version.dwMinorVersion)
        driver_feature_level = min(driver_feature_level, 18);
    else if (os_version.dwMajorVersion < 6)
        driver_feature_level = min(driver_feature_level, 14);

817 818
    driver_info->vendor = gpu_desc->vendor;
    driver_info->device = gpu_desc->device;
819
    wined3d_copy_name(driver_info->description, gpu_desc->description, ARRAY_SIZE(driver_info->description));
820 821 822
    driver_info->vram_bytes = vram_bytes ? vram_bytes : (UINT64)gpu_desc->vidmem * 1024 * 1024;
    driver = gpu_desc->driver;

823 824 825 826 827 828 829
    if (wined3d_settings.emulated_textureram)
    {
        driver_info->vram_bytes = wined3d_settings.emulated_textureram;
        TRACE("Overriding amount of video memory with 0x%s bytes.\n",
                wine_dbgstr_longlong(driver_info->vram_bytes));
    }

830 831 832 833 834 835
    /**
     * Diablo 2 crashes when the amount of video memory is greater than 0x7fffffff.
     * In order to avoid this application bug we limit the amount of video memory
     * to LONG_MAX for older Windows versions.
     */
    if (driver_model < DRIVER_MODEL_NT6X && driver_info->vram_bytes > LONG_MAX)
836
    {
837 838
        TRACE("Limiting amount of video memory to %#lx bytes for OS version older than Vista.\n", LONG_MAX);
        driver_info->vram_bytes = LONG_MAX;
839 840
    }

841 842 843 844 845 846 847 848 849
    if (!(driver_info->sysmem_bytes = sysmem_bytes))
    {
        driver_info->sysmem_bytes = 64 * 1024 * 1024;
        memory_status.dwLength = sizeof(memory_status);
        if (GlobalMemoryStatusEx(&memory_status))
            driver_info->sysmem_bytes = max(memory_status.ullTotalPhys / 2, driver_info->sysmem_bytes);
        else
            ERR("Failed to get global memory status.\n");
    }
850

851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
    /* Try to obtain driver version information for the current Windows version. This fails in
     * some cases:
     * - the gpu is not available on the currently selected OS version:
     *   - Geforce GTX480 on Win98. When running applications in compatibility mode on Windows,
     *     version information for the current Windows version is returned instead of faked info.
     *     We do the same and assume the default Windows version to emulate is WinXP.
     *
     *   - Videocard is a Riva TNT but winver is set to win7 (there are no drivers for this beast)
     *     For now return the XP driver info. Perhaps later on we should return VESA.
     *
     * - the gpu is not in our database (can happen when the user overrides the vendor_id / device_id)
     *   This could be an indication that our database is not up to date, so this should be fixed.
     */
    if ((version_info = get_driver_version_info(driver, driver_model))
            || (version_info = get_driver_version_info(driver, DRIVER_MODEL_GENERIC)))
866
    {
867
        driver_info->name = version_info->driver_name;
868
        driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_feature_level);
869
        driver_info->version_low = MAKEDWORD_VERSION(version_info->subversion, version_info->build);
870 871

        return true;
872
    }
873 874 875 876

    ERR("No driver version info found for device %04x:%04x, driver model %#x.\n",
            driver_info->vendor, driver_info->device, driver_model);
    return false;
877
}
878

879 880 881
enum wined3d_pci_device wined3d_gpu_from_feature_level(enum wined3d_pci_vendor *vendor,
        enum wined3d_feature_level feature_level)
{
882 883 884 885 886 887
    static const struct wined3d_fallback_card
    {
        enum wined3d_feature_level feature_level;
        enum wined3d_pci_device device_id;
    }
    card_fallback_nvidia[] =
888
    {
889 890 891 892
        {WINED3D_FEATURE_LEVEL_5,     CARD_NVIDIA_RIVA_128},
        {WINED3D_FEATURE_LEVEL_6,     CARD_NVIDIA_RIVA_TNT},
        {WINED3D_FEATURE_LEVEL_7,     CARD_NVIDIA_GEFORCE},
        {WINED3D_FEATURE_LEVEL_8,     CARD_NVIDIA_GEFORCE3},
893 894
        {WINED3D_FEATURE_LEVEL_9_2,   CARD_NVIDIA_GEFORCEFX_5800},
        {WINED3D_FEATURE_LEVEL_9_3,   CARD_NVIDIA_GEFORCE_6800},
895 896 897
        {WINED3D_FEATURE_LEVEL_10,    CARD_NVIDIA_GEFORCE_8800GTX},
        {WINED3D_FEATURE_LEVEL_11,    CARD_NVIDIA_GEFORCE_GTX470},
        {WINED3D_FEATURE_LEVEL_NONE},
898 899 900
    },
    card_fallback_amd[] =
    {
901 902 903
        {WINED3D_FEATURE_LEVEL_5,     CARD_AMD_RAGE_128PRO},
        {WINED3D_FEATURE_LEVEL_7,     CARD_AMD_RADEON_7200},
        {WINED3D_FEATURE_LEVEL_8,     CARD_AMD_RADEON_8500},
904 905
        {WINED3D_FEATURE_LEVEL_9_1,   CARD_AMD_RADEON_9500},
        {WINED3D_FEATURE_LEVEL_9_3,   CARD_AMD_RADEON_X1600},
906 907 908
        {WINED3D_FEATURE_LEVEL_10,    CARD_AMD_RADEON_HD2900},
        {WINED3D_FEATURE_LEVEL_11,    CARD_AMD_RADEON_HD5600},
        {WINED3D_FEATURE_LEVEL_NONE},
909 910 911
    },
    card_fallback_intel[] =
    {
912 913
        {WINED3D_FEATURE_LEVEL_5,     CARD_INTEL_845G},
        {WINED3D_FEATURE_LEVEL_8,     CARD_INTEL_915G},
914
        {WINED3D_FEATURE_LEVEL_9_3,   CARD_INTEL_945G},
915 916 917
        {WINED3D_FEATURE_LEVEL_10,    CARD_INTEL_G45},
        {WINED3D_FEATURE_LEVEL_11,    CARD_INTEL_IVBD},
        {WINED3D_FEATURE_LEVEL_NONE},
918
    };
919

920
    static const struct
921 922
    {
        enum wined3d_pci_vendor vendor;
923
        const struct wined3d_fallback_card *cards;
924 925 926 927 928 929 930 931
    }
    fallbacks[] =
    {
        {HW_VENDOR_AMD,    card_fallback_amd},
        {HW_VENDOR_NVIDIA, card_fallback_nvidia},
        {HW_VENDOR_VMWARE, card_fallback_amd},
        {HW_VENDOR_INTEL,  card_fallback_intel},
    };
932

933 934 935 936 937
    const struct wined3d_fallback_card *cards;
    enum wined3d_pci_device device_id;
    unsigned int i;

    cards = NULL;
938 939 940
    for (i = 0; i < ARRAY_SIZE(fallbacks); ++i)
    {
        if (*vendor == fallbacks[i].vendor)
941 942 943 944 945 946
            cards = fallbacks[i].cards;
    }
    if (!cards)
    {
        *vendor = HW_VENDOR_NVIDIA;
        cards = card_fallback_nvidia;
947 948
    }

949 950 951 952 953 954 955
    device_id = cards->device_id;
    for (i = 0; cards[i].feature_level; ++i)
    {
        if (feature_level >= cards[i].feature_level)
            device_id = cards[i].device_id;
    }
    return device_id;
956 957
}

958 959 960 961 962 963 964 965 966 967
struct wined3d_adapter * CDECL wined3d_get_adapter(const struct wined3d *wined3d, unsigned int idx)
{
    TRACE("wined3d %p, idx %u.\n", wined3d, idx);

    if (idx >= wined3d->adapter_count)
        return NULL;

    return wined3d->adapters[idx];
}

968 969
UINT CDECL wined3d_get_adapter_count(const struct wined3d *wined3d)
{
970
    TRACE("wined3d %p, reporting %u adapters.\n",
971
            wined3d, wined3d->adapter_count);
972

973
    return wined3d->adapter_count;
974 975
}

976 977 978 979 980 981 982 983 984 985 986
struct wined3d_output * CDECL wined3d_adapter_get_output(const struct wined3d_adapter *adapter,
        unsigned int idx)
{
    TRACE("adapter %p, idx %u.\n", adapter, idx);

    if (idx >= adapter->output_count)
        return NULL;

    return &adapter->outputs[idx];
}

987 988 989 990 991 992 993
unsigned int CDECL wined3d_adapter_get_output_count(const struct wined3d_adapter *adapter)
{
    TRACE("adapter %p, reporting %u outputs.\n", adapter, adapter->output_count);

    return adapter->output_count;
}

994
HRESULT CDECL wined3d_register_software_device(struct wined3d *wined3d, void *init_function)
995
{
996
    FIXME("wined3d %p, init_function %p stub!\n", wined3d, init_function);
997

998
    return WINED3D_OK;
999 1000
}

1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
static BOOL CALLBACK enum_monitor_proc(HMONITOR monitor, HDC hdc, RECT *rect, LPARAM lparam)
{
    struct wined3d_output_desc *desc = (struct wined3d_output_desc *)lparam;
    MONITORINFOEXW monitor_info;

    monitor_info.cbSize = sizeof(monitor_info);
    if (GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info) &&
            !lstrcmpiW(desc->device_name, monitor_info.szDevice))
    {
        desc->monitor = monitor;
        desc->desktop_rect = monitor_info.rcMonitor;
        desc->attached_to_desktop = TRUE;
        return FALSE;
    }

    return TRUE;
}

1019
HRESULT CDECL wined3d_output_get_desc(const struct wined3d_output *output,
1020
        struct wined3d_output_desc *desc)
1021
{
1022
    TRACE("output %p, desc %p.\n", output, desc);
1023

1024
    memset(desc, 0, sizeof(*desc));
1025
    desc->ordinal = output->ordinal;
1026 1027
    lstrcpyW(desc->device_name, output->device_name);
    EnumDisplayMonitors(NULL, NULL, enum_monitor_proc, (LPARAM)desc);
1028
    return WINED3D_OK;
1029 1030
}

1031
/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1032 1033
     of the same bpp but different resolutions                                  */

1034
/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1035
unsigned int CDECL wined3d_output_get_mode_count(const struct wined3d_output *output,
1036
        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering)
1037
{
1038 1039 1040 1041 1042 1043 1044
    const struct wined3d_adapter *adapter;
    const struct wined3d_format *format;
    unsigned int i = 0;
    unsigned int j = 0;
    UINT format_bits;
    DEVMODEW mode;

1045 1046
    TRACE("output %p, format %s, scanline_ordering %#x.\n",
            output, debug_d3dformat(format_id), scanline_ordering);
1047

1048
    adapter = output->adapter;
1049
    format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET);
1050
    format_bits = format->byte_count * CHAR_BIT;
1051

1052 1053
    memset(&mode, 0, sizeof(mode));
    mode.dmSize = sizeof(mode);
1054

1055
    while (EnumDisplaySettingsExW(output->device_name, j++, &mode, 0))
1056
    {
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
        if (mode.dmFields & DM_DISPLAYFLAGS)
        {
            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_PROGRESSIVE
                    && (mode.u2.dmDisplayFlags & DM_INTERLACED))
                continue;

            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED
                    && !(mode.u2.dmDisplayFlags & DM_INTERLACED))
                continue;
        }

1068
        if (format_id == WINED3DFMT_UNKNOWN)
1069
        {
1070 1071 1072 1073 1074 1075
            /* This is for d3d8, do not enumerate P8 here. */
            if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
        }
        else if (mode.dmBitsPerPel == format_bits)
        {
            ++i;
1076
        }
1077 1078
    }

1079
    TRACE("Returning %u matching modes (out of %u total) for output %p.\n", i, j, output);
1080 1081

    return i;
1082 1083
}

1084
/* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1085
HRESULT CDECL wined3d_output_get_mode(const struct wined3d_output *output,
1086
        enum wined3d_format_id format_id, enum wined3d_scanline_ordering scanline_ordering,
1087
        unsigned int mode_idx, struct wined3d_display_mode *mode)
1088
{
1089 1090 1091 1092 1093 1094 1095
    const struct wined3d_adapter *adapter;
    const struct wined3d_format *format;
    UINT format_bits;
    DEVMODEW m;
    UINT i = 0;
    int j = 0;

1096 1097
    TRACE("output %p, format %s, scanline_ordering %#x, mode_idx %u, mode %p.\n",
            output, debug_d3dformat(format_id), scanline_ordering, mode_idx, mode);
1098

1099
    if (!mode)
1100
        return WINED3DERR_INVALIDCALL;
1101

1102
    adapter = output->adapter;
1103
    format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET);
1104
    format_bits = format->byte_count * CHAR_BIT;
1105

1106 1107
    memset(&m, 0, sizeof(m));
    m.dmSize = sizeof(m);
1108

1109 1110
    while (i <= mode_idx)
    {
1111
        if (!EnumDisplaySettingsExW(output->device_name, j++, &m, 0))
1112
        {
1113 1114
            WARN("Invalid mode_idx %u.\n", mode_idx);
            return WINED3DERR_INVALIDCALL;
1115 1116
        }

1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
        if (m.dmFields & DM_DISPLAYFLAGS)
        {
            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_PROGRESSIVE
                    && (m.u2.dmDisplayFlags & DM_INTERLACED))
                continue;

            if (scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED
                    && !(m.u2.dmDisplayFlags & DM_INTERLACED))
                continue;
        }

1128
        if (format_id == WINED3DFMT_UNKNOWN)
1129 1130 1131 1132 1133 1134 1135 1136 1137
        {
            /* This is for d3d8, do not enumerate P8 here. */
            if (m.dmBitsPerPel == 32 || m.dmBitsPerPel == 16) ++i;
        }
        else if (m.dmBitsPerPel == format_bits)
        {
            ++i;
        }
    }
1138

1139 1140 1141 1142 1143
    mode->width = m.dmPelsWidth;
    mode->height = m.dmPelsHeight;
    mode->refresh_rate = DEFAULT_REFRESH_RATE;
    if (m.dmFields & DM_DISPLAYFREQUENCY)
        mode->refresh_rate = m.dmDisplayFrequency;
1144

1145 1146
    if (format_id == WINED3DFMT_UNKNOWN)
        mode->format_id = pixelformat_for_depth(m.dmBitsPerPel);
1147
    else
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
        mode->format_id = format_id;

    if (!(m.dmFields & DM_DISPLAYFLAGS))
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
    else if (m.u2.dmDisplayFlags & DM_INTERLACED)
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED;
    else
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE;

    TRACE("%ux%u@%u %u bpp, %s %#x.\n", mode->width, mode->height, mode->refresh_rate,
            m.dmBitsPerPel, debug_d3dformat(mode->format_id), mode->scanline_ordering);
1159

1160
    return WINED3D_OK;
1161 1162
}

1163 1164
HRESULT CDECL wined3d_output_find_closest_matching_mode(const struct wined3d_output *output,
        struct wined3d_display_mode *mode)
1165 1166 1167 1168 1169 1170
{
    unsigned int i, j, mode_count, matching_mode_count, closest;
    struct wined3d_display_mode **matching_modes;
    struct wined3d_display_mode *modes;
    HRESULT hr;

1171
    TRACE("output %p, mode %p.\n", output, mode);
1172

1173 1174
    if (!(mode_count = wined3d_output_get_mode_count(output, mode->format_id,
            WINED3D_SCANLINE_ORDERING_UNKNOWN)))
1175
    {
1176
        WARN("Output has 0 matching modes.\n");
1177 1178 1179
        return E_FAIL;
    }

1180
    if (!(modes = heap_calloc(mode_count, sizeof(*modes))))
1181
        return E_OUTOFMEMORY;
1182
    if (!(matching_modes = heap_calloc(mode_count, sizeof(*matching_modes))))
1183
    {
1184
        heap_free(modes);
1185 1186 1187 1188 1189
        return E_OUTOFMEMORY;
    }

    for (i = 0; i < mode_count; ++i)
    {
1190 1191
        if (FAILED(hr = wined3d_output_get_mode(output, mode->format_id,
                WINED3D_SCANLINE_ORDERING_UNKNOWN, i, &modes[i])))
1192
        {
1193 1194
            heap_free(matching_modes);
            heap_free(modes);
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
            return hr;
        }
        matching_modes[i] = &modes[i];
    }

    matching_mode_count = mode_count;

    if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN)
    {
        for (i = 0, j = 0; i < matching_mode_count; ++i)
        {
            if (matching_modes[i]->scanline_ordering == mode->scanline_ordering)
                matching_modes[j++] = matching_modes[i];
        }
        if (j > 0)
            matching_mode_count = j;
    }

    if (mode->refresh_rate)
    {
        for (i = 0, j = 0; i < matching_mode_count; ++i)
        {
            if (matching_modes[i]->refresh_rate == mode->refresh_rate)
                matching_modes[j++] = matching_modes[i];
        }
        if (j > 0)
            matching_mode_count = j;
    }

    if (!mode->width || !mode->height)
    {
        struct wined3d_display_mode current_mode;
1227
        if (FAILED(hr = wined3d_output_get_display_mode(output, &current_mode, NULL)))
1228
        {
1229 1230
            heap_free(matching_modes);
            heap_free(modes);
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
            return hr;
        }
        mode->width = current_mode.width;
        mode->height = current_mode.height;
    }

    closest = ~0u;
    for (i = 0, j = 0; i < matching_mode_count; ++i)
    {
        unsigned int d = abs(mode->width - matching_modes[i]->width)
                + abs(mode->height - matching_modes[i]->height);

        if (closest > d)
        {
            closest = d;
            j = i;
        }
    }

    *mode = *matching_modes[j];

1252 1253
    heap_free(matching_modes);
    heap_free(modes);
1254 1255 1256 1257 1258 1259 1260 1261

    TRACE("Returning %ux%u@%u %s %#x.\n", mode->width, mode->height,
            mode->refresh_rate, debug_d3dformat(mode->format_id),
            mode->scanline_ordering);

    return WINED3D_OK;
}

1262 1263 1264 1265 1266 1267 1268
struct wined3d_adapter * CDECL wined3d_output_get_adapter(const struct wined3d_output *output)
{
    TRACE("output %p.\n", output);

    return output->adapter;
}

1269
HRESULT CDECL wined3d_output_get_display_mode(const struct wined3d_output *output,
1270
        struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
1271
{
1272
    DEVMODEW m;
1273

1274
    TRACE("output %p, display_mode %p, rotation %p.\n", output, mode, rotation);
1275

1276
    if (!mode)
1277
        return WINED3DERR_INVALIDCALL;
1278

1279 1280
    memset(&m, 0, sizeof(m));
    m.dmSize = sizeof(m);
1281

1282
    EnumDisplaySettingsExW(output->device_name, ENUM_CURRENT_SETTINGS, &m, 0);
1283 1284 1285 1286 1287 1288
    mode->width = m.dmPelsWidth;
    mode->height = m.dmPelsHeight;
    mode->refresh_rate = DEFAULT_REFRESH_RATE;
    if (m.dmFields & DM_DISPLAYFREQUENCY)
        mode->refresh_rate = m.dmDisplayFrequency;
    mode->format_id = pixelformat_for_depth(m.dmBitsPerPel);
1289

1290 1291 1292 1293
    /* Lie about the format. X11 can't change the color depth, and some apps
     * are pretty angry if they SetDisplayMode from 24 to 16 bpp and find out
     * that GetDisplayMode still returns 24 bpp. This should probably be
     * handled in winex11 instead. */
1294
    if (output->screen_format && output->screen_format != mode->format_id)
1295 1296 1297
    {
        WARN("Overriding format %s with stored format %s.\n",
                debug_d3dformat(mode->format_id),
1298 1299
                debug_d3dformat(output->screen_format));
        mode->format_id = output->screen_format;
1300
    }
1301

1302 1303 1304 1305 1306 1307
    if (!(m.dmFields & DM_DISPLAYFLAGS))
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
    else if (m.u2.dmDisplayFlags & DM_INTERLACED)
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_INTERLACED;
    else
        mode->scanline_ordering = WINED3D_SCANLINE_ORDERING_PROGRESSIVE;
1308

1309 1310 1311
    if (rotation)
    {
        switch (m.u1.s2.dmDisplayOrientation)
1312
        {
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
            case DMDO_DEFAULT:
                *rotation = WINED3D_DISPLAY_ROTATION_0;
                break;
            case DMDO_90:
                *rotation = WINED3D_DISPLAY_ROTATION_90;
                break;
            case DMDO_180:
                *rotation = WINED3D_DISPLAY_ROTATION_180;
                break;
            case DMDO_270:
                *rotation = WINED3D_DISPLAY_ROTATION_270;
                break;
            default:
                FIXME("Unhandled display rotation %#x.\n", m.u1.s2.dmDisplayOrientation);
                *rotation = WINED3D_DISPLAY_ROTATION_UNSPECIFIED;
                break;
1329
        }
1330
    }
1331

1332 1333 1334
    TRACE("Returning %ux%u@%u %s %#x.\n", mode->width, mode->height,
            mode->refresh_rate, debug_d3dformat(mode->format_id),
            mode->scanline_ordering);
1335
    return WINED3D_OK;
1336
}
1337

1338
static BOOL equal_display_mode(const DEVMODEW *mode1, const DEVMODEW *mode2)
1339
{
1340 1341 1342 1343 1344 1345 1346 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
    if (mode1->dmFields & mode2->dmFields & DM_PELSWIDTH
            && mode1->dmPelsWidth != mode2->dmPelsWidth)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_PELSHEIGHT
            && mode1->dmPelsHeight != mode2->dmPelsHeight)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_BITSPERPEL
            && mode1->dmBitsPerPel != mode2->dmBitsPerPel)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_DISPLAYFLAGS
            && mode1->u2.dmDisplayFlags != mode2->u2.dmDisplayFlags)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_DISPLAYFREQUENCY
            && mode1->dmDisplayFrequency != mode2->dmDisplayFrequency)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_DISPLAYORIENTATION
            && mode1->u1.s2.dmDisplayOrientation != mode2->u1.s2.dmDisplayOrientation)
        return FALSE;

    if (mode1->dmFields & mode2->dmFields & DM_POSITION
            && (mode1->u1.s2.dmPosition.x != mode2->u1.s2.dmPosition.x
            || mode1->u1.s2.dmPosition.y != mode2->u1.s2.dmPosition.y))
        return FALSE;

    return TRUE;
}

HRESULT CDECL wined3d_restore_display_modes(struct wined3d *wined3d)
{
    unsigned int adapter_idx, output_idx = 0;
    DEVMODEW current_mode, registry_mode;
    struct wined3d_adapter *adapter;
    DISPLAY_DEVICEW display_device;
    struct wined3d_output *output;
    BOOL do_mode_change = FALSE;
1380 1381
    LONG ret;

1382
    TRACE("wined3d %p.\n", wined3d);
1383

1384
    memset(&current_mode, 0, sizeof(current_mode));
1385
    memset(&registry_mode, 0, sizeof(registry_mode));
1386
    current_mode.dmSize = sizeof(current_mode);
1387 1388 1389
    registry_mode.dmSize = sizeof(registry_mode);
    display_device.cb = sizeof(display_device);
    while (EnumDisplayDevicesW(NULL, output_idx++, &display_device, 0))
1390
    {
1391 1392 1393 1394 1395 1396
        if (!EnumDisplaySettingsExW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &current_mode, 0))
        {
            ERR("Failed to read the current display mode for %s.\n",
                    wine_dbgstr_w(display_device.DeviceName));
            return WINED3DERR_NOTAVAILABLE;
        }
1397

1398 1399 1400 1401 1402 1403
        if (!EnumDisplaySettingsExW(display_device.DeviceName, ENUM_REGISTRY_SETTINGS, &registry_mode, 0))
        {
            ERR("Failed to read the registry display mode for %s.\n",
                    wine_dbgstr_w(display_device.DeviceName));
            return WINED3DERR_NOTAVAILABLE;
        }
1404

1405 1406 1407 1408 1409 1410
        if (!equal_display_mode(&current_mode, &registry_mode))
        {
            do_mode_change = TRUE;
            break;
        }
    }
1411

1412 1413 1414 1415
    if (do_mode_change)
    {
        ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
        if (ret != DISP_CHANGE_SUCCESSFUL)
1416
        {
1417 1418
            ERR("Failed to restore all outputs to their registry display settings, error %d.\n", ret);
            return WINED3DERR_NOTAVAILABLE;
1419 1420 1421
        }
    }
    else
1422
    {
1423 1424 1425 1426 1427 1428 1429
        TRACE("Skipping redundant mode setting call.\n");
    }

    for (adapter_idx = 0; adapter_idx < wined3d->adapter_count; ++adapter_idx)
    {
        adapter = wined3d->adapters[adapter_idx];
        for (output_idx = 0; output_idx < adapter->output_count; ++output_idx)
1430
        {
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
            output = &adapter->outputs[output_idx];

            if (!EnumDisplaySettingsExW(output->device_name, ENUM_CURRENT_SETTINGS, &current_mode, 0))
            {
                ERR("Failed to read the current display mode for %s.\n",
                        wine_dbgstr_w(output->device_name));
                return WINED3DERR_NOTAVAILABLE;
            }

            output->screen_format = pixelformat_for_depth(current_mode.dmBitsPerPel);
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
    return WINED3D_OK;
}

HRESULT CDECL wined3d_output_set_display_mode(struct wined3d_output *output,
        const struct wined3d_display_mode *mode)
{
    enum wined3d_format_id new_format_id;
    const struct wined3d_format *format;
    DEVMODEW new_mode, current_mode;
    LONG ret;

    TRACE("output %p, mode %p.\n", output, mode);
    TRACE("mode %ux%u@%u %s %#x.\n", mode->width, mode->height, mode->refresh_rate,
            debug_d3dformat(mode->format_id), mode->scanline_ordering);

    memset(&new_mode, 0, sizeof(new_mode));
    new_mode.dmSize = sizeof(new_mode);
    memset(&current_mode, 0, sizeof(current_mode));
    current_mode.dmSize = sizeof(current_mode);

    format = wined3d_get_format(output->adapter, mode->format_id, WINED3D_BIND_RENDER_TARGET);

    new_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    new_mode.dmBitsPerPel = format->byte_count * CHAR_BIT;
    new_mode.dmPelsWidth = mode->width;
    new_mode.dmPelsHeight = mode->height;
    new_mode.dmDisplayFrequency = mode->refresh_rate;
    if (mode->refresh_rate)
        new_mode.dmFields |= DM_DISPLAYFREQUENCY;
    if (mode->scanline_ordering != WINED3D_SCANLINE_ORDERING_UNKNOWN)
    {
        new_mode.dmFields |= DM_DISPLAYFLAGS;
        if (mode->scanline_ordering == WINED3D_SCANLINE_ORDERING_INTERLACED)
            new_mode.u2.dmDisplayFlags |= DM_INTERLACED;
    }
    new_format_id = mode->format_id;

1481
    /* Only change the mode if necessary. */
1482
    if (!EnumDisplaySettingsW(output->device_name, ENUM_CURRENT_SETTINGS, &current_mode))
1483
    {
1484
        ERR("Failed to get current display mode.\n");
1485
    }
1486
    else if (equal_display_mode(&current_mode, &new_mode))
1487 1488
    {
        TRACE("Skipping redundant mode setting call.\n");
1489
        output->screen_format = new_format_id;
1490 1491 1492
        return WINED3D_OK;
    }

1493
    ret = ChangeDisplaySettingsExW(output->device_name, &new_mode, NULL, CDS_FULLSCREEN, NULL);
1494 1495
    if (ret != DISP_CHANGE_SUCCESSFUL)
    {
1496
        if (new_mode.dmFields & DM_DISPLAYFREQUENCY)
1497 1498
        {
            WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate.\n");
1499 1500
            new_mode.dmFields &= ~DM_DISPLAYFREQUENCY;
            new_mode.dmDisplayFrequency = 0;
1501
            ret = ChangeDisplaySettingsExW(output->device_name, &new_mode, NULL, CDS_FULLSCREEN, NULL);
1502 1503 1504 1505 1506 1507
        }
        if (ret != DISP_CHANGE_SUCCESSFUL)
            return WINED3DERR_NOTAVAILABLE;
    }

    /* Store the new values. */
1508
    output->screen_format = new_format_id;
1509 1510 1511 1512

    return WINED3D_OK;
}

1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525
HRESULT CDECL wined3d_output_set_gamma_ramp(struct wined3d_output *output, const struct wined3d_gamma_ramp *ramp)
{
    HDC dc;

    TRACE("output %p, ramp %p.\n", output, ramp);

    dc = CreateDCW(output->device_name, NULL, NULL, NULL);
    SetDeviceGammaRamp(dc, (void *)ramp);
    DeleteDC(dc);

    return WINED3D_OK;
}

1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
HRESULT wined3d_output_get_gamma_ramp(struct wined3d_output *output, struct wined3d_gamma_ramp *ramp)
{
    HDC dc;

    TRACE("output %p, ramp %p.\n", output, ramp);

    dc = CreateDCW(output->device_name, NULL, NULL, NULL);
    GetDeviceGammaRamp(dc, ramp);
    DeleteDC(dc);

    return WINED3D_OK;
}

1539 1540
HRESULT CDECL wined3d_adapter_get_identifier(const struct wined3d_adapter *adapter,
        DWORD flags, struct wined3d_adapter_identifier *identifier)
1541
{
1542
    TRACE("adapter %p, flags %#x, identifier %p.\n", adapter, flags, identifier);
1543

1544 1545
    wined3d_mutex_lock();

1546 1547
    wined3d_copy_name(identifier->driver, adapter->driver_info.name, identifier->driver_size);
    wined3d_copy_name(identifier->description, adapter->driver_info.description, identifier->description_size);
1548

1549 1550 1551 1552 1553 1554
    identifier->driver_version.u.HighPart = adapter->driver_info.version_high;
    identifier->driver_version.u.LowPart = adapter->driver_info.version_low;
    identifier->vendor_id = adapter->driver_info.vendor;
    identifier->device_id = adapter->driver_info.device;
    identifier->subsystem_id = 0;
    identifier->revision = 0;
1555 1556 1557
    identifier->device_identifier = IID_D3DDEVICE_D3DUID;
    identifier->driver_uuid = adapter->driver_uuid;
    identifier->device_uuid = adapter->device_uuid;
1558
    identifier->whql_level = (flags & WINED3DENUM_WHQL_LEVEL) ? 1 : 0;
1559
    identifier->adapter_luid = adapter->luid;
1560
    identifier->video_memory = min(~(SIZE_T)0, adapter->driver_info.vram_bytes);
1561
    identifier->shared_system_memory = min(~(SIZE_T)0, adapter->driver_info.sysmem_bytes);
1562

1563 1564
    wined3d_mutex_unlock();

1565
    return WINED3D_OK;
1566 1567
}

1568
HRESULT CDECL wined3d_output_get_raster_status(const struct wined3d_output *output,
1569 1570 1571 1572 1573 1574 1575 1576
        struct wined3d_raster_status *raster_status)
{
    LONGLONG freq_per_frame, freq_per_line;
    LARGE_INTEGER counter, freq_per_sec;
    struct wined3d_display_mode mode;
    static UINT once;

    if (!once++)
1577
        FIXME("output %p, raster_status %p semi-stub!\n", output, raster_status);
1578
    else
1579
        WARN("output %p, raster_status %p semi-stub!\n", output, raster_status);
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589

    /* Obtaining the raster status is a widely implemented but optional
     * feature. When this method returns OK StarCraft 2 expects the
     * raster_status->InVBlank value to actually change over time.
     * And Endless Alice Crysis doesn't care even if this method fails.
     * Thus this method returns OK and fakes raster_status by
     * QueryPerformanceCounter. */

    if (!QueryPerformanceCounter(&counter) || !QueryPerformanceFrequency(&freq_per_sec))
        return WINED3DERR_INVALIDCALL;
1590
    if (FAILED(wined3d_output_get_display_mode(output, &mode, NULL)))
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
        return WINED3DERR_INVALIDCALL;
    if (mode.refresh_rate == DEFAULT_REFRESH_RATE)
        mode.refresh_rate = 60;

    freq_per_frame = freq_per_sec.QuadPart / mode.refresh_rate;
    /* Assume 20 scan lines in the vertical blank. */
    freq_per_line = freq_per_frame / (mode.height + 20);
    raster_status->scan_line = (counter.QuadPart % freq_per_frame) / freq_per_line;
    if (raster_status->scan_line < mode.height)
        raster_status->in_vblank = FALSE;
    else
    {
        raster_status->scan_line = 0;
        raster_status->in_vblank = TRUE;
    }

    TRACE("Returning fake value, in_vblank %u, scan_line %u.\n",
            raster_status->in_vblank, raster_status->scan_line);

    return WINED3D_OK;
}

1613 1614
HRESULT CDECL wined3d_check_depth_stencil_match(const struct wined3d_adapter *adapter,
        enum wined3d_device_type device_type, enum wined3d_format_id adapter_format_id,
1615
        enum wined3d_format_id render_target_format_id, enum wined3d_format_id depth_stencil_format_id)
1616
{
1617 1618
    const struct wined3d_format *rt_format;
    const struct wined3d_format *ds_format;
1619

1620 1621 1622
    TRACE("adapter %p, device_type %s, adapter_format %s, render_target_format %s, "
            "depth_stencil_format %s.\n",
            adapter, debug_d3ddevicetype(device_type), debug_d3dformat(adapter_format_id),
1623
            debug_d3dformat(render_target_format_id), debug_d3dformat(depth_stencil_format_id));
1624

1625 1626
    rt_format = wined3d_get_format(adapter, render_target_format_id, WINED3D_BIND_RENDER_TARGET);
    ds_format = wined3d_get_format(adapter, depth_stencil_format_id, WINED3D_BIND_DEPTH_STENCIL);
1627 1628

    if (!(rt_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_RENDERTARGET))
1629
    {
1630 1631
        WARN("Format %s is not render target format.\n", debug_d3dformat(rt_format->id));
        return WINED3DERR_NOTAVAILABLE;
1632
    }
1633
    if (!(ds_format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_DEPTH_STENCIL))
1634 1635 1636 1637 1638
    {
        WARN("Format %s is not depth/stencil format.\n", debug_d3dformat(ds_format->id));
        return WINED3DERR_NOTAVAILABLE;
    }

1639
    if (adapter->adapter_ops->adapter_check_format(adapter, NULL, rt_format, ds_format))
1640
    {
1641 1642
        TRACE("Formats match.\n");
        return WINED3D_OK;
1643 1644
    }

1645 1646 1647 1648 1649
    TRACE("Unsupported format pair: %s and %s.\n",
            debug_d3dformat(render_target_format_id),
            debug_d3dformat(depth_stencil_format_id));

    return WINED3DERR_NOTAVAILABLE;
1650 1651
}

1652
HRESULT CDECL wined3d_check_device_multisample_type(const struct wined3d_adapter *adapter,
1653
        enum wined3d_device_type device_type, enum wined3d_format_id surface_format_id, BOOL windowed,
1654
        enum wined3d_multisample_type multisample_type, DWORD *quality_levels)
1655
{
1656
    const struct wined3d_format *format;
1657
    HRESULT hr = WINED3D_OK;
1658

1659
    TRACE("adapter %p, device_type %s, surface_format %s, "
1660
            "windowed %#x, multisample_type %#x, quality_levels %p.\n",
1661
            adapter, debug_d3ddevicetype(device_type), debug_d3dformat(surface_format_id),
1662
            windowed, multisample_type, quality_levels);
1663

1664 1665
    if (surface_format_id == WINED3DFMT_UNKNOWN)
        return WINED3DERR_INVALIDCALL;
1666
    if (multisample_type < WINED3D_MULTISAMPLE_NONE)
1667
        return WINED3DERR_INVALIDCALL;
1668 1669 1670 1671 1672
    if (multisample_type > WINED3D_MULTISAMPLE_16_SAMPLES)
    {
        FIXME("multisample_type %u not handled yet.\n", multisample_type);
        return WINED3DERR_NOTAVAILABLE;
    }
1673

1674 1675
    format = wined3d_get_format(adapter, surface_format_id, 0);

1676 1677
    if (multisample_type && !(format->multisample_types & 1u << (multisample_type - 1)))
        hr = WINED3DERR_NOTAVAILABLE;
1678

1679
    if (SUCCEEDED(hr) || (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE && format->multisample_types))
1680
    {
1681
        if (quality_levels)
1682 1683 1684 1685 1686 1687 1688
        {
            if (multisample_type == WINED3D_MULTISAMPLE_NON_MASKABLE)
                *quality_levels = wined3d_popcount(format->multisample_types);
            else
                *quality_levels = 1;
        }
        return WINED3D_OK;
1689 1690
    }

1691 1692
    TRACE("Returning not supported.\n");
    return hr;
1693 1694
}

1695 1696
static BOOL wined3d_check_depth_stencil_format(const struct wined3d_adapter *adapter,
        const struct wined3d_format *adapter_format, const struct wined3d_format *ds_format,
1697
        enum wined3d_gl_resource_type gl_type)
1698
{
1699
    if (!ds_format->depth_size && !ds_format->stencil_size)
1700
        return FALSE;
1701

1702
    return adapter->adapter_ops->adapter_check_format(adapter, adapter_format, NULL, ds_format);
1703 1704
}

1705
static BOOL wined3d_check_surface_format(const struct wined3d_format *format)
1706
{
1707
    if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] | format->flags[WINED3D_GL_RES_TYPE_RB]) & WINED3DFMT_FLAG_BLIT)
1708 1709
        return TRUE;

1710 1711 1712 1713
    if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_EXTENSION | WINED3DFMT_FLAG_TEXTURE))
            == (WINED3DFMT_FLAG_EXTENSION | WINED3DFMT_FLAG_TEXTURE))
        return TRUE;

1714 1715 1716
    return FALSE;
}

1717 1718 1719 1720 1721 1722 1723 1724
/* OpenGL supports mipmapping on all formats. Wrapping is unsupported, but we
 * have to report mipmapping so we cannot reject WRAPANDMIP. Tests show that
 * Windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to
 * show that wrapping is supported. The lack of filtering will sort out the
 * mipmapping capability anyway.
 *
 * For now lets report this on all formats, but in the future we may want to
 * restrict it to some should applications need that. */
1725 1726 1727 1728
HRESULT CDECL wined3d_check_device_format(const struct wined3d *wined3d,
        const struct wined3d_adapter *adapter, enum wined3d_device_type device_type,
        enum wined3d_format_id adapter_format_id, DWORD usage, unsigned int bind_flags,
        enum wined3d_resource_type resource_type, enum wined3d_format_id check_format_id)
1729
{
1730
    const struct wined3d_format *adapter_format, *format;
1731
    enum wined3d_gl_resource_type gl_type, gl_type_end;
1732
    BOOL mipmap_gen_supported = TRUE;
1733
    unsigned int allowed_bind_flags;
1734 1735
    DWORD format_flags = 0;
    DWORD allowed_usage;
1736

1737
    TRACE("wined3d %p, adapter %p, device_type %s, adapter_format %s, usage %s, "
1738
            "bind_flags %s, resource_type %s, check_format %s.\n",
1739
            wined3d, adapter, debug_d3ddevicetype(device_type), debug_d3dformat(adapter_format_id),
1740
            debug_d3dusage(usage), wined3d_debug_bind_flags(bind_flags),
1741
            debug_d3dresourcetype(resource_type), debug_d3dformat(check_format_id));
1742

1743 1744
    adapter_format = wined3d_get_format(adapter, adapter_format_id, WINED3D_BIND_RENDER_TARGET);
    format = wined3d_get_format(adapter, check_format_id, bind_flags);
1745

1746 1747
    switch (resource_type)
    {
1748
        case WINED3D_RTYPE_NONE:
1749 1750
            allowed_usage = 0;
            allowed_bind_flags = WINED3D_BIND_RENDER_TARGET
1751 1752
                    | WINED3D_BIND_DEPTH_STENCIL
                    | WINED3D_BIND_UNORDERED_ACCESS;
1753 1754 1755 1756
            gl_type = WINED3D_GL_RES_TYPE_TEX_2D;
            gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
            break;

1757 1758 1759 1760 1761 1762 1763 1764 1765 1766
        case WINED3D_RTYPE_TEXTURE_1D:
            allowed_usage = WINED3DUSAGE_DYNAMIC
                    | WINED3DUSAGE_SOFTWAREPROCESSING
                    | WINED3DUSAGE_QUERY_FILTER
                    | WINED3DUSAGE_QUERY_GENMIPMAP
                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
                    | WINED3DUSAGE_QUERY_SRGBREAD
                    | WINED3DUSAGE_QUERY_SRGBWRITE
                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
1767 1768
            allowed_bind_flags = WINED3D_BIND_SHADER_RESOURCE
                    | WINED3D_BIND_UNORDERED_ACCESS;
1769 1770 1771
            gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_1D;
            break;

1772
        case WINED3D_RTYPE_TEXTURE_2D:
1773 1774
            allowed_usage = WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
            if (bind_flags & WINED3D_BIND_RENDER_TARGET)
1775
                allowed_usage |= WINED3DUSAGE_QUERY_SRGBWRITE;
1776
            allowed_bind_flags = WINED3D_BIND_RENDER_TARGET
1777 1778
                    | WINED3D_BIND_DEPTH_STENCIL
                    | WINED3D_BIND_UNORDERED_ACCESS;
1779
            if (!(bind_flags & WINED3D_BIND_SHADER_RESOURCE))
1780
            {
1781
                if (!wined3d_check_surface_format(format))
1782
                {
1783
                    TRACE("%s is not supported for plain surfaces.\n", debug_d3dformat(format->id));
1784 1785
                    return WINED3DERR_NOTAVAILABLE;
                }
1786

1787
                gl_type = gl_type_end = WINED3D_GL_RES_TYPE_RB;
1788 1789
                break;
            }
1790
            allowed_usage |= WINED3DUSAGE_DYNAMIC
1791
                    | WINED3DUSAGE_LEGACY_CUBEMAP
1792 1793
                    | WINED3DUSAGE_SOFTWAREPROCESSING
                    | WINED3DUSAGE_QUERY_FILTER
1794
                    | WINED3DUSAGE_QUERY_GENMIPMAP
1795 1796 1797 1798 1799
                    | WINED3DUSAGE_QUERY_LEGACYBUMPMAP
                    | WINED3DUSAGE_QUERY_SRGBREAD
                    | WINED3DUSAGE_QUERY_SRGBWRITE
                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
1800
            allowed_bind_flags |= WINED3D_BIND_SHADER_RESOURCE;
1801
            gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_2D;
1802 1803
            if (usage & WINED3DUSAGE_LEGACY_CUBEMAP)
            {
1804 1805
                allowed_usage &= ~WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
                allowed_bind_flags &= ~WINED3D_BIND_DEPTH_STENCIL;
1806
                gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_CUBE;
1807
            }
1808
            break;
1809

1810
        case WINED3D_RTYPE_TEXTURE_3D:
1811 1812 1813 1814 1815 1816 1817 1818
            allowed_usage = WINED3DUSAGE_DYNAMIC
                    | WINED3DUSAGE_SOFTWAREPROCESSING
                    | WINED3DUSAGE_QUERY_FILTER
                    | WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
                    | WINED3DUSAGE_QUERY_SRGBREAD
                    | WINED3DUSAGE_QUERY_SRGBWRITE
                    | WINED3DUSAGE_QUERY_VERTEXTEXTURE
                    | WINED3DUSAGE_QUERY_WRAPANDMIP;
1819 1820
            allowed_bind_flags = WINED3D_BIND_SHADER_RESOURCE
                    | WINED3D_BIND_UNORDERED_ACCESS;
1821
            gl_type = gl_type_end = WINED3D_GL_RES_TYPE_TEX_3D;
1822
            break;
1823

1824 1825 1826 1827 1828 1829 1830 1831 1832
        case WINED3D_RTYPE_BUFFER:
            if (wined3d_format_is_typeless(format))
            {
                TRACE("Requested WINED3D_RTYPE_BUFFER, but format %s is typeless.\n", debug_d3dformat(check_format_id));
                return WINED3DERR_NOTAVAILABLE;
            }

            allowed_usage = WINED3DUSAGE_DYNAMIC;
            allowed_bind_flags = WINED3D_BIND_SHADER_RESOURCE
1833
                    | WINED3D_BIND_UNORDERED_ACCESS
1834 1835
                    | WINED3D_BIND_VERTEX_BUFFER
                    | WINED3D_BIND_INDEX_BUFFER;
1836 1837 1838
            gl_type = gl_type_end = WINED3D_GL_RES_TYPE_BUFFER;
            break;

1839 1840 1841 1842
        default:
            FIXME("Unhandled resource type %s.\n", debug_d3dresourcetype(resource_type));
            return WINED3DERR_NOTAVAILABLE;
    }
1843

1844 1845 1846 1847 1848 1849
    if ((usage & allowed_usage) != usage)
    {
        TRACE("Requested usage %#x, but resource type %s only allows %#x.\n",
                usage, debug_d3dresourcetype(resource_type), allowed_usage);
        return WINED3DERR_NOTAVAILABLE;
    }
1850

1851 1852 1853 1854 1855 1856 1857 1858 1859
    if ((bind_flags & allowed_bind_flags) != bind_flags)
    {
        TRACE("Requested bind flags %s, but resource type %s only allows %s.\n",
                wined3d_debug_bind_flags(bind_flags), debug_d3dresourcetype(resource_type),
                wined3d_debug_bind_flags(allowed_bind_flags));
        return WINED3DERR_NOTAVAILABLE;
    }

    if (bind_flags & WINED3D_BIND_SHADER_RESOURCE)
1860
        format_flags |= WINED3DFMT_FLAG_TEXTURE;
1861 1862
    if (bind_flags & WINED3D_BIND_RENDER_TARGET)
        format_flags |= WINED3DFMT_FLAG_RENDERTARGET;
1863 1864
    if (bind_flags & WINED3D_BIND_DEPTH_STENCIL)
        format_flags |= WINED3DFMT_FLAG_DEPTH_STENCIL;
1865 1866
    if (bind_flags & WINED3D_BIND_UNORDERED_ACCESS)
        format_flags |= WINED3DFMT_FLAG_UNORDERED_ACCESS;
1867 1868
    if (bind_flags & WINED3D_BIND_VERTEX_BUFFER)
        format_flags |= WINED3DFMT_FLAG_VERTEX_ATTRIBUTE;
1869 1870
    if (bind_flags & WINED3D_BIND_INDEX_BUFFER)
        format_flags |= WINED3DFMT_FLAG_INDEX_BUFFER;
1871

1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
    if (usage & WINED3DUSAGE_QUERY_FILTER)
        format_flags |= WINED3DFMT_FLAG_FILTERING;
    if (usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
        format_flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
    if (usage & WINED3DUSAGE_QUERY_SRGBREAD)
        format_flags |= WINED3DFMT_FLAG_SRGB_READ;
    if (usage & WINED3DUSAGE_QUERY_SRGBWRITE)
        format_flags |= WINED3DFMT_FLAG_SRGB_WRITE;
    if (usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE)
        format_flags |= WINED3DFMT_FLAG_VTF;
    if (usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP)
        format_flags |= WINED3DFMT_FLAG_BUMPMAP;
1884

1885 1886 1887 1888 1889
    if ((format_flags & WINED3DFMT_FLAG_TEXTURE) && (wined3d->flags & WINED3D_NO3D))
    {
        TRACE("Requested texturing support, but wined3d was created with WINED3D_NO3D.\n");
        return WINED3DERR_NOTAVAILABLE;
    }
1890

1891
    for (; gl_type <= gl_type_end; ++gl_type)
1892
    {
1893
        if ((bind_flags & WINED3D_BIND_RENDER_TARGET)
1894
                && !adapter->adapter_ops->adapter_check_format(adapter, adapter_format, format, NULL))
1895
        {
1896
            TRACE("Requested WINED3D_BIND_RENDER_TARGET, but format %s is not supported for render targets.\n",
1897 1898 1899 1900 1901
                    debug_d3dformat(check_format_id));
            return WINED3DERR_NOTAVAILABLE;
        }

        /* 3D depth / stencil textures are never supported. */
1902
        if (bind_flags == WINED3D_BIND_DEPTH_STENCIL && gl_type == WINED3D_GL_RES_TYPE_TEX_3D)
1903 1904
            continue;

1905
        if ((bind_flags & WINED3D_BIND_DEPTH_STENCIL)
1906
                && !wined3d_check_depth_stencil_format(adapter, adapter_format, format, gl_type))
1907
        {
1908
            TRACE("Requested WINED3D_BIND_DEPTH_STENCIL, but format %s is not supported for depth/stencil buffers.\n",
1909 1910 1911
                    debug_d3dformat(check_format_id));
            return WINED3DERR_NOTAVAILABLE;
        }
1912

1913 1914 1915 1916 1917 1918 1919
        if ((bind_flags & WINED3D_BIND_UNORDERED_ACCESS) && wined3d_format_is_typeless(format))
        {
            TRACE("Requested WINED3D_BIND_UNORDERED_ACCESS, but format %s is typeless.\n",
                    debug_d3dformat(check_format_id));
            return WINED3DERR_NOTAVAILABLE;
        }

1920 1921 1922 1923 1924 1925 1926
        if ((format->flags[gl_type] & format_flags) != format_flags)
        {
            TRACE("Requested format flags %#x, but format %s only has %#x.\n",
                    format_flags, debug_d3dformat(check_format_id), format->flags[gl_type]);
            return WINED3DERR_NOTAVAILABLE;
        }

1927
        if (!(format->flags[gl_type] & WINED3DFMT_FLAG_GEN_MIPMAP))
1928
            mipmap_gen_supported = FALSE;
1929 1930
    }

1931
    if ((usage & WINED3DUSAGE_QUERY_GENMIPMAP) && !mipmap_gen_supported)
1932 1933
    {
        TRACE("No WINED3DUSAGE_AUTOGENMIPMAP support, returning WINED3DOK_NOAUTOGEN.\n");
1934
        return WINED3DOK_NOMIPGEN;
1935
    }
1936

1937
    return WINED3D_OK;
1938 1939
}

1940 1941
unsigned int CDECL wined3d_calculate_format_pitch(const struct wined3d_adapter *adapter,
        enum wined3d_format_id format_id, unsigned int width)
1942
{
1943
    unsigned int row_pitch, slice_pitch;
1944

1945
    TRACE("adapter %p, format_id %s, width %u.\n", adapter, debug_d3dformat(format_id), width);
1946

1947
    wined3d_format_calculate_pitch(wined3d_get_format(adapter, format_id, 0),
1948 1949 1950
            1, width, 1, &row_pitch, &slice_pitch);

    return row_pitch;
1951 1952
}

1953 1954 1955
HRESULT CDECL wined3d_check_device_format_conversion(const struct wined3d_output *output,
        enum wined3d_device_type device_type, enum wined3d_format_id src_format,
        enum wined3d_format_id dst_format)
1956
{
1957 1958
    FIXME("output %p, device_type %s, src_format %s, dst_format %s stub!\n",
            output, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
1959
            debug_d3dformat(dst_format));
1960

1961
    return WINED3D_OK;
1962 1963
}

1964 1965 1966 1967
HRESULT CDECL wined3d_check_device_type(const struct wined3d *wined3d,
        const struct wined3d_output *output, enum wined3d_device_type device_type,
        enum wined3d_format_id display_format, enum wined3d_format_id backbuffer_format,
        BOOL windowed)
1968
{
1969
    BOOL present_conversion = wined3d->flags & WINED3D_PRESENT_CONVERSION;
1970

1971 1972
    TRACE("wined3d %p, output %p, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
            wined3d, output, debug_d3ddevicetype(device_type), debug_d3dformat(display_format),
1973 1974 1975
            debug_d3dformat(backbuffer_format), windowed);

    /* The task of this function is to check whether a certain display / backbuffer format
1976
     * combination is available on the given output. In fullscreen mode microsoft specified
1977 1978
     * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
     * and display format should match exactly.
1979
     * In windowed mode format conversion can occur and this depends on the driver. */
1980 1981 1982 1983 1984 1985 1986

    /* There are only 4 display formats. */
    if (!(display_format == WINED3DFMT_B5G6R5_UNORM
            || display_format == WINED3DFMT_B5G5R5X1_UNORM
            || display_format == WINED3DFMT_B8G8R8X8_UNORM
            || display_format == WINED3DFMT_B10G10R10A2_UNORM))
    {
1987
        TRACE("Format %s is not supported as display format.\n", debug_d3dformat(display_format));
1988 1989 1990
        return WINED3DERR_NOTAVAILABLE;
    }

1991
    if (!windowed)
1992
    {
1993
        /* If the requested display format is not available, don't continue. */
1994 1995
        if (!wined3d_output_get_mode_count(output, display_format,
                WINED3D_SCANLINE_ORDERING_UNKNOWN))
1996
        {
1997
            TRACE("No available modes for display format %s.\n", debug_d3dformat(display_format));
1998 1999
            return WINED3DERR_NOTAVAILABLE;
        }
2000

2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
        present_conversion = FALSE;
    }
    else if (display_format == WINED3DFMT_B10G10R10A2_UNORM)
    {
        /* WINED3DFMT_B10G10R10A2_UNORM is only allowed in fullscreen mode. */
        TRACE("Unsupported format combination %s / %s in windowed mode.\n",
                debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
        return WINED3DERR_NOTAVAILABLE;
    }

    if (present_conversion)
    {
        /* Use the display format as back buffer format if the latter is
         * WINED3DFMT_UNKNOWN. */
2015 2016
        if (backbuffer_format == WINED3DFMT_UNKNOWN)
            backbuffer_format = display_format;
2017

2018 2019
        if (FAILED(wined3d_check_device_format_conversion(output, device_type, backbuffer_format,
                display_format)))
2020
        {
2021 2022
            TRACE("Format conversion from %s to %s not supported.\n",
                    debug_d3dformat(backbuffer_format), debug_d3dformat(display_format));
2023 2024
            return WINED3DERR_NOTAVAILABLE;
        }
2025
    }
2026
    else
2027
    {
2028 2029 2030
        /* When format conversion from the back buffer format to the display
         * format is not allowed, only a limited number of combinations are
         * valid. */
2031

2032 2033
        if (display_format == WINED3DFMT_B5G6R5_UNORM && backbuffer_format != WINED3DFMT_B5G6R5_UNORM)
        {
2034
            TRACE("Unsupported format combination %s / %s.\n",
2035 2036 2037 2038 2039 2040 2041
                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
            return WINED3DERR_NOTAVAILABLE;
        }

        if (display_format == WINED3DFMT_B5G5R5X1_UNORM
                && !(backbuffer_format == WINED3DFMT_B5G5R5X1_UNORM || backbuffer_format == WINED3DFMT_B5G5R5A1_UNORM))
        {
2042
            TRACE("Unsupported format combination %s / %s.\n",
2043 2044 2045 2046 2047 2048 2049
                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
            return WINED3DERR_NOTAVAILABLE;
        }

        if (display_format == WINED3DFMT_B8G8R8X8_UNORM
                && !(backbuffer_format == WINED3DFMT_B8G8R8X8_UNORM || backbuffer_format == WINED3DFMT_B8G8R8A8_UNORM))
        {
2050
            TRACE("Unsupported format combination %s / %s.\n",
2051 2052 2053 2054 2055 2056 2057
                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
            return WINED3DERR_NOTAVAILABLE;
        }

        if (display_format == WINED3DFMT_B10G10R10A2_UNORM
                && backbuffer_format != WINED3DFMT_B10G10R10A2_UNORM)
        {
2058
            TRACE("Unsupported format combination %s / %s.\n",
2059 2060 2061
                    debug_d3dformat(display_format), debug_d3dformat(backbuffer_format));
            return WINED3DERR_NOTAVAILABLE;
        }
2062 2063
    }

2064
    /* Validate that the back buffer format is usable for render targets. */
2065
    if (FAILED(wined3d_check_device_format(wined3d, output->adapter, device_type,
2066 2067
            display_format, 0, WINED3D_BIND_RENDER_TARGET, WINED3D_RTYPE_TEXTURE_2D,
            backbuffer_format)))
2068 2069 2070 2071
    {
        TRACE("Format %s not allowed for render targets.\n", debug_d3dformat(backbuffer_format));
        return WINED3DERR_NOTAVAILABLE;
    }
2072

2073
    return WINED3D_OK;
2074 2075
}

2076
HRESULT CDECL wined3d_get_device_caps(const struct wined3d_adapter *adapter,
2077
        enum wined3d_device_type device_type, struct wined3d_caps *caps)
2078
{
2079
    const struct wined3d_d3d_info *d3d_info;
2080
    struct wined3d_vertex_caps vertex_caps;
2081
    DWORD ckey_caps, blit_caps, fx_caps;
2082 2083
    struct fragment_caps fragment_caps;
    struct shader_caps shader_caps;
2084

2085 2086
    TRACE("adapter %p, device_type %s, caps %p.\n",
            adapter, debug_d3ddevicetype(device_type), caps);
2087

2088 2089
    d3d_info = &adapter->d3d_info;

2090
    caps->DeviceType = (device_type == WINED3D_DEVICE_TYPE_HAL) ? WINED3D_DEVICE_TYPE_HAL : WINED3D_DEVICE_TYPE_REF;
2091

2092 2093
    caps->Caps                     = 0;
    caps->Caps2                    = WINED3DCAPS2_CANRENDERWINDOWED |
2094 2095
                                     WINED3DCAPS2_FULLSCREENGAMMA |
                                     WINED3DCAPS2_DYNAMICTEXTURES;
2096

2097
    caps->Caps3                    = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
2098 2099 2100
                                     WINED3DCAPS3_COPY_TO_VIDMEM                   |
                                     WINED3DCAPS3_COPY_TO_SYSTEMMEM;

2101
    caps->CursorCaps               = WINED3DCURSORCAPS_COLOR            |
2102 2103
                                     WINED3DCURSORCAPS_LOWRES;

2104
    caps->DevCaps                  = WINED3DDEVCAPS_FLOATTLVERTEX       |
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116
                                     WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
                                     WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
                                     WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
                                     WINED3DDEVCAPS_DRAWPRIMTLVERTEX    |
                                     WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
                                     WINED3DDEVCAPS_EXECUTEVIDEOMEMORY  |
                                     WINED3DDEVCAPS_PUREDEVICE          |
                                     WINED3DDEVCAPS_HWRASTERIZATION     |
                                     WINED3DDEVCAPS_TEXTUREVIDEOMEMORY  |
                                     WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
                                     WINED3DDEVCAPS_CANRENDERAFTERFLIP  |
                                     WINED3DDEVCAPS_DRAWPRIMITIVES2     |
2117
                                     WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
2118

2119
    caps->PrimitiveMiscCaps        = WINED3DPMISCCAPS_CULLNONE              |
2120 2121 2122 2123 2124 2125
                                     WINED3DPMISCCAPS_CULLCCW               |
                                     WINED3DPMISCCAPS_CULLCW                |
                                     WINED3DPMISCCAPS_COLORWRITEENABLE      |
                                     WINED3DPMISCCAPS_CLIPTLVERTS           |
                                     WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
                                     WINED3DPMISCCAPS_MASKZ                 |
2126
                                     WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
2127
                                    /* TODO:
2128 2129 2130
                                        WINED3DPMISCCAPS_NULLREFERENCE
                                        WINED3DPMISCCAPS_FOGANDSPECULARALPHA
                                        WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2131

2132
    caps->RasterCaps               = WINED3DPRASTERCAPS_DITHER    |
2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
                                     WINED3DPRASTERCAPS_PAT       |
                                     WINED3DPRASTERCAPS_WFOG      |
                                     WINED3DPRASTERCAPS_ZFOG      |
                                     WINED3DPRASTERCAPS_FOGVERTEX |
                                     WINED3DPRASTERCAPS_FOGTABLE  |
                                     WINED3DPRASTERCAPS_STIPPLE   |
                                     WINED3DPRASTERCAPS_SUBPIXEL  |
                                     WINED3DPRASTERCAPS_ZTEST     |
                                     WINED3DPRASTERCAPS_SCISSORTEST   |
                                     WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
                                     WINED3DPRASTERCAPS_DEPTHBIAS;
2144

2145
    caps->ZCmpCaps =  WINED3DPCMPCAPS_ALWAYS       |
2146 2147 2148 2149 2150 2151 2152 2153
                      WINED3DPCMPCAPS_EQUAL        |
                      WINED3DPCMPCAPS_GREATER      |
                      WINED3DPCMPCAPS_GREATEREQUAL |
                      WINED3DPCMPCAPS_LESS         |
                      WINED3DPCMPCAPS_LESSEQUAL    |
                      WINED3DPCMPCAPS_NEVER        |
                      WINED3DPCMPCAPS_NOTEQUAL;

2154 2155
    /* WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA
     * are legacy settings for srcblend only. */
2156
    caps->SrcBlendCaps  =  WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
                           WINED3DPBLENDCAPS_BOTHSRCALPHA    |
                           WINED3DPBLENDCAPS_DESTALPHA       |
                           WINED3DPBLENDCAPS_DESTCOLOR       |
                           WINED3DPBLENDCAPS_INVDESTALPHA    |
                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
                           WINED3DPBLENDCAPS_INVSRCALPHA     |
                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
                           WINED3DPBLENDCAPS_ONE             |
                           WINED3DPBLENDCAPS_SRCALPHA        |
                           WINED3DPBLENDCAPS_SRCALPHASAT     |
                           WINED3DPBLENDCAPS_SRCCOLOR        |
                           WINED3DPBLENDCAPS_ZERO;

2170
    caps->DestBlendCaps =  WINED3DPBLENDCAPS_DESTALPHA       |
2171 2172 2173 2174 2175 2176 2177 2178 2179
                           WINED3DPBLENDCAPS_DESTCOLOR       |
                           WINED3DPBLENDCAPS_INVDESTALPHA    |
                           WINED3DPBLENDCAPS_INVDESTCOLOR    |
                           WINED3DPBLENDCAPS_INVSRCALPHA     |
                           WINED3DPBLENDCAPS_INVSRCCOLOR     |
                           WINED3DPBLENDCAPS_ONE             |
                           WINED3DPBLENDCAPS_SRCALPHA        |
                           WINED3DPBLENDCAPS_SRCCOLOR        |
                           WINED3DPBLENDCAPS_ZERO;
2180

2181
    caps->AlphaCmpCaps  = WINED3DPCMPCAPS_ALWAYS       |
2182 2183 2184 2185 2186 2187 2188 2189
                          WINED3DPCMPCAPS_EQUAL        |
                          WINED3DPCMPCAPS_GREATER      |
                          WINED3DPCMPCAPS_GREATEREQUAL |
                          WINED3DPCMPCAPS_LESS         |
                          WINED3DPCMPCAPS_LESSEQUAL    |
                          WINED3DPCMPCAPS_NEVER        |
                          WINED3DPCMPCAPS_NOTEQUAL;

2190
    caps->ShadeCaps      = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2191 2192 2193 2194 2195 2196 2197 2198
                           WINED3DPSHADECAPS_COLORGOURAUDRGB    |
                           WINED3DPSHADECAPS_ALPHAFLATBLEND     |
                           WINED3DPSHADECAPS_ALPHAGOURAUDBLEND  |
                           WINED3DPSHADECAPS_COLORFLATRGB       |
                           WINED3DPSHADECAPS_FOGFLAT            |
                           WINED3DPSHADECAPS_FOGGOURAUD         |
                           WINED3DPSHADECAPS_SPECULARFLATRGB;

2199
    caps->TextureCaps   = WINED3DPTEXTURECAPS_ALPHA              |
2200
                          WINED3DPTEXTURECAPS_ALPHAPALETTE       |
2201
                          WINED3DPTEXTURECAPS_TRANSPARENCY       |
2202 2203 2204 2205
                          WINED3DPTEXTURECAPS_BORDER             |
                          WINED3DPTEXTURECAPS_MIPMAP             |
                          WINED3DPTEXTURECAPS_PROJECTED          |
                          WINED3DPTEXTURECAPS_PERSPECTIVE;
2206

2207
    if (!d3d_info->texture_npot)
2208
    {
2209
        caps->TextureCaps |= WINED3DPTEXTURECAPS_POW2;
2210
        if (d3d_info->texture_npot_conditional)
2211
            caps->TextureCaps |= WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2212
    }
2213

2214
    caps->TextureFilterCaps =  WINED3DPTFILTERCAPS_MAGFLINEAR       |
2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225
                               WINED3DPTFILTERCAPS_MAGFPOINT        |
                               WINED3DPTFILTERCAPS_MINFLINEAR       |
                               WINED3DPTFILTERCAPS_MINFPOINT        |
                               WINED3DPTFILTERCAPS_MIPFLINEAR       |
                               WINED3DPTFILTERCAPS_MIPFPOINT        |
                               WINED3DPTFILTERCAPS_LINEAR           |
                               WINED3DPTFILTERCAPS_LINEARMIPLINEAR  |
                               WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
                               WINED3DPTFILTERCAPS_MIPLINEAR        |
                               WINED3DPTFILTERCAPS_MIPNEAREST       |
                               WINED3DPTFILTERCAPS_NEAREST;
2226

2227 2228
    caps->CubeTextureFilterCaps = 0;
    caps->VolumeTextureFilterCaps = 0;
2229

2230
    caps->TextureAddressCaps  =  WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2231 2232
                                 WINED3DPTADDRESSCAPS_CLAMP  |
                                 WINED3DPTADDRESSCAPS_WRAP;
2233

2234
    caps->VolumeTextureAddressCaps = 0;
2235

2236
    caps->LineCaps  = WINED3DLINECAPS_TEXTURE       |
2237 2238 2239 2240 2241 2242 2243
                      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
     */
2244

2245 2246
    caps->MaxTextureWidth = d3d_info->limits.texture_size;
    caps->MaxTextureHeight = d3d_info->limits.texture_size;
2247

2248
    caps->MaxVolumeExtent = 0;
2249

2250
    caps->MaxTextureRepeat = 32768;
2251
    caps->MaxTextureAspectRatio = d3d_info->limits.texture_size;
2252
    caps->MaxVertexW = 1e10f;
2253

2254 2255 2256 2257
    caps->GuardBandLeft = -32768.0f;
    caps->GuardBandTop = -32768.0f;
    caps->GuardBandRight = 32768.0f;
    caps->GuardBandBottom = 32768.0f;
2258

2259
    caps->ExtentsAdjust = 0.0f;
2260

2261
    caps->StencilCaps   = WINED3DSTENCILCAPS_DECRSAT |
2262 2263 2264 2265 2266
                          WINED3DSTENCILCAPS_INCRSAT |
                          WINED3DSTENCILCAPS_INVERT  |
                          WINED3DSTENCILCAPS_KEEP    |
                          WINED3DSTENCILCAPS_REPLACE |
                          WINED3DSTENCILCAPS_ZERO;
2267

2268
    caps->MaxAnisotropy = 0;
2269
    caps->MaxPointSize = d3d_info->limits.pointsize_max;
2270

2271 2272
    caps->MaxPrimitiveCount   = 0x555555; /* Taken from an AMD Radeon HD 5700 (Evergreen) GPU. */
    caps->MaxVertexIndex      = 0xffffff; /* Taken from an AMD Radeon HD 5700 (Evergreen) GPU. */
2273
    caps->MaxStreams          = WINED3D_MAX_STREAMS;
2274
    caps->MaxStreamStride     = 1024;
2275

2276
    /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2277 2278 2279
    caps->DevCaps2                          = WINED3DDEVCAPS2_STREAMOFFSET |
                                              WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
    caps->MaxNpatchTessellationLevel        = 0;
2280

2281
    caps->NumSimultaneousRTs = d3d_info->limits.max_rt_count;
2282

2283
    caps->StretchRectFilterCaps               = WINED3DPTFILTERCAPS_MINFPOINT  |
2284 2285 2286
                                                WINED3DPTFILTERCAPS_MAGFPOINT  |
                                                WINED3DPTFILTERCAPS_MINFLINEAR |
                                                WINED3DPTFILTERCAPS_MAGFLINEAR;
2287
    caps->VertexTextureFilterCaps             = 0;
2288

2289
    adapter->shader_backend->shader_get_caps(adapter, &shader_caps);
2290
    adapter->fragment_pipe->get_caps(adapter, &fragment_caps);
2291
    adapter->vertex_pipe->vp_get_caps(adapter, &vertex_caps);
2292

2293
    /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
2294
    caps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
2295

2296 2297
    caps->VertexShaderVersion = shader_caps.vs_version;
    caps->MaxVertexShaderConst = shader_caps.vs_uniform_count;
2298

2299 2300
    caps->PixelShaderVersion = shader_caps.ps_version;
    caps->PixelShader1xMaxValue = shader_caps.ps_1x_max_value;
2301

2302 2303 2304
    caps->TextureOpCaps                    = fragment_caps.TextureOpCaps;
    caps->MaxTextureBlendStages            = fragment_caps.MaxTextureBlendStages;
    caps->MaxSimultaneousTextures          = fragment_caps.MaxSimultaneousTextures;
2305

2306 2307 2308 2309 2310 2311 2312 2313
    caps->MaxUserClipPlanes                = vertex_caps.max_user_clip_planes;
    caps->MaxActiveLights                  = vertex_caps.max_active_lights;
    caps->MaxVertexBlendMatrices           = vertex_caps.max_vertex_blend_matrices;
    caps->MaxVertexBlendMatrixIndex        = vertex_caps.max_vertex_blend_matrix_index;
    caps->VertexProcessingCaps             = vertex_caps.vertex_processing_caps;
    caps->FVFCaps                          = vertex_caps.fvf_caps;
    caps->RasterCaps                      |= vertex_caps.raster_caps;

2314 2315 2316 2317
    /* 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
     */
2318
    if (caps->VertexShaderVersion >= 3)
2319 2320 2321 2322 2323
    {
        /* 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. */
2324
        caps->VS20Caps.caps = WINED3DVS20CAPS_PREDICATION;
2325
        /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2326
        caps->VS20Caps.dynamic_flow_control_depth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
2327
        caps->VS20Caps.temp_count = 32;
2328
        /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2329
        caps->VS20Caps.static_flow_control_depth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH;
2330 2331

        caps->MaxVShaderInstructionsExecuted    = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2332
        caps->MaxVertexShader30InstructionSlots = WINED3DMIN30SHADERINSTRUCTIONS;
2333
        caps->VertexTextureFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT | WINED3DPTFILTERCAPS_MAGFPOINT;
2334
    }
2335
    else if (caps->VertexShaderVersion == 2)
2336
    {
2337 2338
        caps->VS20Caps.caps = 0;
        caps->VS20Caps.dynamic_flow_control_depth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2339
        caps->VS20Caps.temp_count = WINED3DVS20_MIN_NUMTEMPS;
2340
        caps->VS20Caps.static_flow_control_depth = 1;
2341 2342 2343 2344

        caps->MaxVShaderInstructionsExecuted    = 65535;
        caps->MaxVertexShader30InstructionSlots = 0;
    }
2345 2346
    else /* VS 1.x */
    {
2347 2348 2349 2350
        caps->VS20Caps.caps = 0;
        caps->VS20Caps.dynamic_flow_control_depth = 0;
        caps->VS20Caps.temp_count = 0;
        caps->VS20Caps.static_flow_control_depth = 0;
2351 2352 2353 2354 2355

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

2356
    if (caps->PixelShaderVersion >= 3)
2357 2358 2359 2360 2361 2362 2363 2364 2365
    {
        /* 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 */
2366
        caps->PS20Caps.caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2367 2368 2369 2370
                WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
                WINED3DPS20CAPS_PREDICATION          |
                WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
                WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2371
        /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2372
        caps->PS20Caps.dynamic_flow_control_depth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
2373
        caps->PS20Caps.temp_count = 32;
2374
        /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2375
        caps->PS20Caps.static_flow_control_depth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH;
2376
        /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2377
        caps->PS20Caps.instruction_slot_count = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS;
2378 2379

        caps->MaxPShaderInstructionsExecuted = 65535;
2380
        caps->MaxPixelShader30InstructionSlots = WINED3DMIN30SHADERINSTRUCTIONS;
2381
    }
2382
    else if (caps->PixelShaderVersion == 2)
2383
    {
2384
        /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2385 2386
        caps->PS20Caps.caps = 0;
        caps->PS20Caps.dynamic_flow_control_depth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2387
        caps->PS20Caps.temp_count = WINED3DPS20_MIN_NUMTEMPS;
2388
        caps->PS20Caps.static_flow_control_depth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
2389
        /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2390
        caps->PS20Caps.instruction_slot_count = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS;
2391 2392 2393 2394 2395 2396

        caps->MaxPShaderInstructionsExecuted    = 512; /* Minimum value, a GeforceFX uses 1024 */
        caps->MaxPixelShader30InstructionSlots  = 0;
    }
    else /* PS 1.x */
    {
2397 2398 2399 2400 2401
        caps->PS20Caps.caps = 0;
        caps->PS20Caps.dynamic_flow_control_depth = 0;
        caps->PS20Caps.temp_count = 0;
        caps->PS20Caps.static_flow_control_depth = 0;
        caps->PS20Caps.instruction_slot_count = 0;
2402 2403 2404 2405 2406

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

2407
    if (caps->VertexShaderVersion >= 2)
2408
    {
2409 2410 2411 2412 2413 2414 2415
        /* 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 */
2416 2417 2418 2419 2420 2421 2422 2423 2424
        caps->DeclTypes = WINED3DDTCAPS_UBYTE4    |
                          WINED3DDTCAPS_UBYTE4N   |
                          WINED3DDTCAPS_SHORT2N   |
                          WINED3DDTCAPS_SHORT4N;
    }
    else
    {
        caps->DeclTypes = 0;
    }
2425

2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
    /* 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             |
2436
                                        WINEDDFXCAPS_BLTSHRINKYN            |
2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448
                                        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                 |
2449
                                        WINEDDCAPS_COLORKEYHWASSIST;
2450 2451

    /* Fill the ddraw caps structure */
2452
    caps->ddraw_caps.caps =             WINEDDCAPS_GDI                      |
2453
                                        WINEDDCAPS_PALETTE                  |
2454
                                        blit_caps;
2455 2456 2457 2458
    caps->ddraw_caps.caps2 =            WINEDDCAPS2_CERTIFIED               |
                                        WINEDDCAPS2_NOPAGELOCKREQUIRED      |
                                        WINEDDCAPS2_PRIMARYGAMMA            |
                                        WINEDDCAPS2_WIDESURFACES            |
2459
                                        WINEDDCAPS2_CANRENDERWINDOWED;
2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471
    caps->ddraw_caps.color_key_caps = ckey_caps;
    caps->ddraw_caps.fx_caps = fx_caps;
    caps->ddraw_caps.svb_caps = blit_caps;
    caps->ddraw_caps.svb_color_key_caps = ckey_caps;
    caps->ddraw_caps.svb_fx_caps = fx_caps;
    caps->ddraw_caps.vsb_caps = blit_caps;
    caps->ddraw_caps.vsb_color_key_caps = ckey_caps;
    caps->ddraw_caps.vsb_fx_caps = fx_caps;
    caps->ddraw_caps.ssb_caps = blit_caps;
    caps->ddraw_caps.ssb_color_key_caps = ckey_caps;
    caps->ddraw_caps.ssb_fx_caps = fx_caps;

2472
    caps->ddraw_caps.dds_caps = WINEDDSCAPS_FLIP
2473 2474
            | WINEDDSCAPS_OFFSCREENPLAIN
            | WINEDDSCAPS_PALETTE
2475 2476 2477 2478
            | WINEDDSCAPS_PRIMARYSURFACE
            | WINEDDSCAPS_TEXTURE
            | WINEDDSCAPS_ZBUFFER
            | WINEDDSCAPS_MIPMAP;
2479

2480
    caps->shader_double_precision = d3d_info->shader_double_precision;
2481
    caps->viewport_array_index_any_shader = d3d_info->viewport_array_index_any_shader;
2482

2483 2484
    caps->max_feature_level = d3d_info->feature_level;

2485 2486
    adapter->adapter_ops->adapter_get_wined3d_caps(adapter, caps);

2487
    return WINED3D_OK;
2488 2489
}

2490
HRESULT CDECL wined3d_device_create(struct wined3d *wined3d, struct wined3d_adapter *adapter,
2491 2492 2493
        enum wined3d_device_type device_type, HWND focus_window, DWORD flags, BYTE surface_alignment,
        const enum wined3d_feature_level *feature_levels, unsigned int feature_level_count,
        struct wined3d_device_parent *device_parent, struct wined3d_device **device)
2494
{
2495
    struct wined3d_device *object;
2496
    HRESULT hr;
2497

2498
    TRACE("wined3d %p, adapter %p, device_type %#x, focus_window %p, flags %#x, "
2499
            "surface_alignment %u, feature_levels %p, feature_level_count %u, device_parent %p, device %p.\n",
2500
            wined3d, adapter, device_type, focus_window, flags, surface_alignment,
2501
            feature_levels, feature_level_count, device_parent, device);
2502

2503
    if (FAILED(hr = adapter->adapter_ops->adapter_create_device(wined3d, adapter,
2504
            device_type, focus_window, flags, surface_alignment,
2505
            feature_levels, feature_level_count, device_parent, &object)))
2506
        return hr;
2507

2508 2509
    TRACE("Created device %p.\n", object);
    *device = object;
2510

2511
    device_parent->ops->wined3d_device_created(device_parent, *device);
2512

2513 2514
    return WINED3D_OK;
}
2515

2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530
static const struct wined3d_state_entry_template misc_state_template_no3d[] =
{
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),   {STATE_VDECL}},
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),     {STATE_VDECL}},
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),   {STATE_VDECL}},
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY), {STATE_VDECL}},
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),    {STATE_VDECL}},
    {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE),  {STATE_VDECL}},
    {STATE_GRAPHICS_SHADER_RESOURCE_BINDING,              {STATE_VDECL}},
    {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,        {STATE_VDECL}},
    {STATE_COMPUTE_SHADER_RESOURCE_BINDING,               {STATE_VDECL}},
    {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,         {STATE_VDECL}},
    {STATE_STREAM_OUTPUT,                                 {STATE_VDECL}},
    {STATE_BLEND,                                         {STATE_VDECL}},
    {STATE_BLEND_FACTOR,                                  {STATE_VDECL}},
2531
    {STATE_SAMPLE_MASK,                                   {STATE_VDECL}},
2532
    {STATE_DEPTH_STENCIL,                                 {STATE_VDECL}},
2533
    {STATE_STENCIL_REF,                                   {STATE_VDECL}},
2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 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 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 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673
    {STATE_STREAMSRC,                                     {STATE_VDECL}},
    {STATE_VDECL,                                         {STATE_VDECL, state_nop}},
    {STATE_RASTERIZER,                                    {STATE_VDECL}},
    {STATE_SCISSORRECT,                                   {STATE_VDECL}},
    {STATE_POINTSPRITECOORDORIGIN,                        {STATE_VDECL}},

    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),    {STATE_VDECL}},
    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),   {STATE_VDECL}},
    {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET),  {STATE_VDECL}},

    {STATE_VIEWPORT,                                      {STATE_VDECL}},
    {STATE_INDEXBUFFER,                                   {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ANTIALIAS),                  {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE),         {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAPU),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAPV),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_LINEPATTERN),                {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_MONOENABLE),                 {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ROP2),                       {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_PLANEMASK),                  {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_LASTPIXEL),                  {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ZFUNC),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_DITHERENABLE),               {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_SUBPIXEL),                   {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_SUBPIXELX),                  {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_STIPPLEDALPHA),              {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_STIPPLEENABLE),              {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS),              {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ANISOTROPY),                 {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_FLUSHBATCH),                 {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT), {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP0),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP1),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP2),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP3),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP4),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP5),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP6),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP7),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP8),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP9),                      {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP10),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP11),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP12),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP13),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP14),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_WRAP15),                     {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_EXTENTS),                    {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE),        {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING),   {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_PATCHSEGMENTS),              {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_POSITIONDEGREE),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_NORMALDEGREE),               {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL),       {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL),       {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W),             {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION), {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),       {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN),          {STATE_VDECL}},
    {STATE_RENDER(WINED3D_RS_ZVISIBLE),                   {STATE_VDECL}},
    /* Samplers */
    {STATE_SAMPLER(0),                                    {STATE_VDECL}},
    {STATE_SAMPLER(1),                                    {STATE_VDECL}},
    {STATE_SAMPLER(2),                                    {STATE_VDECL}},
    {STATE_SAMPLER(3),                                    {STATE_VDECL}},
    {STATE_SAMPLER(4),                                    {STATE_VDECL}},
    {STATE_SAMPLER(5),                                    {STATE_VDECL}},
    {STATE_SAMPLER(6),                                    {STATE_VDECL}},
    {STATE_SAMPLER(7),                                    {STATE_VDECL}},
    {STATE_SAMPLER(8),                                    {STATE_VDECL}},
    {STATE_SAMPLER(9),                                    {STATE_VDECL}},
    {STATE_SAMPLER(10),                                   {STATE_VDECL}},
    {STATE_SAMPLER(11),                                   {STATE_VDECL}},
    {STATE_SAMPLER(12),                                   {STATE_VDECL}},
    {STATE_SAMPLER(13),                                   {STATE_VDECL}},
    {STATE_SAMPLER(14),                                   {STATE_VDECL}},
    {STATE_SAMPLER(15),                                   {STATE_VDECL}},
    {STATE_SAMPLER(16), /* Vertex sampler 0 */            {STATE_VDECL}},
    {STATE_SAMPLER(17), /* Vertex sampler 1 */            {STATE_VDECL}},
    {STATE_SAMPLER(18), /* Vertex sampler 2 */            {STATE_VDECL}},
    {STATE_SAMPLER(19), /* Vertex sampler 3 */            {STATE_VDECL}},
    {STATE_BASEVERTEXINDEX,                               {STATE_VDECL}},
    {STATE_FRAMEBUFFER,                                   {STATE_VDECL}},
    {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),             {STATE_VDECL}},
    {STATE_SHADER(WINED3D_SHADER_TYPE_HULL),              {STATE_VDECL}},
    {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN),            {STATE_VDECL}},
    {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY),          {STATE_VDECL}},
    {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE),           {STATE_VDECL}},
    {0}, /* Terminate */
};

2674 2675 2676 2677 2678 2679
static void adapter_no3d_destroy(struct wined3d_adapter *adapter)
{
    wined3d_adapter_cleanup(adapter);
    heap_free(adapter);
}

2680 2681 2682 2683 2684
static HRESULT adapter_no3d_create_device(struct wined3d *wined3d, const struct wined3d_adapter *adapter,
        enum wined3d_device_type device_type, HWND focus_window, unsigned int flags, BYTE surface_alignment,
        const enum wined3d_feature_level *levels, unsigned int level_count,
        struct wined3d_device_parent *device_parent, struct wined3d_device **device)
{
2685
    struct wined3d_device_no3d *device_no3d;
2686 2687
    HRESULT hr;

2688
    if (!(device_no3d = heap_alloc_zero(sizeof(*device_no3d))))
2689 2690
        return E_OUTOFMEMORY;

2691 2692
    if (FAILED(hr = wined3d_device_init(&device_no3d->d, wined3d, adapter->ordinal, device_type, focus_window,
            flags, surface_alignment, levels, level_count, adapter->gl_info.supported, device_parent)))
2693 2694
    {
        WARN("Failed to initialize device, hr %#x.\n", hr);
2695
        heap_free(device_no3d);
2696 2697 2698
        return hr;
    }

2699 2700
    *device = &device_no3d->d;

2701 2702 2703 2704 2705 2706 2707 2708 2709
    return WINED3D_OK;
}

static void adapter_no3d_destroy_device(struct wined3d_device *device)
{
    wined3d_device_cleanup(device);
    heap_free(device);
}

2710
static struct wined3d_context *adapter_no3d_acquire_context(struct wined3d_device *device,
2711
        struct wined3d_texture *texture, unsigned int sub_resource_idx)
2712
{
2713
    TRACE("device %p, texture %p, sub_resource_idx %u.\n", device, texture, sub_resource_idx);
2714

2715
    wined3d_from_cs(device->cs);
2716

2717 2718
    if (!device->context_count)
        return NULL;
2719

2720
    return &wined3d_device_no3d(device)->context_no3d;
2721 2722
}

2723
static void adapter_no3d_release_context(struct wined3d_context *context)
2724
{
2725
    TRACE("context %p.\n", context);
2726 2727
}

2728 2729 2730 2731
static void adapter_no3d_get_wined3d_caps(const struct wined3d_adapter *adapter, struct wined3d_caps *caps)
{
}

2732 2733 2734 2735 2736 2737 2738
static BOOL adapter_no3d_check_format(const struct wined3d_adapter *adapter,
        const struct wined3d_format *adapter_format, const struct wined3d_format *rt_format,
        const struct wined3d_format *ds_format)
{
    return TRUE;
}

2739 2740
static HRESULT adapter_no3d_init_3d(struct wined3d_device *device)
{
2741 2742 2743
    struct wined3d_context *context_no3d;
    HRESULT hr;

2744 2745
    TRACE("device %p.\n", device);

2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761
    context_no3d = &wined3d_device_no3d(device)->context_no3d;
    if (FAILED(hr = wined3d_context_no3d_init(context_no3d, device->swapchains[0])))
    {
        WARN("Failed to initialise context.\n");
        return hr;
    }

    if (!device_context_add(device, context_no3d))
    {
        ERR("Failed to add the newly created context to the context list.\n");
        wined3d_context_cleanup(context_no3d);
        return E_FAIL;
    }

    TRACE("Initialised context %p.\n", context_no3d);

2762 2763 2764
    if (!(device->blitter = wined3d_cpu_blitter_create()))
    {
        ERR("Failed to create CPU blitter.\n");
2765 2766
        device_context_remove(device, context_no3d);
        wined3d_context_cleanup(context_no3d);
2767 2768 2769 2770 2771 2772 2773 2774
        return E_FAIL;
    }

    return WINED3D_OK;
}

static void adapter_no3d_uninit_3d(struct wined3d_device *device)
{
2775 2776
    struct wined3d_context *context_no3d;

2777 2778
    TRACE("device %p.\n", device);

2779
    context_no3d = &wined3d_device_no3d(device)->context_no3d;
2780
    device->blitter->ops->blitter_destroy(device->blitter, NULL);
2781 2782
    wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT);

2783 2784
    device_context_remove(device, context_no3d);
    wined3d_context_cleanup(context_no3d);
2785 2786
}

2787
static void *adapter_no3d_map_bo_address(struct wined3d_context *context,
2788
        const struct wined3d_bo_address *data, size_t size, uint32_t map_flags)
2789 2790 2791
{
    if (data->buffer_object)
    {
2792
        ERR("Unsupported buffer object %p.\n", data->buffer_object);
2793 2794 2795 2796 2797 2798
        return NULL;
    }

    return data->addr;
}

2799 2800
static void adapter_no3d_unmap_bo_address(struct wined3d_context *context,
        const struct wined3d_bo_address *data, unsigned int range_count, const struct wined3d_range *ranges)
2801 2802
{
    if (data->buffer_object)
2803
        ERR("Unsupported buffer object %p.\n", data->buffer_object);
2804 2805
}

2806
static void adapter_no3d_copy_bo_address(struct wined3d_context *context,
2807 2808
        const struct wined3d_bo_address *dst, const struct wined3d_bo_address *src,
        unsigned int range_count, const struct wined3d_range *ranges)
2809
{
2810 2811
    unsigned int i;

2812
    if (dst->buffer_object)
2813
        ERR("Unsupported dst buffer object %p.\n", dst->buffer_object);
2814
    if (src->buffer_object)
2815
        ERR("Unsupported src buffer object %p.\n", src->buffer_object);
2816 2817
    if (dst->buffer_object || src->buffer_object)
        return;
2818 2819 2820

    for (i = 0; i < range_count; ++i)
        memcpy(dst->addr + ranges[i].offset, src->addr + ranges[i].offset, ranges[i].size);
2821 2822
}

2823 2824 2825 2826 2827
static void adapter_no3d_flush_bo_address(struct wined3d_context *context,
        const struct wined3d_const_bo_address *data, size_t size)
{
}

2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
static bool adapter_no3d_alloc_bo(struct wined3d_device *device, struct wined3d_resource *resource,
        unsigned int sub_resource_idx, struct wined3d_bo_address *addr)
{
    return false;
}

static void adapter_no3d_destroy_bo(struct wined3d_context *context, struct wined3d_bo *bo)
{
}

2838 2839
static HRESULT adapter_no3d_create_swapchain(struct wined3d_device *device,
        struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
2840 2841 2842 2843 2844
        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
{
    struct wined3d_swapchain *swapchain_no3d;
    HRESULT hr;

2845 2846
    TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
            device, desc, state_parent, parent, parent_ops, swapchain);
2847 2848 2849 2850

    if (!(swapchain_no3d = heap_alloc_zero(sizeof(*swapchain_no3d))))
        return E_OUTOFMEMORY;

2851 2852
    if (FAILED(hr = wined3d_swapchain_no3d_init(swapchain_no3d, device, desc, state_parent, parent,
            parent_ops)))
2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870
    {
        WARN("Failed to initialise swapchain, hr %#x.\n", hr);
        heap_free(swapchain_no3d);
        return hr;
    }

    TRACE("Created swapchain %p.\n", swapchain_no3d);
    *swapchain = swapchain_no3d;

    return hr;
}

static void adapter_no3d_destroy_swapchain(struct wined3d_swapchain *swapchain)
{
    wined3d_swapchain_cleanup(swapchain);
    heap_free(swapchain);
}

2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915
static HRESULT adapter_no3d_create_buffer(struct wined3d_device *device,
        const struct wined3d_buffer_desc *desc, const struct wined3d_sub_resource_data *data,
        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_buffer **buffer)
{
    struct wined3d_buffer *buffer_no3d;
    HRESULT hr;

    TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
            device, desc, data, parent, parent_ops, buffer);

    if (!(buffer_no3d = heap_alloc_zero(sizeof(*buffer_no3d))))
        return E_OUTOFMEMORY;

    if (FAILED(hr = wined3d_buffer_no3d_init(buffer_no3d, device, desc, data, parent, parent_ops)))
    {
        WARN("Failed to initialise buffer, hr %#x.\n", hr);
        heap_free(buffer_no3d);
        return hr;
    }

    TRACE("Created buffer %p.\n", buffer_no3d);
    *buffer = buffer_no3d;

    return hr;
}

static void adapter_no3d_destroy_buffer(struct wined3d_buffer *buffer)
{
    struct wined3d_device *device = buffer->resource.device;
    unsigned int swapchain_count = device->swapchain_count;

    TRACE("buffer %p.\n", buffer);

    /* Take a reference to the device, in case releasing the buffer would
     * cause the device to be destroyed. However, swapchain resources don't
     * take a reference to the device, and we wouldn't want to increment the
     * refcount on a device that's in the process of being destroyed. */
    if (swapchain_count)
        wined3d_device_incref(device);
    wined3d_buffer_cleanup(buffer);
    wined3d_cs_destroy_object(device->cs, heap_free, buffer);
    if (swapchain_count)
        wined3d_device_decref(device);
}

2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966
static HRESULT adapter_no3d_create_texture(struct wined3d_device *device,
        const struct wined3d_resource_desc *desc, unsigned int layer_count, unsigned int level_count,
        uint32_t flags, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_texture **texture)
{
    struct wined3d_texture *texture_no3d;
    HRESULT hr;

    TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
            device, desc, layer_count, level_count, flags, parent, parent_ops, texture);

    if (!(texture_no3d = wined3d_texture_allocate_object_memory(sizeof(*texture_no3d), level_count, layer_count)))
        return E_OUTOFMEMORY;

    if (FAILED(hr = wined3d_texture_no3d_init(texture_no3d, device, desc,
            layer_count, level_count, flags, parent, parent_ops)))
    {
        WARN("Failed to initialise texture, hr %#x.\n", hr);
        heap_free(texture_no3d);
        return hr;
    }

    TRACE("Created texture %p.\n", texture_no3d);
    *texture = texture_no3d;

    return hr;
}

static void adapter_no3d_destroy_texture(struct wined3d_texture *texture)
{
    struct wined3d_device *device = texture->resource.device;
    unsigned int swapchain_count = device->swapchain_count;

    TRACE("texture %p.\n", texture);

    /* Take a reference to the device, in case releasing the texture would
     * cause the device to be destroyed. However, swapchain resources don't
     * take a reference to the device, and we wouldn't want to increment the
     * refcount on a device that's in the process of being destroyed. */
    if (swapchain_count)
        wined3d_device_incref(device);

    wined3d_texture_sub_resources_destroyed(texture);
    texture->resource.parent_ops->wined3d_object_destroyed(texture->resource.parent);

    wined3d_texture_cleanup(texture);
    wined3d_cs_destroy_object(device->cs, heap_free, texture);

    if (swapchain_count)
        wined3d_device_decref(device);
}

2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011
static HRESULT adapter_no3d_create_rendertarget_view(const struct wined3d_view_desc *desc,
        struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
        struct wined3d_rendertarget_view **view)
{
    struct wined3d_rendertarget_view *view_no3d;
    HRESULT hr;

    TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
            wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);

    if (!(view_no3d = heap_alloc_zero(sizeof(*view_no3d))))
        return E_OUTOFMEMORY;

    if (FAILED(hr = wined3d_rendertarget_view_no3d_init(view_no3d, desc, resource, parent, parent_ops)))
    {
        WARN("Failed to initialise view, hr %#x.\n", hr);
        heap_free(view_no3d);
        return hr;
    }

    TRACE("Created render target view %p.\n", view_no3d);
    *view = view_no3d;

    return hr;
}

static void adapter_no3d_destroy_rendertarget_view(struct wined3d_rendertarget_view *view)
{
    struct wined3d_device *device = view->resource->device;
    unsigned int swapchain_count = device->swapchain_count;

    TRACE("view %p.\n", view);

    /* Take a reference to the device, in case releasing the view's resource
     * would cause the device to be destroyed. However, swapchain resources
     * don't take a reference to the device, and we wouldn't want to increment
     * the refcount on a device that's in the process of being destroyed. */
    if (swapchain_count)
        wined3d_device_incref(device);
    wined3d_rendertarget_view_cleanup(view);
    wined3d_cs_destroy_object(device->cs, heap_free, view);
    if (swapchain_count)
        wined3d_device_decref(device);
}

3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
static HRESULT adapter_no3d_create_shader_resource_view(const struct wined3d_view_desc *desc,
        struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
        struct wined3d_shader_resource_view **view)
{
    TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
            wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);

    return E_NOTIMPL;
}

static void adapter_no3d_destroy_shader_resource_view(struct wined3d_shader_resource_view *view)
{
    TRACE("view %p.\n", view);
}

3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041
static HRESULT adapter_no3d_create_unordered_access_view(const struct wined3d_view_desc *desc,
        struct wined3d_resource *resource, void *parent, const struct wined3d_parent_ops *parent_ops,
        struct wined3d_unordered_access_view **view)
{
    TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
            wined3d_debug_view_desc(desc, resource), resource, parent, parent_ops, view);

    return E_NOTIMPL;
}

static void adapter_no3d_destroy_unordered_access_view(struct wined3d_unordered_access_view *view)
{
    TRACE("view %p.\n", view);
}

3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055
static HRESULT adapter_no3d_create_sampler(struct wined3d_device *device, const struct wined3d_sampler_desc *desc,
        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_sampler **sampler)
{
    TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
            device, desc, parent, parent_ops, sampler);

    return E_NOTIMPL;
}

static void adapter_no3d_destroy_sampler(struct wined3d_sampler *sampler)
{
    TRACE("sampler %p.\n", sampler);
}

3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
static HRESULT adapter_no3d_create_query(struct wined3d_device *device, enum wined3d_query_type type,
        void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query)
{
    TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
            device, type, parent, parent_ops, query);

    return WINED3DERR_NOTAVAILABLE;
}

static void adapter_no3d_destroy_query(struct wined3d_query *query)
{
    TRACE("query %p.\n", query);
}

3070 3071 3072 3073 3074
static void adapter_no3d_flush_context(struct wined3d_context *context)
{
    TRACE("context %p.\n", context);
}

3075 3076 3077 3078 3079 3080
static void adapter_no3d_draw_primitive(struct wined3d_device *device,
        const struct wined3d_state *state, const struct wined3d_draw_parameters *parameters)
{
    ERR("device %p, state %p, parameters %p.\n", device, state, parameters);
}

3081 3082 3083 3084 3085 3086
static void adapter_no3d_dispatch_compute(struct wined3d_device *device,
        const struct wined3d_state *state, const struct wined3d_dispatch_parameters *parameters)
{
    ERR("device %p, state %p, parameters %p.\n", device, state, parameters);
}

3087
static void adapter_no3d_clear_uav(struct wined3d_context *context,
3088
        struct wined3d_unordered_access_view *view, const struct wined3d_uvec4 *clear_value, bool fp)
3089
{
3090
    ERR("context %p, view %p, clear_value %s, fp %#x.\n", context, view, debug_uvec4(clear_value), fp);
3091 3092
}

3093 3094
static const struct wined3d_adapter_ops wined3d_adapter_no3d_ops =
{
3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106
    .adapter_destroy = adapter_no3d_destroy,
    .adapter_create_device = adapter_no3d_create_device,
    .adapter_destroy_device = adapter_no3d_destroy_device,
    .adapter_acquire_context = adapter_no3d_acquire_context,
    .adapter_release_context = adapter_no3d_release_context,
    .adapter_get_wined3d_caps = adapter_no3d_get_wined3d_caps,
    .adapter_check_format = adapter_no3d_check_format,
    .adapter_init_3d = adapter_no3d_init_3d,
    .adapter_uninit_3d = adapter_no3d_uninit_3d,
    .adapter_map_bo_address = adapter_no3d_map_bo_address,
    .adapter_unmap_bo_address = adapter_no3d_unmap_bo_address,
    .adapter_copy_bo_address = adapter_no3d_copy_bo_address,
3107
    .adapter_flush_bo_address = adapter_no3d_flush_bo_address,
3108 3109
    .adapter_alloc_bo = adapter_no3d_alloc_bo,
    .adapter_destroy_bo = adapter_no3d_destroy_bo,
3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126
    .adapter_create_swapchain = adapter_no3d_create_swapchain,
    .adapter_destroy_swapchain = adapter_no3d_destroy_swapchain,
    .adapter_create_buffer = adapter_no3d_create_buffer,
    .adapter_destroy_buffer = adapter_no3d_destroy_buffer,
    .adapter_create_texture = adapter_no3d_create_texture,
    .adapter_destroy_texture = adapter_no3d_destroy_texture,
    .adapter_create_rendertarget_view = adapter_no3d_create_rendertarget_view,
    .adapter_destroy_rendertarget_view = adapter_no3d_destroy_rendertarget_view,
    .adapter_create_shader_resource_view = adapter_no3d_create_shader_resource_view,
    .adapter_destroy_shader_resource_view = adapter_no3d_destroy_shader_resource_view,
    .adapter_create_unordered_access_view = adapter_no3d_create_unordered_access_view,
    .adapter_destroy_unordered_access_view = adapter_no3d_destroy_unordered_access_view,
    .adapter_create_sampler = adapter_no3d_create_sampler,
    .adapter_destroy_sampler = adapter_no3d_destroy_sampler,
    .adapter_create_query = adapter_no3d_create_query,
    .adapter_destroy_query = adapter_no3d_destroy_query,
    .adapter_flush_context = adapter_no3d_flush_context,
3127
    .adapter_draw_primitive = adapter_no3d_draw_primitive,
3128 3129
    .adapter_dispatch_compute = adapter_no3d_dispatch_compute,
    .adapter_clear_uav = adapter_no3d_clear_uav,
3130 3131
};

3132
static void wined3d_adapter_no3d_init_d3d_info(struct wined3d_adapter *adapter, unsigned int wined3d_creation_flags)
3133 3134 3135 3136
{
    struct wined3d_d3d_info *d3d_info = &adapter->d3d_info;

    d3d_info->wined3d_creation_flags = wined3d_creation_flags;
3137
    d3d_info->texture_npot = TRUE;
3138
    d3d_info->feature_level = WINED3D_FEATURE_LEVEL_5;
3139 3140
}

3141
static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal, unsigned int wined3d_creation_flags)
3142
{
3143
    struct wined3d_adapter *adapter;
3144
    LUID primary_luid, *luid = NULL;
3145

3146 3147 3148 3149 3150
    static const struct wined3d_gpu_description gpu_description =
    {
        HW_VENDOR_SOFTWARE, CARD_WINE, "WineD3D DirectDraw Emulation", DRIVER_WINE, 128,
    };

3151 3152 3153 3154
    TRACE("ordinal %u, wined3d_creation_flags %#x.\n", ordinal, wined3d_creation_flags);

    if (!(adapter = heap_alloc_zero(sizeof(*adapter))))
        return NULL;
3155

3156 3157 3158 3159
    if (ordinal == 0 && wined3d_get_primary_adapter_luid(&primary_luid))
        luid = &primary_luid;

    if (!wined3d_adapter_init(adapter, ordinal, luid, &wined3d_adapter_no3d_ops))
3160 3161 3162 3163 3164
    {
        heap_free(adapter);
        return NULL;
    }

3165
    if (!wined3d_adapter_no3d_init_format_info(adapter))
3166
    {
3167
        wined3d_adapter_cleanup(adapter);
3168 3169 3170
        heap_free(adapter);
        return NULL;
    }
3171

3172 3173 3174 3175 3176 3177
    if (!wined3d_driver_info_init(&adapter->driver_info, &gpu_description, WINED3D_FEATURE_LEVEL_NONE, 0, 0))
    {
        wined3d_adapter_cleanup(adapter);
        heap_free(adapter);
        return NULL;
    }
3178 3179 3180
    adapter->vram_bytes_used = 0;
    TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter->driver_info.vram_bytes));

3181
    adapter->vertex_pipe = &none_vertex_pipe;
3182
    adapter->fragment_pipe = &none_fragment_pipe;
3183
    adapter->misc_state_template = misc_state_template_no3d;
3184
    adapter->shader_backend = &none_shader_backend;
3185

3186 3187
    wined3d_adapter_no3d_init_d3d_info(adapter, wined3d_creation_flags);

3188 3189 3190
    TRACE("Created adapter %p.\n", adapter);

    return adapter;
3191 3192
}

3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222
static BOOL wined3d_adapter_create_output(struct wined3d_adapter *adapter, const WCHAR *output_name)
{
    struct wined3d_output *outputs;
    HRESULT hr;

    if (!adapter->outputs && !(adapter->outputs = heap_calloc(1, sizeof(*adapter->outputs))))
    {
        return FALSE;
    }
    else
    {
        if (!(outputs = heap_realloc(adapter->outputs,
                sizeof(*adapter->outputs) * (adapter->output_count + 1))))
            return FALSE;

        adapter->outputs = outputs;
    }

    if (FAILED(hr = wined3d_output_init(&adapter->outputs[adapter->output_count],
            adapter->output_count, adapter, output_name)))
    {
        ERR("Failed to initialise output %s, hr %#x.\n", wine_dbgstr_w(output_name), hr);
        return FALSE;
    }

    ++adapter->output_count;
    TRACE("Initialised output %s.\n", wine_dbgstr_w(output_name));
    return TRUE;
}

3223
BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, unsigned int ordinal, const LUID *luid,
3224
        const struct wined3d_adapter_ops *adapter_ops)
3225
{
3226
    unsigned int output_idx = 0, primary_idx = 0;
3227
    DISPLAY_DEVICEW display_device;
3228
    BOOL ret = FALSE;
3229 3230

    adapter->ordinal = ordinal;
3231
    adapter->output_count = 0;
3232
    adapter->outputs = NULL;
3233

3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248
    if (luid)
    {
        adapter->luid = *luid;
    }
    else
    {
        WARN("Allocating a random LUID.\n");
        if (!AllocateLocallyUniqueId(&adapter->luid))
        {
            ERR("Failed to allocate a LUID, error %#x.\n", GetLastError());
            return FALSE;
        }
    }
    TRACE("adapter %p LUID %08x:%08x.\n", adapter, adapter->luid.HighPart, adapter->luid.LowPart);

3249
    display_device.cb = sizeof(display_device);
3250
    while (EnumDisplayDevicesW(NULL, output_idx++, &display_device, 0))
3251
    {
3252 3253 3254 3255 3256 3257 3258 3259 3260
        /* Detached outputs are not enumerated */
        if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
            continue;

        if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
            primary_idx = adapter->output_count;

        if (!wined3d_adapter_create_output(adapter, display_device.DeviceName))
            goto done;
3261
    }
3262
    TRACE("Initialised %d outputs for adapter %p.\n", adapter->output_count, adapter);
3263

3264 3265
    /* Make the primary output first */
    if (primary_idx)
3266
    {
3267 3268 3269 3270 3271
        struct wined3d_output tmp = adapter->outputs[0];
        adapter->outputs[0] = adapter->outputs[primary_idx];
        adapter->outputs[0].ordinal = 0;
        adapter->outputs[primary_idx] = tmp;
        adapter->outputs[primary_idx].ordinal = primary_idx;
3272
    }
3273

3274 3275 3276
    memset(&adapter->driver_uuid, 0, sizeof(adapter->driver_uuid));
    memset(&adapter->device_uuid, 0, sizeof(adapter->device_uuid));

3277
    adapter->formats = NULL;
3278
    adapter->adapter_ops = adapter_ops;
3279 3280 3281 3282 3283 3284 3285 3286 3287
    ret = TRUE;
done:
    if (!ret)
    {
        for (output_idx = 0; output_idx < adapter->output_count; ++output_idx)
            wined3d_output_cleanup(&adapter->outputs[output_idx]);
        heap_free(adapter->outputs);
    }
    return ret;
3288 3289 3290 3291
}

static struct wined3d_adapter *wined3d_adapter_create(unsigned int ordinal, DWORD wined3d_creation_flags)
{
3292
    if (wined3d_creation_flags & WINED3D_NO3D)
3293 3294
        return wined3d_adapter_no3d_create(ordinal, wined3d_creation_flags);

3295 3296 3297
    if (wined3d_settings.renderer == WINED3D_RENDERER_VULKAN)
        return wined3d_adapter_vk_create(ordinal, wined3d_creation_flags);

3298
    return wined3d_adapter_gl_create(ordinal, wined3d_creation_flags);
3299 3300
}

3301 3302 3303 3304 3305 3306
static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}

const struct wined3d_parent_ops wined3d_null_parent_ops =
{
    wined3d_null_wined3d_object_destroyed,
};
3307

3308
HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags)
3309 3310
{
    wined3d->ref = 1;
3311
    wined3d->flags = flags;
3312

3313
    TRACE("Initialising adapters.\n");
3314

3315
    if (!(wined3d->adapters[0] = wined3d_adapter_create(0, flags)))
3316
    {
3317
        WARN("Failed to create adapter.\n");
3318
        return E_FAIL;
3319
    }
3320
    wined3d->adapter_count = 1;
3321 3322 3323

    return WINED3D_OK;
}