17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
227ec681f3Smrg
237ec681f3Smrg#include "adapter9.h"
247ec681f3Smrg#include "device9ex.h"
257ec681f3Smrg#include "nine_helpers.h"
267ec681f3Smrg#include "nine_defines.h"
277ec681f3Smrg#include "nine_pipe.h"
287ec681f3Smrg#include "nine_dump.h"
297ec681f3Smrg#include "util/u_math.h"
307ec681f3Smrg#include "util/format/u_format.h"
317ec681f3Smrg#include "util/u_dump.h"
327ec681f3Smrg
337ec681f3Smrg#include "pipe/p_screen.h"
347ec681f3Smrg
357ec681f3Smrg#define DBG_CHANNEL DBG_ADAPTER
367ec681f3Smrg
377ec681f3Smrgstatic bool
387ec681f3Smrghas_sm3(struct pipe_screen *hal)
397ec681f3Smrg{
407ec681f3Smrg    return hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD) &&
417ec681f3Smrg           hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES) &&
427ec681f3Smrg           hal->get_param(hal, PIPE_CAP_VERTEX_SHADER_SATURATE);
437ec681f3Smrg}
447ec681f3Smrg
457ec681f3SmrgHRESULT
467ec681f3SmrgNineAdapter9_ctor( struct NineAdapter9 *This,
477ec681f3Smrg                   struct NineUnknownParams *pParams,
487ec681f3Smrg                   struct d3dadapter9_context *pCTX )
497ec681f3Smrg{
507ec681f3Smrg    struct pipe_screen *hal = pCTX->hal;
517ec681f3Smrg    HRESULT hr = NineUnknown_ctor(&This->base, pParams);
527ec681f3Smrg    if (FAILED(hr)) { return hr; }
537ec681f3Smrg
547ec681f3Smrg    DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX);
557ec681f3Smrg    nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier);
567ec681f3Smrg
577ec681f3Smrg    This->ctx = pCTX;
587ec681f3Smrg    if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) {
597ec681f3Smrg        ERR("Driver doesn't support d3d9 coordinates\n");
607ec681f3Smrg        return D3DERR_DRIVERINTERNALERROR;
617ec681f3Smrg    }
627ec681f3Smrg    if (This->ctx->ref &&
637ec681f3Smrg        !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) {
647ec681f3Smrg        ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n");
657ec681f3Smrg    }
667ec681f3Smrg    /* Old cards had tricks to bypass some restrictions to implement
677ec681f3Smrg     * everything and fit tight the requirements: number of constants,
687ec681f3Smrg     * number of temp registers, special behaviours, etc. Since we don't
697ec681f3Smrg     * have access to all this, we need a bit more than what dx9 required.
707ec681f3Smrg     * For example we have to use more than 32 temp registers to emulate
717ec681f3Smrg     * behaviours, while some dx9 hw don't have more. As for sm2 hardware,
727ec681f3Smrg     * we could support vs2 / ps2 for them but it needs some more care, and
737ec681f3Smrg     * as these are very old, we choose to drop support for them */
747ec681f3Smrg
757ec681f3Smrg    /* checks minimum requirements, most are vs3/ps3 strict requirements */
767ec681f3Smrg    if (!has_sm3(hal) ||
777ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
787ec681f3Smrg                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) ||
797ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
807ec681f3Smrg                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) ||
817ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
827ec681f3Smrg                              PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
837ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
847ec681f3Smrg                              PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
857ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
867ec681f3Smrg                              PIPE_SHADER_CAP_MAX_INPUTS) < 16 ||
877ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
887ec681f3Smrg                              PIPE_SHADER_CAP_MAX_INPUTS) < 10 ||
897ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
907ec681f3Smrg                              PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) < 16) {
917ec681f3Smrg        ERR("Your card is not supported by Gallium Nine. Minimum requirement "
927ec681f3Smrg            "is >= r500, >= nv50, >= i965\n");
937ec681f3Smrg        return D3DERR_DRIVERINTERNALERROR;
947ec681f3Smrg    }
957ec681f3Smrg    /* for r500 */
967ec681f3Smrg    if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
977ec681f3Smrg                              PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */
987ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
997ec681f3Smrg                              PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */
1007ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
1017ec681f3Smrg                              PIPE_SHADER_CAP_MAX_TEMPS) < 40 ||
1027ec681f3Smrg        hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
1037ec681f3Smrg                              PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */
1047ec681f3Smrg        ERR("Your card is at the limit of Gallium Nine requirements. Some games "
1057ec681f3Smrg            "may run into issues because requirements are too tight\n");
1067ec681f3Smrg    return D3D_OK;
1077ec681f3Smrg}
1087ec681f3Smrg
1097ec681f3Smrgvoid
1107ec681f3SmrgNineAdapter9_dtor( struct NineAdapter9 *This )
1117ec681f3Smrg{
1127ec681f3Smrg    struct d3dadapter9_context *ctx = This->ctx;
1137ec681f3Smrg
1147ec681f3Smrg    DBG("This=%p\n", This);
1157ec681f3Smrg
1167ec681f3Smrg    NineUnknown_dtor(&This->base);
1177ec681f3Smrg
1187ec681f3Smrg    /* special case, call backend-specific dtor AFTER destroying this object
1197ec681f3Smrg     * completely. */
1207ec681f3Smrg    if (ctx) {
1217ec681f3Smrg        if (ctx->destroy) { ctx->destroy(ctx); }
1227ec681f3Smrg    }
1237ec681f3Smrg}
1247ec681f3Smrg
1257ec681f3Smrgstatic HRESULT
1267ec681f3SmrgNineAdapter9_GetScreen( struct NineAdapter9 *This,
1277ec681f3Smrg                        D3DDEVTYPE DevType,
1287ec681f3Smrg                        struct pipe_screen **ppScreen )
1297ec681f3Smrg{
1307ec681f3Smrg    const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE");
1317ec681f3Smrg    switch (DevType) {
1327ec681f3Smrg        case D3DDEVTYPE_HAL:
1337ec681f3Smrg            if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) {
1347ec681f3Smrg                *ppScreen = This->ctx->ref;
1357ec681f3Smrg                break;
1367ec681f3Smrg            }
1377ec681f3Smrg            *ppScreen = This->ctx->hal;
1387ec681f3Smrg            break;
1397ec681f3Smrg
1407ec681f3Smrg        case D3DDEVTYPE_REF:
1417ec681f3Smrg        case D3DDEVTYPE_NULLREF:
1427ec681f3Smrg        case D3DDEVTYPE_SW:
1437ec681f3Smrg            if (force_sw && !strcmp(force_sw, "0")) {
1447ec681f3Smrg                *ppScreen = This->ctx->hal;
1457ec681f3Smrg                break;
1467ec681f3Smrg            }
1477ec681f3Smrg            *ppScreen = This->ctx->ref;
1487ec681f3Smrg            break;
1497ec681f3Smrg
1507ec681f3Smrg        default:
1517ec681f3Smrg            user_assert(!"Invalid device type", D3DERR_INVALIDCALL);
1527ec681f3Smrg    }
1537ec681f3Smrg
1547ec681f3Smrg    if (!*ppScreen) { return D3DERR_NOTAVAILABLE; }
1557ec681f3Smrg
1567ec681f3Smrg    return D3D_OK;
1577ec681f3Smrg}
1587ec681f3Smrg
1597ec681f3SmrgHRESULT NINE_WINAPI
1607ec681f3SmrgNineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This,
1617ec681f3Smrg                                   DWORD Flags,
1627ec681f3Smrg                                   D3DADAPTER_IDENTIFIER9 *pIdentifier )
1637ec681f3Smrg{
1647ec681f3Smrg    DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier);
1657ec681f3Smrg
1667ec681f3Smrg    /* regarding flags, MSDN has this to say:
1677ec681f3Smrg     *  Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be
1687ec681f3Smrg     *  set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is
1697ec681f3Smrg     *  specified, this call can connect to the Internet to download new
1707ec681f3Smrg     *  Microsoft Windows Hardware Quality Labs (WHQL) certificates.
1717ec681f3Smrg     * so let's just ignore it. */
1727ec681f3Smrg    *pIdentifier = This->ctx->identifier;
1737ec681f3Smrg    return D3D_OK;
1747ec681f3Smrg}
1757ec681f3Smrg
1767ec681f3Smrgstatic inline boolean
1777ec681f3Smrgbackbuffer_format( D3DFORMAT dfmt,
1787ec681f3Smrg                   D3DFORMAT bfmt,
1797ec681f3Smrg                   boolean win )
1807ec681f3Smrg{
1817ec681f3Smrg    if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
1827ec681f3Smrg
1837ec681f3Smrg    if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) ||
1847ec681f3Smrg        (dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt ||
1857ec681f3Smrg                                     bfmt == D3DFMT_A8R8G8B8)) ||
1867ec681f3Smrg        (dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt ||
1877ec681f3Smrg                                     bfmt == D3DFMT_A1R5G5B5)) ||
1887ec681f3Smrg        (dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) {
1897ec681f3Smrg        return TRUE;
1907ec681f3Smrg    }
1917ec681f3Smrg
1927ec681f3Smrg    return FALSE;
1937ec681f3Smrg}
1947ec681f3Smrg
1957ec681f3SmrgHRESULT NINE_WINAPI
1967ec681f3SmrgNineAdapter9_CheckDeviceType( struct NineAdapter9 *This,
1977ec681f3Smrg                              D3DDEVTYPE DevType,
1987ec681f3Smrg                              D3DFORMAT AdapterFormat,
1997ec681f3Smrg                              D3DFORMAT BackBufferFormat,
2007ec681f3Smrg                              BOOL bWindowed )
2017ec681f3Smrg{
2027ec681f3Smrg    struct pipe_screen *screen;
2037ec681f3Smrg    enum pipe_format dfmt, bfmt;
2047ec681f3Smrg    HRESULT hr;
2057ec681f3Smrg
2067ec681f3Smrg    DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s "
2077ec681f3Smrg        "bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType),
2087ec681f3Smrg        d3dformat_to_string(AdapterFormat),
2097ec681f3Smrg        d3dformat_to_string(BackBufferFormat), bWindowed);
2107ec681f3Smrg
2117ec681f3Smrg    user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed),
2127ec681f3Smrg                D3DERR_NOTAVAILABLE);
2137ec681f3Smrg
2147ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DevType, &screen);
2157ec681f3Smrg    if (FAILED(hr)) { return hr; }
2167ec681f3Smrg
2177ec681f3Smrg    /* The display format is not handled in Nine. We always present an XRGB8888
2187ec681f3Smrg     * buffer (and the display server will eventually do the conversion). We probably
2197ec681f3Smrg     * don't need to check for anything for the adapter format support, since if the
2207ec681f3Smrg     * display server advertise support, it will likely be able to do the conversion.
2217ec681f3Smrg     * We do the approximation that a format is available in the display server if
2227ec681f3Smrg     * the format passes with NINE_BIND_BACKBUFFER_FLAGS */
2237ec681f3Smrg    dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D,
2247ec681f3Smrg                                       1,
2257ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
2267ec681f3Smrg    bfmt = d3d9_to_pipe_format_checked(screen, BackBufferFormat, PIPE_TEXTURE_2D,
2277ec681f3Smrg                                       1,
2287ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
2297ec681f3Smrg    if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
2307ec681f3Smrg        DBG("Unsupported Adapter/BackBufferFormat.\n");
2317ec681f3Smrg        return D3DERR_NOTAVAILABLE;
2327ec681f3Smrg    }
2337ec681f3Smrg
2347ec681f3Smrg    return D3D_OK;
2357ec681f3Smrg}
2367ec681f3Smrg
2377ec681f3Smrgstatic inline boolean
2387ec681f3Smrgdisplay_format( D3DFORMAT fmt,
2397ec681f3Smrg                boolean win )
2407ec681f3Smrg{
2417ec681f3Smrg    /* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */
2427ec681f3Smrg    static const D3DFORMAT allowed[] = {
2437ec681f3Smrg        D3DFMT_A2R10G10B10,
2447ec681f3Smrg        D3DFMT_X8R8G8B8,
2457ec681f3Smrg        D3DFMT_X1R5G5B5,
2467ec681f3Smrg        D3DFMT_R5G6B5,
2477ec681f3Smrg    };
2487ec681f3Smrg    unsigned i;
2497ec681f3Smrg
2507ec681f3Smrg    if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
2517ec681f3Smrg
2527ec681f3Smrg    for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
2537ec681f3Smrg        if (fmt == allowed[i]) { return TRUE; }
2547ec681f3Smrg    }
2557ec681f3Smrg    return FALSE;
2567ec681f3Smrg}
2577ec681f3Smrg
2587ec681f3Smrgstatic inline boolean
2597ec681f3Smrgadapter_format( D3DFORMAT fmt )
2607ec681f3Smrg{
2617ec681f3Smrg    /* Formats that are compatible to display_format (modulo alpha bits) */
2627ec681f3Smrg    static const D3DFORMAT allowed[] = {
2637ec681f3Smrg        D3DFMT_A2R10G10B10,
2647ec681f3Smrg        D3DFMT_X8R8G8B8,
2657ec681f3Smrg        D3DFMT_A8R8G8B8,
2667ec681f3Smrg        D3DFMT_X1R5G5B5,
2677ec681f3Smrg        D3DFMT_A1R5G5B5,
2687ec681f3Smrg        D3DFMT_R5G6B5,
2697ec681f3Smrg    };
2707ec681f3Smrg    unsigned i;
2717ec681f3Smrg
2727ec681f3Smrg    for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
2737ec681f3Smrg        if (fmt == allowed[i]) { return TRUE; }
2747ec681f3Smrg    }
2757ec681f3Smrg    return FALSE;
2767ec681f3Smrg}
2777ec681f3Smrg
2787ec681f3SmrgHRESULT NINE_WINAPI
2797ec681f3SmrgNineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
2807ec681f3Smrg                                D3DDEVTYPE DeviceType,
2817ec681f3Smrg                                D3DFORMAT AdapterFormat,
2827ec681f3Smrg                                DWORD Usage,
2837ec681f3Smrg                                D3DRESOURCETYPE RType,
2847ec681f3Smrg                                D3DFORMAT CheckFormat )
2857ec681f3Smrg{
2867ec681f3Smrg    struct pipe_screen *screen;
2877ec681f3Smrg    HRESULT hr;
2887ec681f3Smrg    enum pipe_format pf;
2897ec681f3Smrg    enum pipe_texture_target target;
2907ec681f3Smrg    unsigned bind = 0;
2917ec681f3Smrg    boolean srgb;
2927ec681f3Smrg
2937ec681f3Smrg    /* Check adapter format. */
2947ec681f3Smrg
2957ec681f3Smrg    DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,
2967ec681f3Smrg        nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));
2977ec681f3Smrg    DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType,
2987ec681f3Smrg        d3dformat_to_string(CheckFormat));
2997ec681f3Smrg
3007ec681f3Smrg    /* Wine tests, but suspicious. Needs more tests. */
3017ec681f3Smrg    user_assert(adapter_format(AdapterFormat), D3DERR_INVALIDCALL);
3027ec681f3Smrg    user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);
3037ec681f3Smrg
3047ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
3057ec681f3Smrg    if (FAILED(hr))
3067ec681f3Smrg        return hr;
3077ec681f3Smrg    pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
3087ec681f3Smrg                                     PIPE_BIND_DISPLAY_TARGET |
3097ec681f3Smrg                                     PIPE_BIND_SHARED, FALSE, FALSE);
3107ec681f3Smrg    if (pf == PIPE_FORMAT_NONE) {
3117ec681f3Smrg        DBG("AdapterFormat %s not available.\n",
3127ec681f3Smrg            d3dformat_to_string(AdapterFormat));
3137ec681f3Smrg        return D3DERR_NOTAVAILABLE;
3147ec681f3Smrg    }
3157ec681f3Smrg
3167ec681f3Smrg    /* Check actual format. */
3177ec681f3Smrg
3187ec681f3Smrg    switch (RType) {
3197ec681f3Smrg    case D3DRTYPE_SURFACE:       target = PIPE_TEXTURE_2D; break;
3207ec681f3Smrg    case D3DRTYPE_TEXTURE:       target = PIPE_TEXTURE_2D; break;
3217ec681f3Smrg    case D3DRTYPE_CUBETEXTURE:   target = PIPE_TEXTURE_CUBE; break;
3227ec681f3Smrg    case D3DRTYPE_VOLUME:        target = PIPE_TEXTURE_3D; break;
3237ec681f3Smrg    case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;
3247ec681f3Smrg    case D3DRTYPE_VERTEXBUFFER:  target = PIPE_BUFFER; break;
3257ec681f3Smrg    case D3DRTYPE_INDEXBUFFER:   target = PIPE_BUFFER; break;
3267ec681f3Smrg    default:
3277ec681f3Smrg        user_assert(0, D3DERR_INVALIDCALL);
3287ec681f3Smrg    }
3297ec681f3Smrg
3307ec681f3Smrg    bind = 0;
3317ec681f3Smrg    if (Usage & D3DUSAGE_RENDERTARGET) {
3327ec681f3Smrg        if (depth_stencil_format(CheckFormat))
3337ec681f3Smrg            return D3DERR_NOTAVAILABLE;
3347ec681f3Smrg        bind |= PIPE_BIND_RENDER_TARGET;
3357ec681f3Smrg    }
3367ec681f3Smrg    if (Usage & D3DUSAGE_DEPTHSTENCIL) {
3377ec681f3Smrg        if (!depth_stencil_format(CheckFormat))
3387ec681f3Smrg            return D3DERR_NOTAVAILABLE;
3397ec681f3Smrg        bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat);
3407ec681f3Smrg    }
3417ec681f3Smrg
3427ec681f3Smrg    /* API hack because setting RT[0] to NULL is forbidden */
3437ec681f3Smrg    if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&
3447ec681f3Smrg        (RType == D3DRTYPE_SURFACE ||
3457ec681f3Smrg         RType == D3DRTYPE_TEXTURE))
3467ec681f3Smrg        return D3D_OK;
3477ec681f3Smrg
3487ec681f3Smrg    /* RESZ hack */
3497ec681f3Smrg    if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&
3507ec681f3Smrg        RType == D3DRTYPE_SURFACE)
3517ec681f3Smrg        return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?
3527ec681f3Smrg               D3D_OK : D3DERR_NOTAVAILABLE;
3537ec681f3Smrg
3547ec681f3Smrg    /* ATOC hack */
3557ec681f3Smrg    if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE)
3567ec681f3Smrg        return D3D_OK;
3577ec681f3Smrg
3587ec681f3Smrg    if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) &&
3597ec681f3Smrg        (Usage & D3DUSAGE_RENDERTARGET))
3607ec681f3Smrg        bind |= PIPE_BIND_BLENDABLE;
3617ec681f3Smrg
3627ec681f3Smrg    if (Usage & D3DUSAGE_DMAP) {
3637ec681f3Smrg        DBG("D3DUSAGE_DMAP not available\n");
3647ec681f3Smrg        return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */
3657ec681f3Smrg    }
3667ec681f3Smrg
3677ec681f3Smrg    switch (RType) {
3687ec681f3Smrg    case D3DRTYPE_TEXTURE:       bind |= PIPE_BIND_SAMPLER_VIEW; break;
3697ec681f3Smrg    case D3DRTYPE_CUBETEXTURE:   bind |= PIPE_BIND_SAMPLER_VIEW; break;
3707ec681f3Smrg    case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
3717ec681f3Smrg    case D3DRTYPE_VERTEXBUFFER:  bind |= PIPE_BIND_VERTEX_BUFFER; break;
3727ec681f3Smrg    case D3DRTYPE_INDEXBUFFER:   bind |= PIPE_BIND_INDEX_BUFFER; break;
3737ec681f3Smrg    case D3DRTYPE_SURFACE:
3747ec681f3Smrg        if (!(Usage & D3DUSAGE_DEPTHSTENCIL))
3757ec681f3Smrg            bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
3767ec681f3Smrg        /* Offscreen surface support: Usage = 0.
3777ec681f3Smrg         * In practice drivers are very restrictive on the formats supported.
3787ec681f3Smrg         * Basically a few common formats + YUV and compressed formats. The
3797ec681f3Smrg         * reason is that offscreen surface are useful only for directdraw
3807ec681f3Smrg         * compatibility (a WONTIMPL of nine) + format conversion (useful in
3817ec681f3Smrg         * particular for YUV because the format was not advertised for textures
3827ec681f3Smrg         * on NV chips). */
3837ec681f3Smrg        if (Usage == 0)
3847ec681f3Smrg            bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */
3857ec681f3Smrg        break;
3867ec681f3Smrg    default:
3877ec681f3Smrg        break;
3887ec681f3Smrg    }
3897ec681f3Smrg
3907ec681f3Smrg
3917ec681f3Smrg    srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;
3927ec681f3Smrg    pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target,
3937ec681f3Smrg                                     0, bind, srgb, FALSE);
3947ec681f3Smrg    if (pf == PIPE_FORMAT_NONE) {
3957ec681f3Smrg        DBG("NOT AVAILABLE\n");
3967ec681f3Smrg        return D3DERR_NOTAVAILABLE;
3977ec681f3Smrg    }
3987ec681f3Smrg
3997ec681f3Smrg    /* we support ATI1 and ATI2 hack only for 2D and Cube textures */
4007ec681f3Smrg    if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE &&
4017ec681f3Smrg        (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2))
4027ec681f3Smrg        return D3DERR_NOTAVAILABLE;
4037ec681f3Smrg    /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */
4047ec681f3Smrg    /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */
4057ec681f3Smrg
4067ec681f3Smrg    if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))
4077ec681f3Smrg        return D3DOK_NOAUTOGEN;
4087ec681f3Smrg    return D3D_OK;
4097ec681f3Smrg}
4107ec681f3Smrg
4117ec681f3SmrgHRESULT NINE_WINAPI
4127ec681f3SmrgNineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
4137ec681f3Smrg                                         D3DDEVTYPE DeviceType,
4147ec681f3Smrg                                         D3DFORMAT SurfaceFormat,
4157ec681f3Smrg                                         BOOL Windowed,
4167ec681f3Smrg                                         D3DMULTISAMPLE_TYPE MultiSampleType,
4177ec681f3Smrg                                         DWORD *pQualityLevels )
4187ec681f3Smrg{
4197ec681f3Smrg    struct pipe_screen *screen;
4207ec681f3Smrg    HRESULT hr;
4217ec681f3Smrg    enum pipe_format pf;
4227ec681f3Smrg    unsigned bind;
4237ec681f3Smrg
4247ec681f3Smrg    DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
4257ec681f3Smrg        "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
4267ec681f3Smrg        d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
4277ec681f3Smrg        pQualityLevels);
4287ec681f3Smrg
4297ec681f3Smrg    if (pQualityLevels) {
4307ec681f3Smrg        /* In error cases return only 1 quality level supported */
4317ec681f3Smrg        *pQualityLevels = 1;
4327ec681f3Smrg    }
4337ec681f3Smrg    user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL);
4347ec681f3Smrg
4357ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
4367ec681f3Smrg    if (FAILED(hr))
4377ec681f3Smrg        return hr;
4387ec681f3Smrg
4397ec681f3Smrg    if (depth_stencil_format(SurfaceFormat))
4407ec681f3Smrg        bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);
4417ec681f3Smrg    else /* render-target */
4427ec681f3Smrg        bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
4437ec681f3Smrg
4447ec681f3Smrg    pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
4457ec681f3Smrg                                     0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE);
4467ec681f3Smrg
4477ec681f3Smrg    if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
4487ec681f3Smrg        DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat));
4497ec681f3Smrg        return D3DERR_INVALIDCALL;
4507ec681f3Smrg    }
4517ec681f3Smrg
4527ec681f3Smrg    pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
4537ec681f3Smrg                                     MultiSampleType, bind, FALSE, FALSE);
4547ec681f3Smrg
4557ec681f3Smrg    if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
4567ec681f3Smrg        DBG("%s with %u samples not available.\n",
4577ec681f3Smrg            d3dformat_to_string(SurfaceFormat), MultiSampleType);
4587ec681f3Smrg        return D3DERR_NOTAVAILABLE;
4597ec681f3Smrg    }
4607ec681f3Smrg
4617ec681f3Smrg    if (pQualityLevels) {
4627ec681f3Smrg        /* NONMASKABLE MultiSampleType might have more than one quality level,
4637ec681f3Smrg         * while MASKABLE MultiSampleTypes have only one level.
4647ec681f3Smrg         * Advertise quality levels and map each level to a sample count. */
4657ec681f3Smrg         (void ) d3dmultisample_type_check(screen, SurfaceFormat,
4667ec681f3Smrg                 &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels);
4677ec681f3Smrg         DBG("advertising %u quality levels\n", *pQualityLevels);
4687ec681f3Smrg    }
4697ec681f3Smrg
4707ec681f3Smrg    return D3D_OK;
4717ec681f3Smrg}
4727ec681f3Smrg
4737ec681f3SmrgHRESULT NINE_WINAPI
4747ec681f3SmrgNineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
4757ec681f3Smrg                                     D3DDEVTYPE DeviceType,
4767ec681f3Smrg                                     D3DFORMAT AdapterFormat,
4777ec681f3Smrg                                     D3DFORMAT RenderTargetFormat,
4787ec681f3Smrg                                     D3DFORMAT DepthStencilFormat )
4797ec681f3Smrg{
4807ec681f3Smrg    struct pipe_screen *screen;
4817ec681f3Smrg    enum pipe_format dfmt, bfmt, zsfmt;
4827ec681f3Smrg    HRESULT hr;
4837ec681f3Smrg
4847ec681f3Smrg    DBG("This=%p DeviceType=%s AdapterFormat=%s "
4857ec681f3Smrg        "RenderTargetFormat=%s DepthStencilFormat=%s\n", This,
4867ec681f3Smrg        nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),
4877ec681f3Smrg        d3dformat_to_string(RenderTargetFormat),
4887ec681f3Smrg        d3dformat_to_string(DepthStencilFormat));
4897ec681f3Smrg
4907ec681f3Smrg    /* TODO: does it check AdapterFormat at all ?
4917ec681f3Smrg     * It seems to need to pass at least for A8R8G8B8:
4927ec681f3Smrg     * https://github.com/iXit/Mesa-3D/issues/317 */
4937ec681f3Smrg    user_assert(adapter_format(AdapterFormat), D3DERR_NOTAVAILABLE);
4947ec681f3Smrg    user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);
4957ec681f3Smrg
4967ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
4977ec681f3Smrg    if (FAILED(hr)) { return hr; }
4987ec681f3Smrg
4997ec681f3Smrg    dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
5007ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
5017ec681f3Smrg    bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat,
5027ec681f3Smrg                                       PIPE_TEXTURE_2D, 0,
5037ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
5047ec681f3Smrg    if (RenderTargetFormat == D3DFMT_NULL)
5057ec681f3Smrg        bfmt = dfmt;
5067ec681f3Smrg    zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat,
5077ec681f3Smrg                                        PIPE_TEXTURE_2D, 0,
5087ec681f3Smrg                                        d3d9_get_pipe_depth_format_bindings(DepthStencilFormat),
5097ec681f3Smrg                                        FALSE, FALSE);
5107ec681f3Smrg    if (dfmt == PIPE_FORMAT_NONE ||
5117ec681f3Smrg        bfmt == PIPE_FORMAT_NONE ||
5127ec681f3Smrg        zsfmt == PIPE_FORMAT_NONE) {
5137ec681f3Smrg        return D3DERR_NOTAVAILABLE;
5147ec681f3Smrg    }
5157ec681f3Smrg
5167ec681f3Smrg    return D3D_OK;
5177ec681f3Smrg}
5187ec681f3Smrg
5197ec681f3SmrgHRESULT NINE_WINAPI
5207ec681f3SmrgNineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,
5217ec681f3Smrg                                          D3DDEVTYPE DeviceType,
5227ec681f3Smrg                                          D3DFORMAT SourceFormat,
5237ec681f3Smrg                                          D3DFORMAT TargetFormat )
5247ec681f3Smrg{
5257ec681f3Smrg    /* MSDN says this tests whether a certain backbuffer format can be used in
5267ec681f3Smrg     * conjunction with a certain front buffer format. It's a little confusing
5277ec681f3Smrg     * but some one wiser might be able to figure this one out. XXX */
5287ec681f3Smrg    struct pipe_screen *screen;
5297ec681f3Smrg    enum pipe_format dfmt, bfmt;
5307ec681f3Smrg    HRESULT hr;
5317ec681f3Smrg
5327ec681f3Smrg    DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This,
5337ec681f3Smrg        nine_D3DDEVTYPE_to_str(DeviceType),
5347ec681f3Smrg        d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat));
5357ec681f3Smrg
5367ec681f3Smrg    user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE),
5377ec681f3Smrg                D3DERR_NOTAVAILABLE);
5387ec681f3Smrg
5397ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
5407ec681f3Smrg    if (FAILED(hr)) { return hr; }
5417ec681f3Smrg
5427ec681f3Smrg    dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1,
5437ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
5447ec681f3Smrg    bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1,
5457ec681f3Smrg                                       NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
5467ec681f3Smrg
5477ec681f3Smrg    if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
5487ec681f3Smrg        DBG("%s to %s not supported.\n",
5497ec681f3Smrg            d3dformat_to_string(SourceFormat),
5507ec681f3Smrg            d3dformat_to_string(TargetFormat));
5517ec681f3Smrg        return D3DERR_NOTAVAILABLE;
5527ec681f3Smrg    }
5537ec681f3Smrg
5547ec681f3Smrg    return D3D_OK;
5557ec681f3Smrg}
5567ec681f3Smrg
5577ec681f3SmrgHRESULT NINE_WINAPI
5587ec681f3SmrgNineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
5597ec681f3Smrg                            D3DDEVTYPE DeviceType,
5607ec681f3Smrg                            D3DCAPS9 *pCaps )
5617ec681f3Smrg{
5627ec681f3Smrg    struct pipe_screen *screen;
5637ec681f3Smrg    HRESULT hr;
5647ec681f3Smrg
5657ec681f3Smrg    DBG("This=%p DeviceType=%s pCaps=%p\n", This,
5667ec681f3Smrg        nine_D3DDEVTYPE_to_str(DeviceType), pCaps);
5677ec681f3Smrg
5687ec681f3Smrg    user_assert(pCaps, D3DERR_INVALIDCALL);
5697ec681f3Smrg
5707ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
5717ec681f3Smrg    if (FAILED(hr)) {
5727ec681f3Smrg       DBG("Failed to get pipe_screen.\n");
5737ec681f3Smrg       return hr;
5747ec681f3Smrg    }
5757ec681f3Smrg
5767ec681f3Smrg#define D3DPIPECAP(pcap, d3dcap) \
5777ec681f3Smrg    (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0)
5787ec681f3Smrg
5797ec681f3Smrg#define D3DNPIPECAP(pcap, d3dcap) \
5807ec681f3Smrg    (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))
5817ec681f3Smrg
5827ec681f3Smrg    pCaps->DeviceType = DeviceType;
5837ec681f3Smrg
5847ec681f3Smrg    pCaps->AdapterOrdinal = 0;
5857ec681f3Smrg
5867ec681f3Smrg    pCaps->Caps = D3DCAPS_READ_SCANLINE;
5877ec681f3Smrg
5887ec681f3Smrg    pCaps->Caps2 = /* D3DCAPS2_CANMANAGERESOURCE | */
5897ec681f3Smrg                /* D3DCAPS2_CANSHARERESOURCE | */
5907ec681f3Smrg                /* D3DCAPS2_CANCALIBRATEGAMMA | */
5917ec681f3Smrg                   D3DCAPS2_DYNAMICTEXTURES |
5927ec681f3Smrg                   D3DCAPS2_FULLSCREENGAMMA |
5937ec681f3Smrg                   D3DCAPS2_CANAUTOGENMIPMAP;
5947ec681f3Smrg
5957ec681f3Smrg    /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the
5967ec681f3Smrg     * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen
5977ec681f3Smrg     * and in discard mode. */
5987ec681f3Smrg    pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
5997ec681f3Smrg                   D3DCAPS3_COPY_TO_VIDMEM |
6007ec681f3Smrg                   D3DCAPS3_COPY_TO_SYSTEMMEM |
6017ec681f3Smrg                   D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION;
6027ec681f3Smrg
6037ec681f3Smrg    pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT |
6047ec681f3Smrg                                   D3DPRESENT_INTERVAL_ONE |
6057ec681f3Smrg                                   D3DPRESENT_INTERVAL_TWO |
6067ec681f3Smrg                                   D3DPRESENT_INTERVAL_THREE |
6077ec681f3Smrg                                   D3DPRESENT_INTERVAL_FOUR |
6087ec681f3Smrg                                   D3DPRESENT_INTERVAL_IMMEDIATE;
6097ec681f3Smrg    pCaps->CursorCaps = D3DCURSORCAPS_COLOR /* | D3DCURSORCAPS_LOWRES*/;
6107ec681f3Smrg
6117ec681f3Smrg    pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL |
6127ec681f3Smrg                     D3DDEVCAPS_CANRENDERAFTERFLIP |
6137ec681f3Smrg                     D3DDEVCAPS_DRAWPRIMITIVES2 |
6147ec681f3Smrg                     D3DDEVCAPS_DRAWPRIMITIVES2EX |
6157ec681f3Smrg                     D3DDEVCAPS_DRAWPRIMTLVERTEX |
6167ec681f3Smrg                     D3DDEVCAPS_EXECUTESYSTEMMEMORY |
6177ec681f3Smrg                     D3DDEVCAPS_EXECUTEVIDEOMEMORY |
6187ec681f3Smrg                     D3DDEVCAPS_HWRASTERIZATION |
6197ec681f3Smrg                     D3DDEVCAPS_HWTRANSFORMANDLIGHT |
6207ec681f3Smrg                     /*D3DDEVCAPS_NPATCHES |*/
6217ec681f3Smrg                     D3DDEVCAPS_PUREDEVICE |
6227ec681f3Smrg                     /*D3DDEVCAPS_QUINTICRTPATCHES |*/
6237ec681f3Smrg                     /*D3DDEVCAPS_RTPATCHES |*/
6247ec681f3Smrg                     /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/
6257ec681f3Smrg                     /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/
6267ec681f3Smrg                     D3DDEVCAPS_TEXTURENONLOCALVIDMEM |
6277ec681f3Smrg                     /* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/
6287ec681f3Smrg                     D3DDEVCAPS_TEXTUREVIDEOMEMORY |
6297ec681f3Smrg                     D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
6307ec681f3Smrg                     D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
6317ec681f3Smrg
6327ec681f3Smrg    pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ |
6337ec681f3Smrg                               D3DPMISCCAPS_CULLNONE | /* XXX */
6347ec681f3Smrg                               D3DPMISCCAPS_CULLCW |
6357ec681f3Smrg                               D3DPMISCCAPS_CULLCCW |
6367ec681f3Smrg                               D3DPMISCCAPS_COLORWRITEENABLE |
6377ec681f3Smrg                               D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
6387ec681f3Smrg                               /*D3DPMISCCAPS_CLIPTLVERTS |*/
6397ec681f3Smrg                               D3DPMISCCAPS_TSSARGTEMP |
6407ec681f3Smrg                               D3DPMISCCAPS_BLENDOP |
6417ec681f3Smrg                               D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |
6427ec681f3Smrg                               D3DPMISCCAPS_PERSTAGECONSTANT |
6437ec681f3Smrg                               /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */
6447ec681f3Smrg                               D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */
6457ec681f3Smrg                               D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |
6467ec681f3Smrg                               D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |
6477ec681f3Smrg                               D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |
6487ec681f3Smrg                               D3DPMISCCAPS_FOGVERTEXCLAMPED;
6497ec681f3Smrg    if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION))
6507ec681f3Smrg        pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS;
6517ec681f3Smrg
6527ec681f3Smrg    pCaps->RasterCaps =
6537ec681f3Smrg        D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |
6547ec681f3Smrg        D3DPRASTERCAPS_COLORPERSPECTIVE |
6557ec681f3Smrg        D3DPRASTERCAPS_DITHER |
6567ec681f3Smrg        D3DPRASTERCAPS_DEPTHBIAS |
6577ec681f3Smrg        D3DPRASTERCAPS_FOGRANGE |
6587ec681f3Smrg        D3DPRASTERCAPS_FOGTABLE |
6597ec681f3Smrg        D3DPRASTERCAPS_FOGVERTEX |
6607ec681f3Smrg        D3DPRASTERCAPS_MIPMAPLODBIAS |
6617ec681f3Smrg        D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |
6627ec681f3Smrg        D3DPRASTERCAPS_SCISSORTEST |
6637ec681f3Smrg        D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
6647ec681f3Smrg        /*D3DPRASTERCAPS_WBUFFER |*/
6657ec681f3Smrg        D3DPRASTERCAPS_WFOG |
6667ec681f3Smrg        /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/
6677ec681f3Smrg        D3DPRASTERCAPS_ZFOG |
6687ec681f3Smrg        D3DPRASTERCAPS_ZTEST;
6697ec681f3Smrg
6707ec681f3Smrg    pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |
6717ec681f3Smrg                      D3DPCMPCAPS_LESS |
6727ec681f3Smrg                      D3DPCMPCAPS_EQUAL |
6737ec681f3Smrg                      D3DPCMPCAPS_LESSEQUAL |
6747ec681f3Smrg                      D3DPCMPCAPS_GREATER |
6757ec681f3Smrg                      D3DPCMPCAPS_NOTEQUAL |
6767ec681f3Smrg                      D3DPCMPCAPS_GREATEREQUAL |
6777ec681f3Smrg                      D3DPCMPCAPS_ALWAYS;
6787ec681f3Smrg
6797ec681f3Smrg    pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO |
6807ec681f3Smrg                          D3DPBLENDCAPS_ONE |
6817ec681f3Smrg                          D3DPBLENDCAPS_SRCCOLOR |
6827ec681f3Smrg                          D3DPBLENDCAPS_INVSRCCOLOR |
6837ec681f3Smrg                          D3DPBLENDCAPS_SRCALPHA |
6847ec681f3Smrg                          D3DPBLENDCAPS_INVSRCALPHA |
6857ec681f3Smrg                          D3DPBLENDCAPS_DESTALPHA |
6867ec681f3Smrg                          D3DPBLENDCAPS_INVDESTALPHA |
6877ec681f3Smrg                          D3DPBLENDCAPS_DESTCOLOR |
6887ec681f3Smrg                          D3DPBLENDCAPS_INVDESTCOLOR |
6897ec681f3Smrg                          D3DPBLENDCAPS_SRCALPHASAT |
6907ec681f3Smrg                          D3DPBLENDCAPS_BOTHSRCALPHA |
6917ec681f3Smrg                          D3DPBLENDCAPS_BOTHINVSRCALPHA |
6927ec681f3Smrg                          D3DPBLENDCAPS_BLENDFACTOR |
6937ec681f3Smrg                          D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS,
6947ec681f3Smrg                              D3DPBLENDCAPS_INVSRCCOLOR2 |
6957ec681f3Smrg                              D3DPBLENDCAPS_SRCCOLOR2);
6967ec681f3Smrg
6977ec681f3Smrg    pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
6987ec681f3Smrg
6997ec681f3Smrg    pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER |
7007ec681f3Smrg                          D3DPCMPCAPS_LESS |
7017ec681f3Smrg                          D3DPCMPCAPS_EQUAL |
7027ec681f3Smrg                          D3DPCMPCAPS_LESSEQUAL |
7037ec681f3Smrg                          D3DPCMPCAPS_GREATER |
7047ec681f3Smrg                          D3DPCMPCAPS_NOTEQUAL |
7057ec681f3Smrg                          D3DPCMPCAPS_GREATEREQUAL |
7067ec681f3Smrg                          D3DPCMPCAPS_ALWAYS;
7077ec681f3Smrg
7087ec681f3Smrg    /* FLAT caps not legal for D3D9. */
7097ec681f3Smrg    pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB |
7107ec681f3Smrg                       D3DPSHADECAPS_SPECULARGOURAUDRGB |
7117ec681f3Smrg                       D3DPSHADECAPS_ALPHAGOURAUDBLEND |
7127ec681f3Smrg                       D3DPSHADECAPS_FOGGOURAUD;
7137ec681f3Smrg
7147ec681f3Smrg    pCaps->TextureCaps =
7157ec681f3Smrg        D3DPTEXTURECAPS_ALPHA |
7167ec681f3Smrg        D3DPTEXTURECAPS_ALPHAPALETTE |
7177ec681f3Smrg        D3DPTEXTURECAPS_PERSPECTIVE |
7187ec681f3Smrg        D3DPTEXTURECAPS_PROJECTED |
7197ec681f3Smrg        D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE |
7207ec681f3Smrg        D3DPTEXTURECAPS_CUBEMAP |
7217ec681f3Smrg        D3DPTEXTURECAPS_VOLUMEMAP |
7227ec681f3Smrg        D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) |
7237ec681f3Smrg        D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) |
7247ec681f3Smrg        D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) |
7257ec681f3Smrg        D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) |
7267ec681f3Smrg        D3DPIPECAP(MAX_TEXTURE_2D_SIZE, D3DPTEXTURECAPS_MIPMAP) |
7277ec681f3Smrg        D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) |
7287ec681f3Smrg        D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP);
7297ec681f3Smrg
7307ec681f3Smrg    pCaps->TextureFilterCaps =
7317ec681f3Smrg        D3DPTFILTERCAPS_MINFPOINT |
7327ec681f3Smrg        D3DPTFILTERCAPS_MINFLINEAR |
7337ec681f3Smrg        D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) |
7347ec681f3Smrg        /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/
7357ec681f3Smrg        /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/
7367ec681f3Smrg        D3DPTFILTERCAPS_MIPFPOINT |
7377ec681f3Smrg        D3DPTFILTERCAPS_MIPFLINEAR |
7387ec681f3Smrg        D3DPTFILTERCAPS_MAGFPOINT |
7397ec681f3Smrg        D3DPTFILTERCAPS_MAGFLINEAR |
7407ec681f3Smrg        D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) |
7417ec681f3Smrg        /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/
7427ec681f3Smrg        /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0;
7437ec681f3Smrg
7447ec681f3Smrg    pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;
7457ec681f3Smrg    pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;
7467ec681f3Smrg
7477ec681f3Smrg    pCaps->TextureAddressCaps =
7487ec681f3Smrg        D3DPTADDRESSCAPS_BORDER |
7497ec681f3Smrg        D3DPTADDRESSCAPS_INDEPENDENTUV |
7507ec681f3Smrg        D3DPTADDRESSCAPS_WRAP |
7517ec681f3Smrg        D3DPTADDRESSCAPS_MIRROR |
7527ec681f3Smrg        D3DPTADDRESSCAPS_CLAMP |
7537ec681f3Smrg        D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE);
7547ec681f3Smrg
7557ec681f3Smrg    pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;
7567ec681f3Smrg
7577ec681f3Smrg    pCaps->LineCaps =
7587ec681f3Smrg        D3DLINECAPS_ALPHACMP |
7597ec681f3Smrg        D3DLINECAPS_BLEND |
7607ec681f3Smrg        D3DLINECAPS_TEXTURE |
7617ec681f3Smrg        D3DLINECAPS_ZTEST |
7627ec681f3Smrg        D3DLINECAPS_FOG;
7637ec681f3Smrg    if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) {
7647ec681f3Smrg        pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS;
7657ec681f3Smrg    }
7667ec681f3Smrg
7677ec681f3Smrg    pCaps->MaxTextureWidth =screen->get_param(screen,
7687ec681f3Smrg                                              PIPE_CAP_MAX_TEXTURE_2D_SIZE);
7697ec681f3Smrg    pCaps->MaxTextureHeight = pCaps->MaxTextureWidth;
7707ec681f3Smrg    pCaps->MaxVolumeExtent =
7717ec681f3Smrg        1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1);
7727ec681f3Smrg    /* XXX values from wine */
7737ec681f3Smrg    pCaps->MaxTextureRepeat = 32768;
7747ec681f3Smrg    pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth;
7757ec681f3Smrg
7767ec681f3Smrg    pCaps->MaxAnisotropy =
7777ec681f3Smrg        (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);
7787ec681f3Smrg
7797ec681f3Smrg    /* Values for GeForce 9600 GT */
7807ec681f3Smrg    pCaps->MaxVertexW = 1e10f;
7817ec681f3Smrg    pCaps->GuardBandLeft = -1e9f;
7827ec681f3Smrg    pCaps->GuardBandTop = -1e9f;
7837ec681f3Smrg    pCaps->GuardBandRight = 1e9f;
7847ec681f3Smrg    pCaps->GuardBandBottom = 1e9f;
7857ec681f3Smrg    pCaps->ExtentsAdjust = 0.0f;
7867ec681f3Smrg
7877ec681f3Smrg    pCaps->StencilCaps =
7887ec681f3Smrg        D3DSTENCILCAPS_KEEP |
7897ec681f3Smrg        D3DSTENCILCAPS_ZERO |
7907ec681f3Smrg        D3DSTENCILCAPS_REPLACE |
7917ec681f3Smrg        D3DSTENCILCAPS_INCRSAT |
7927ec681f3Smrg        D3DSTENCILCAPS_DECRSAT |
7937ec681f3Smrg        D3DSTENCILCAPS_INVERT |
7947ec681f3Smrg        D3DSTENCILCAPS_INCR |
7957ec681f3Smrg        D3DSTENCILCAPS_DECR |
7967ec681f3Smrg        D3DSTENCILCAPS_TWOSIDED;
7977ec681f3Smrg
7987ec681f3Smrg    pCaps->FVFCaps =
7997ec681f3Smrg        8 | /* 8 textures max */
8007ec681f3Smrg        /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/
8017ec681f3Smrg        D3DFVFCAPS_PSIZE;
8027ec681f3Smrg
8037ec681f3Smrg    pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |
8047ec681f3Smrg                           D3DTEXOPCAPS_SELECTARG1 |
8057ec681f3Smrg                           D3DTEXOPCAPS_SELECTARG2 |
8067ec681f3Smrg                           D3DTEXOPCAPS_MODULATE |
8077ec681f3Smrg                           D3DTEXOPCAPS_MODULATE2X |
8087ec681f3Smrg                           D3DTEXOPCAPS_MODULATE4X |
8097ec681f3Smrg                           D3DTEXOPCAPS_ADD |
8107ec681f3Smrg                           D3DTEXOPCAPS_ADDSIGNED |
8117ec681f3Smrg                           D3DTEXOPCAPS_ADDSIGNED2X |
8127ec681f3Smrg                           D3DTEXOPCAPS_SUBTRACT |
8137ec681f3Smrg                           D3DTEXOPCAPS_ADDSMOOTH |
8147ec681f3Smrg                           D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
8157ec681f3Smrg                           D3DTEXOPCAPS_BLENDTEXTUREALPHA |
8167ec681f3Smrg                           D3DTEXOPCAPS_BLENDFACTORALPHA |
8177ec681f3Smrg                           D3DTEXOPCAPS_BLENDTEXTUREALPHAPM |
8187ec681f3Smrg                           D3DTEXOPCAPS_BLENDCURRENTALPHA |
8197ec681f3Smrg                           D3DTEXOPCAPS_PREMODULATE |
8207ec681f3Smrg                           D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
8217ec681f3Smrg                           D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
8227ec681f3Smrg                           D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
8237ec681f3Smrg                           D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |
8247ec681f3Smrg                           D3DTEXOPCAPS_BUMPENVMAP |
8257ec681f3Smrg                           D3DTEXOPCAPS_BUMPENVMAPLUMINANCE |
8267ec681f3Smrg                           D3DTEXOPCAPS_DOTPRODUCT3 |
8277ec681f3Smrg                           D3DTEXOPCAPS_MULTIPLYADD |
8287ec681f3Smrg                           D3DTEXOPCAPS_LERP;
8297ec681f3Smrg
8307ec681f3Smrg    pCaps->MaxTextureBlendStages = 8; /* XXX wine */
8317ec681f3Smrg        (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE);
8327ec681f3Smrg    pCaps->MaxSimultaneousTextures = 8;
8337ec681f3Smrg
8347ec681f3Smrg    pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN |
8357ec681f3Smrg                                  D3DVTXPCAPS_TEXGEN_SPHEREMAP |
8367ec681f3Smrg                                  D3DVTXPCAPS_MATERIALSOURCE7 |
8377ec681f3Smrg                                  D3DVTXPCAPS_DIRECTIONALLIGHTS |
8387ec681f3Smrg                                  D3DVTXPCAPS_POSITIONALLIGHTS |
8397ec681f3Smrg                                  D3DVTXPCAPS_LOCALVIEWER |
8407ec681f3Smrg                                  D3DVTXPCAPS_TWEENING |
8417ec681f3Smrg                                  /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0;
8427ec681f3Smrg
8437ec681f3Smrg    pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */
8447ec681f3Smrg    pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES;
8457ec681f3Smrg    pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */
8467ec681f3Smrg    pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */
8477ec681f3Smrg
8487ec681f3Smrg    pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH);
8497ec681f3Smrg
8507ec681f3Smrg    pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */
8517ec681f3Smrg    pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */
8527ec681f3Smrg    pCaps->MaxStreams =
8537ec681f3Smrg        _min(screen->get_shader_param(screen,
8547ec681f3Smrg                 PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS),
8557ec681f3Smrg             16);
8567ec681f3Smrg
8577ec681f3Smrg    pCaps->MaxStreamStride = screen->get_param(screen,
8587ec681f3Smrg            PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);
8597ec681f3Smrg
8607ec681f3Smrg    pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
8617ec681f3Smrg
8627ec681f3Smrg    /* VS 2 as well as 3.0 supports a minimum of 256 consts.
8637ec681f3Smrg     * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them,
8647ec681f3Smrg     * advertise 256. Problem is with hw that can only do 256, because
8657ec681f3Smrg     * we need take a few slots for boolean and integer constants. For these
8667ec681f3Smrg     * we'll have to fail later if they use complex shaders. */
8677ec681f3Smrg    pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;
8687ec681f3Smrg
8697ec681f3Smrg    pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
8707ec681f3Smrg    /* Value for GeForce 9600 GT */
8717ec681f3Smrg    pCaps->PixelShader1xMaxValue = 65504.f;
8727ec681f3Smrg
8737ec681f3Smrg    pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
8747ec681f3Smrg                      D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |
8757ec681f3Smrg                      D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES |
8767ec681f3Smrg                      /*D3DDEVCAPS2_DMAPNPATCH |*/
8777ec681f3Smrg                      /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/
8787ec681f3Smrg                      /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/
8797ec681f3Smrg                      /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0;
8807ec681f3Smrg
8817ec681f3Smrg    pCaps->MasterAdapterOrdinal = 0;
8827ec681f3Smrg    pCaps->AdapterOrdinalInGroup = 0;
8837ec681f3Smrg    pCaps->NumberOfAdaptersInGroup = 1;
8847ec681f3Smrg
8857ec681f3Smrg    /* Undocumented ? */
8867ec681f3Smrg    pCaps->MaxNpatchTessellationLevel = 0.0f;
8877ec681f3Smrg    pCaps->Reserved5 = 0;
8887ec681f3Smrg
8897ec681f3Smrg    /* XXX: use is_format_supported */
8907ec681f3Smrg    pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
8917ec681f3Smrg                       D3DDTCAPS_UBYTE4N |
8927ec681f3Smrg                       D3DDTCAPS_SHORT2N |
8937ec681f3Smrg                       D3DDTCAPS_SHORT4N |
8947ec681f3Smrg                       D3DDTCAPS_USHORT2N |
8957ec681f3Smrg                       D3DDTCAPS_USHORT4N |
8967ec681f3Smrg                       D3DDTCAPS_UDEC3 |
8977ec681f3Smrg                       D3DDTCAPS_DEC3N |
8987ec681f3Smrg                       D3DDTCAPS_FLOAT16_2 |
8997ec681f3Smrg                       D3DDTCAPS_FLOAT16_4;
9007ec681f3Smrg
9017ec681f3Smrg    pCaps->NumSimultaneousRTs =
9027ec681f3Smrg        screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS);
9037ec681f3Smrg    if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS)
9047ec681f3Smrg        pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS;
9057ec681f3Smrg
9067ec681f3Smrg    pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT |
9077ec681f3Smrg                                   D3DPTFILTERCAPS_MINFLINEAR |
9087ec681f3Smrg                                   D3DPTFILTERCAPS_MAGFPOINT |
9097ec681f3Smrg                                   D3DPTFILTERCAPS_MAGFLINEAR;
9107ec681f3Smrg
9117ec681f3Smrg
9127ec681f3Smrg    pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
9137ec681f3Smrg    pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
9147ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
9157ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
9167ec681f3Smrg    pCaps->VS20Caps.NumTemps =
9177ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
9187ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEMPS);
9197ec681f3Smrg    pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */
9207ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
9217ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
9227ec681f3Smrg
9237ec681f3Smrg    /* also check for values < 0, because get_shader_param may return unsigned */
9247ec681f3Smrg    if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
9257ec681f3Smrg        || pCaps->VS20Caps.DynamicFlowControlDepth < 0)
9267ec681f3Smrg        pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
9277ec681f3Smrg    if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH
9287ec681f3Smrg        || pCaps->VS20Caps.StaticFlowControlDepth < 0)
9297ec681f3Smrg        pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH;
9307ec681f3Smrg    if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS)
9317ec681f3Smrg        pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
9327ec681f3Smrg    assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH);
9337ec681f3Smrg    assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH);
9347ec681f3Smrg    assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS);
9357ec681f3Smrg
9367ec681f3Smrg
9377ec681f3Smrg    pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
9387ec681f3Smrg                           D3DPS20CAPS_GRADIENTINSTRUCTIONS |
9397ec681f3Smrg                           D3DPS20CAPS_PREDICATION;
9407ec681f3Smrg    if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9417ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
9427ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9437ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
9447ec681f3Smrg        pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
9457ec681f3Smrg    if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9467ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
9477ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9487ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS))
9497ec681f3Smrg        pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT;
9507ec681f3Smrg    pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
9517ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9527ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
9537ec681f3Smrg    pCaps->PS20Caps.NumTemps =
9547ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9557ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEMPS);
9567ec681f3Smrg    pCaps->PS20Caps.StaticFlowControlDepth =  /* XXX is this static ? */
9577ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9587ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
9597ec681f3Smrg    pCaps->PS20Caps.NumInstructionSlots =
9607ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9617ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
9627ec681f3Smrg
9637ec681f3Smrg    if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
9647ec681f3Smrg        || pCaps->PS20Caps.DynamicFlowControlDepth < 0)
9657ec681f3Smrg        pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
9667ec681f3Smrg    if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH
9677ec681f3Smrg        || pCaps->PS20Caps.StaticFlowControlDepth < 0)
9687ec681f3Smrg        pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH;
9697ec681f3Smrg    if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS)
9707ec681f3Smrg        pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS;
9717ec681f3Smrg    if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS)
9727ec681f3Smrg        pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS;
9737ec681f3Smrg    assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH);
9747ec681f3Smrg    assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH);
9757ec681f3Smrg    assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS);
9767ec681f3Smrg    assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS);
9777ec681f3Smrg
9787ec681f3Smrg
9797ec681f3Smrg    if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
9807ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
9817ec681f3Smrg        pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps &
9827ec681f3Smrg            ~(D3DPTFILTERCAPS_MIPFPOINT |
9837ec681f3Smrg              D3DPTFILTERCAPS_MIPFPOINT); /* XXX */
9847ec681f3Smrg    else
9857ec681f3Smrg        pCaps->VertexTextureFilterCaps = 0;
9867ec681f3Smrg
9877ec681f3Smrg    pCaps->MaxVertexShader30InstructionSlots =
9887ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
9897ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
9907ec681f3Smrg    pCaps->MaxPixelShader30InstructionSlots =
9917ec681f3Smrg        screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
9927ec681f3Smrg                                 PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
9937ec681f3Smrg    if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
9947ec681f3Smrg        pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
9957ec681f3Smrg    if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
9967ec681f3Smrg        pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
9977ec681f3Smrg    assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
9987ec681f3Smrg    assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
9997ec681f3Smrg
10007ec681f3Smrg    /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */
10017ec681f3Smrg    pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);
10027ec681f3Smrg    pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32);
10037ec681f3Smrg
10047ec681f3Smrg    if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE))
10057ec681f3Smrg        nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps);
10067ec681f3Smrg
10077ec681f3Smrg    return D3D_OK;
10087ec681f3Smrg}
10097ec681f3Smrg
10107ec681f3SmrgHRESULT NINE_WINAPI
10117ec681f3SmrgNineAdapter9_CreateDevice( struct NineAdapter9 *This,
10127ec681f3Smrg                           UINT RealAdapter,
10137ec681f3Smrg                           D3DDEVTYPE DeviceType,
10147ec681f3Smrg                           HWND hFocusWindow,
10157ec681f3Smrg                           DWORD BehaviorFlags,
10167ec681f3Smrg                           D3DPRESENT_PARAMETERS *pPresentationParameters,
10177ec681f3Smrg                           IDirect3D9 *pD3D9,
10187ec681f3Smrg                           ID3DPresentGroup *pPresentationGroup,
10197ec681f3Smrg                           IDirect3DDevice9 **ppReturnedDeviceInterface )
10207ec681f3Smrg{
10217ec681f3Smrg    struct pipe_screen *screen;
10227ec681f3Smrg    D3DDEVICE_CREATION_PARAMETERS params;
10237ec681f3Smrg    D3DCAPS9 caps;
10247ec681f3Smrg    int major, minor;
10257ec681f3Smrg    HRESULT hr;
10267ec681f3Smrg
10277ec681f3Smrg    DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
10287ec681f3Smrg        "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p "
10297ec681f3Smrg        "ppReturnedDeviceInterface=%p\n", This,
10307ec681f3Smrg        RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
10317ec681f3Smrg        BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface);
10327ec681f3Smrg
10337ec681f3Smrg    ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
10347ec681f3Smrg    if (major != 1) {
10357ec681f3Smrg        ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
10367ec681f3Smrg            major, minor);
10377ec681f3Smrg        return D3DERR_NOTAVAILABLE;
10387ec681f3Smrg    }
10397ec681f3Smrg
10407ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
10417ec681f3Smrg    if (FAILED(hr)) {
10427ec681f3Smrg        DBG("Failed to get pipe_screen.\n");
10437ec681f3Smrg        return hr;
10447ec681f3Smrg    }
10457ec681f3Smrg
10467ec681f3Smrg    hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
10477ec681f3Smrg    if (FAILED(hr)) {
10487ec681f3Smrg        DBG("Failed to get device caps.\n");
10497ec681f3Smrg        return hr;
10507ec681f3Smrg    }
10517ec681f3Smrg
10527ec681f3Smrg    params.AdapterOrdinal = RealAdapter;
10537ec681f3Smrg    params.DeviceType = DeviceType;
10547ec681f3Smrg    params.hFocusWindow = hFocusWindow;
10557ec681f3Smrg    params.BehaviorFlags = BehaviorFlags;
10567ec681f3Smrg
10577ec681f3Smrg    hr = NineDevice9_new(screen, &params, &caps, pPresentationParameters,
10587ec681f3Smrg                         pD3D9, pPresentationGroup, This->ctx, FALSE, NULL,
10597ec681f3Smrg                         (struct NineDevice9 **)ppReturnedDeviceInterface,
10607ec681f3Smrg                         minor);
10617ec681f3Smrg    if (FAILED(hr)) {
10627ec681f3Smrg        DBG("Failed to create device.\n");
10637ec681f3Smrg        return hr;
10647ec681f3Smrg    }
10657ec681f3Smrg    DBG("NineDevice9 created successfully.\n");
10667ec681f3Smrg
10677ec681f3Smrg    return D3D_OK;
10687ec681f3Smrg}
10697ec681f3Smrg
10707ec681f3SmrgHRESULT NINE_WINAPI
10717ec681f3SmrgNineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,
10727ec681f3Smrg                             UINT RealAdapter,
10737ec681f3Smrg                             D3DDEVTYPE DeviceType,
10747ec681f3Smrg                             HWND hFocusWindow,
10757ec681f3Smrg                             DWORD BehaviorFlags,
10767ec681f3Smrg                             D3DPRESENT_PARAMETERS *pPresentationParameters,
10777ec681f3Smrg                             D3DDISPLAYMODEEX *pFullscreenDisplayMode,
10787ec681f3Smrg                             IDirect3D9Ex *pD3D9Ex,
10797ec681f3Smrg                             ID3DPresentGroup *pPresentationGroup,
10807ec681f3Smrg                             IDirect3DDevice9Ex **ppReturnedDeviceInterface )
10817ec681f3Smrg{
10827ec681f3Smrg    struct pipe_screen *screen;
10837ec681f3Smrg    D3DDEVICE_CREATION_PARAMETERS params;
10847ec681f3Smrg    D3DCAPS9 caps;
10857ec681f3Smrg    int major, minor;
10867ec681f3Smrg    HRESULT hr;
10877ec681f3Smrg
10887ec681f3Smrg    DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
10897ec681f3Smrg        "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p "
10907ec681f3Smrg        "ppReturnedDeviceInterface=%p\n", This,
10917ec681f3Smrg        RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
10927ec681f3Smrg        BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface);
10937ec681f3Smrg
10947ec681f3Smrg    ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
10957ec681f3Smrg    if (major != 1) {
10967ec681f3Smrg        ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
10977ec681f3Smrg            major, minor);
10987ec681f3Smrg        return D3DERR_NOTAVAILABLE;
10997ec681f3Smrg    }
11007ec681f3Smrg
11017ec681f3Smrg    hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
11027ec681f3Smrg    if (FAILED(hr)) {
11037ec681f3Smrg        DBG("Failed to get pipe_screen.\n");
11047ec681f3Smrg        return hr;
11057ec681f3Smrg    }
11067ec681f3Smrg
11077ec681f3Smrg    hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
11087ec681f3Smrg    if (FAILED(hr)) {
11097ec681f3Smrg        DBG("Failed to get device caps.\n");
11107ec681f3Smrg        return hr;
11117ec681f3Smrg    }
11127ec681f3Smrg
11137ec681f3Smrg    params.AdapterOrdinal = RealAdapter;
11147ec681f3Smrg    params.DeviceType = DeviceType;
11157ec681f3Smrg    params.hFocusWindow = hFocusWindow;
11167ec681f3Smrg    params.BehaviorFlags = BehaviorFlags;
11177ec681f3Smrg
11187ec681f3Smrg    hr = NineDevice9Ex_new(screen, &params, &caps, pPresentationParameters,
11197ec681f3Smrg                           pFullscreenDisplayMode,
11207ec681f3Smrg                           pD3D9Ex, pPresentationGroup, This->ctx,
11217ec681f3Smrg                           (struct NineDevice9Ex **)ppReturnedDeviceInterface,
11227ec681f3Smrg                           minor);
11237ec681f3Smrg    if (FAILED(hr)) {
11247ec681f3Smrg        DBG("Failed to create device.\n");
11257ec681f3Smrg        return hr;
11267ec681f3Smrg    }
11277ec681f3Smrg    DBG("NineDevice9Ex created successfully.\n");
11287ec681f3Smrg
11297ec681f3Smrg    return D3D_OK;
11307ec681f3Smrg}
11317ec681f3Smrg
11327ec681f3SmrgID3DAdapter9Vtbl NineAdapter9_vtable = {
11337ec681f3Smrg    (void *)NineUnknown_QueryInterface,
11347ec681f3Smrg    (void *)NineUnknown_AddRef,
11357ec681f3Smrg    (void *)NineUnknown_Release,
11367ec681f3Smrg    (void *)NineAdapter9_GetAdapterIdentifier,
11377ec681f3Smrg    (void *)NineAdapter9_CheckDeviceType,
11387ec681f3Smrg    (void *)NineAdapter9_CheckDeviceFormat,
11397ec681f3Smrg    (void *)NineAdapter9_CheckDeviceMultiSampleType,
11407ec681f3Smrg    (void *)NineAdapter9_CheckDepthStencilMatch,
11417ec681f3Smrg    (void *)NineAdapter9_CheckDeviceFormatConversion,
11427ec681f3Smrg    (void *)NineAdapter9_GetDeviceCaps,
11437ec681f3Smrg    (void *)NineAdapter9_CreateDevice,
11447ec681f3Smrg    (void *)NineAdapter9_CreateDeviceEx
11457ec681f3Smrg};
11467ec681f3Smrg
11477ec681f3Smrgstatic const GUID *NineAdapter9_IIDs[] = {
11487ec681f3Smrg    &IID_ID3D9Adapter,
11497ec681f3Smrg    &IID_IUnknown,
11507ec681f3Smrg    NULL
11517ec681f3Smrg};
11527ec681f3Smrg
11537ec681f3SmrgHRESULT
11547ec681f3SmrgNineAdapter9_new( struct d3dadapter9_context *pCTX,
11557ec681f3Smrg                  struct NineAdapter9 **ppOut )
11567ec681f3Smrg{
11577ec681f3Smrg    NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX);
11587ec681f3Smrg}
1159