Home | History | Annotate | Download | only in nine
      1 /*
      2  * Copyright 2011 Joakim Sindholt <opensource (at) zhasha.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
     22 
     23 #include "adapter9.h"
     24 #include "device9ex.h"
     25 #include "nine_helpers.h"
     26 #include "nine_defines.h"
     27 #include "nine_pipe.h"
     28 #include "nine_dump.h"
     29 #include "util/u_math.h"
     30 #include "util/u_format.h"
     31 #include "util/u_dump.h"
     32 
     33 #include "pipe/p_screen.h"
     34 
     35 #define DBG_CHANNEL DBG_ADAPTER
     36 
     37 HRESULT
     38 NineAdapter9_ctor( struct NineAdapter9 *This,
     39                    struct NineUnknownParams *pParams,
     40                    struct d3dadapter9_context *pCTX )
     41 {
     42     struct pipe_screen *hal = pCTX->hal;
     43     HRESULT hr = NineUnknown_ctor(&This->base, pParams);
     44     if (FAILED(hr)) { return hr; }
     45 
     46     DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX);
     47     nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier);
     48 
     49     This->ctx = pCTX;
     50     if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) {
     51         ERR("Driver doesn't support d3d9 coordinates\n");
     52         return D3DERR_DRIVERINTERNALERROR;
     53     }
     54     if (This->ctx->ref &&
     55         !This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) {
     56         ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n");
     57     }
     58     /* Old cards had tricks to bypass some restrictions to implement
     59      * everything and fit tight the requirements: number of constants,
     60      * number of temp registers, special behaviours, etc. Since we don't
     61      * have access to all this, we need a bit more than what dx9 required.
     62      * For example we have to use more than 32 temp registers to emulate
     63      * behaviours, while some dx9 hw don't have more. As for sm2 hardware,
     64      * we could support vs2 / ps2 for them but it needs some more care, and
     65      * as these are very old, we choose to drop support for them */
     66 
     67     /* checks minimum requirements, most are vs3/ps3 strict requirements */
     68     if (!hal->get_param(hal, PIPE_CAP_SM3) ||
     69         hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
     70                               PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) ||
     71         hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
     72                               PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) ||
     73         hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
     74                               PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
     75         hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
     76                               PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||
     77         hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
     78                               PIPE_SHADER_CAP_MAX_INPUTS) < 16 ||
     79         hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
     80                               PIPE_SHADER_CAP_MAX_INPUTS) < 10) {
     81         ERR("Your card is not supported by Gallium Nine. Minimum requirement "
     82             "is >= r500, >= nv50, >= i965\n");
     83         return D3DERR_DRIVERINTERNALERROR;
     84     }
     85     /* for r500 */
     86     if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
     87                               PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */
     88         hal->get_shader_param(hal, PIPE_SHADER_VERTEX,
     89                               PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */
     90         hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
     91                               PIPE_SHADER_CAP_MAX_TEMPS) < 40 ||
     92         hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,
     93                               PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */
     94         ERR("Your card is at the limit of Gallium Nine requirements. Some games "
     95             "may run into issues because requirements are too tight\n");
     96     return D3D_OK;
     97 }
     98 
     99 void
    100 NineAdapter9_dtor( struct NineAdapter9 *This )
    101 {
    102     struct d3dadapter9_context *ctx = This->ctx;
    103 
    104     DBG("This=%p\n", This);
    105 
    106     NineUnknown_dtor(&This->base);
    107 
    108     /* special case, call backend-specific dtor AFTER destroying this object
    109      * completely. */
    110     if (ctx) {
    111         if (ctx->destroy) { ctx->destroy(ctx); }
    112     }
    113 }
    114 
    115 static HRESULT
    116 NineAdapter9_GetScreen( struct NineAdapter9 *This,
    117                         D3DDEVTYPE DevType,
    118                         struct pipe_screen **ppScreen )
    119 {
    120     const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE");
    121     switch (DevType) {
    122         case D3DDEVTYPE_HAL:
    123             if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) {
    124                 *ppScreen = This->ctx->ref;
    125                 break;
    126             }
    127             *ppScreen = This->ctx->hal;
    128             break;
    129 
    130         case D3DDEVTYPE_REF:
    131         case D3DDEVTYPE_NULLREF:
    132         case D3DDEVTYPE_SW:
    133             if (force_sw && !strcmp(force_sw, "0")) {
    134                 *ppScreen = This->ctx->hal;
    135                 break;
    136             }
    137             *ppScreen = This->ctx->ref;
    138             break;
    139 
    140         default:
    141             user_assert(!"Invalid device type", D3DERR_INVALIDCALL);
    142     }
    143 
    144     if (!*ppScreen) { return D3DERR_NOTAVAILABLE; }
    145 
    146     return D3D_OK;
    147 }
    148 
    149 HRESULT NINE_WINAPI
    150 NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This,
    151                                    DWORD Flags,
    152                                    D3DADAPTER_IDENTIFIER9 *pIdentifier )
    153 {
    154     DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier);
    155 
    156     /* regarding flags, MSDN has this to say:
    157      *  Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be
    158      *  set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is
    159      *  specified, this call can connect to the Internet to download new
    160      *  Microsoft Windows Hardware Quality Labs (WHQL) certificates.
    161      * so let's just ignore it. */
    162     *pIdentifier = This->ctx->identifier;
    163     return D3D_OK;
    164 }
    165 
    166 static inline boolean
    167 backbuffer_format( D3DFORMAT dfmt,
    168                    D3DFORMAT bfmt,
    169                    boolean win )
    170 {
    171     if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
    172 
    173     if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) ||
    174         (dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt ||
    175                                      bfmt == D3DFMT_A8R8G8B8)) ||
    176         (dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt ||
    177                                      bfmt == D3DFMT_A1R5G5B5)) ||
    178         (dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) {
    179         return TRUE;
    180     }
    181 
    182     return FALSE;
    183 }
    184 
    185 HRESULT NINE_WINAPI
    186 NineAdapter9_CheckDeviceType( struct NineAdapter9 *This,
    187                               D3DDEVTYPE DevType,
    188                               D3DFORMAT AdapterFormat,
    189                               D3DFORMAT BackBufferFormat,
    190                               BOOL bWindowed )
    191 {
    192     struct pipe_screen *screen;
    193     enum pipe_format dfmt, bfmt;
    194     HRESULT hr;
    195 
    196     DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s "
    197         "bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType),
    198         d3dformat_to_string(AdapterFormat),
    199         d3dformat_to_string(BackBufferFormat), bWindowed);
    200 
    201     user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed),
    202                 D3DERR_NOTAVAILABLE);
    203 
    204     hr = NineAdapter9_GetScreen(This, DevType, &screen);
    205     if (FAILED(hr)) { return hr; }
    206 
    207     /* The display format is not handled in Nine. We always present an XRGB8888
    208      * buffer (and the display server will eventually do the conversion). We probably
    209      * don't need to check for anything for the adapter format support, since if the
    210      * display server advertise support, it will likely be able to do the conversion.
    211      * We do the approximation that a format is available in the display server if
    212      * the format passes with NINE_BIND_BACKBUFFER_FLAGS */
    213     dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D,
    214                                        1,
    215                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    216     bfmt = d3d9_to_pipe_format_checked(screen, BackBufferFormat, PIPE_TEXTURE_2D,
    217                                        1,
    218                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    219     if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
    220         DBG("Unsupported Adapter/BackBufferFormat.\n");
    221         return D3DERR_NOTAVAILABLE;
    222     }
    223 
    224     return D3D_OK;
    225 }
    226 
    227 static inline boolean
    228 display_format( D3DFORMAT fmt,
    229                 boolean win )
    230 {
    231     /* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */
    232     static const D3DFORMAT allowed[] = {
    233         D3DFMT_A2R10G10B10,
    234         D3DFMT_X8R8G8B8,
    235         D3DFMT_X1R5G5B5,
    236         D3DFMT_R5G6B5,
    237     };
    238     unsigned i;
    239 
    240     if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }
    241 
    242     for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
    243         if (fmt == allowed[i]) { return TRUE; }
    244     }
    245     return FALSE;
    246 }
    247 
    248 HRESULT NINE_WINAPI
    249 NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
    250                                 D3DDEVTYPE DeviceType,
    251                                 D3DFORMAT AdapterFormat,
    252                                 DWORD Usage,
    253                                 D3DRESOURCETYPE RType,
    254                                 D3DFORMAT CheckFormat )
    255 {
    256     struct pipe_screen *screen;
    257     HRESULT hr;
    258     enum pipe_format pf;
    259     enum pipe_texture_target target;
    260     unsigned bind = 0;
    261     boolean srgb;
    262 
    263     /* Check adapter format. */
    264 
    265     DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,
    266         nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));
    267     DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType,
    268         d3dformat_to_string(CheckFormat));
    269 
    270     user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL);
    271 
    272     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    273     if (FAILED(hr))
    274         return hr;
    275     pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
    276                                      PIPE_BIND_DISPLAY_TARGET |
    277                                      PIPE_BIND_SHARED, FALSE, FALSE);
    278     if (pf == PIPE_FORMAT_NONE) {
    279         DBG("AdapterFormat %s not available.\n",
    280             d3dformat_to_string(AdapterFormat));
    281         return D3DERR_NOTAVAILABLE;
    282     }
    283 
    284     /* Check actual format. */
    285 
    286     switch (RType) {
    287     case D3DRTYPE_SURFACE:       target = PIPE_TEXTURE_2D; break;
    288     case D3DRTYPE_TEXTURE:       target = PIPE_TEXTURE_2D; break;
    289     case D3DRTYPE_CUBETEXTURE:   target = PIPE_TEXTURE_CUBE; break;
    290     case D3DRTYPE_VOLUME:        target = PIPE_TEXTURE_3D; break;
    291     case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;
    292     case D3DRTYPE_VERTEXBUFFER:  target = PIPE_BUFFER; break;
    293     case D3DRTYPE_INDEXBUFFER:   target = PIPE_BUFFER; break;
    294     default:
    295         user_assert(0, D3DERR_INVALIDCALL);
    296     }
    297 
    298     bind = 0;
    299     if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET;
    300     if (Usage & D3DUSAGE_DEPTHSTENCIL) {
    301         if (!depth_stencil_format(CheckFormat))
    302             return D3DERR_NOTAVAILABLE;
    303         bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat);
    304     }
    305 
    306     /* API hack because setting RT[0] to NULL is forbidden */
    307     if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&
    308         (RType == D3DRTYPE_SURFACE ||
    309          RType == D3DRTYPE_TEXTURE))
    310         return D3D_OK;
    311 
    312     /* RESZ hack */
    313     if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&
    314         RType == D3DRTYPE_SURFACE)
    315         return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?
    316                D3D_OK : D3DERR_NOTAVAILABLE;
    317 
    318     /* ATOC hack */
    319     if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE)
    320         return D3D_OK;
    321 
    322     if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) &&
    323         (Usage & D3DUSAGE_RENDERTARGET))
    324         bind |= PIPE_BIND_BLENDABLE;
    325 
    326     if (Usage & D3DUSAGE_DMAP) {
    327         DBG("D3DUSAGE_DMAP not available\n");
    328         return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */
    329     }
    330 
    331     switch (RType) {
    332     case D3DRTYPE_TEXTURE:       bind |= PIPE_BIND_SAMPLER_VIEW; break;
    333     case D3DRTYPE_CUBETEXTURE:   bind |= PIPE_BIND_SAMPLER_VIEW; break;
    334     case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
    335     case D3DRTYPE_VERTEXBUFFER:  bind |= PIPE_BIND_VERTEX_BUFFER; break;
    336     case D3DRTYPE_INDEXBUFFER:   bind |= PIPE_BIND_INDEX_BUFFER; break;
    337     case D3DRTYPE_SURFACE:
    338         if (!(Usage & D3DUSAGE_DEPTHSTENCIL))
    339             bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
    340         /* Offscreen surface support: Usage = 0.
    341          * In practice drivers are very restrictive on the formats supported.
    342          * Basically a few common formats + YUV and compressed formats. The
    343          * reason is that offscreen surface are useful only for directdraw
    344          * compatibility (a WONTIMPL of nine) + format conversion (useful in
    345          * particular for YUV because the format was not advertised for textures
    346          * on NV chips). */
    347         if (Usage == 0)
    348             bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */
    349     default:
    350         break;
    351     }
    352 
    353 
    354     srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;
    355     pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target,
    356                                      0, bind, srgb, FALSE);
    357     if (pf == PIPE_FORMAT_NONE) {
    358         DBG("NOT AVAILABLE\n");
    359         return D3DERR_NOTAVAILABLE;
    360     }
    361 
    362     /* we support ATI1 and ATI2 hack only for 2D and Cube textures */
    363     if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE &&
    364         (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2))
    365         return D3DERR_NOTAVAILABLE;
    366     /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */
    367     /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */
    368 
    369     if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))
    370         return D3DOK_NOAUTOGEN;
    371     return D3D_OK;
    372 }
    373 
    374 HRESULT NINE_WINAPI
    375 NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
    376                                          D3DDEVTYPE DeviceType,
    377                                          D3DFORMAT SurfaceFormat,
    378                                          BOOL Windowed,
    379                                          D3DMULTISAMPLE_TYPE MultiSampleType,
    380                                          DWORD *pQualityLevels )
    381 {
    382     struct pipe_screen *screen;
    383     HRESULT hr;
    384     enum pipe_format pf;
    385     unsigned bind;
    386 
    387     DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
    388         "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
    389         d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
    390         pQualityLevels);
    391 
    392     if (pQualityLevels) {
    393         /* In error cases return only 1 quality level supported */
    394         *pQualityLevels = 1;
    395     }
    396     user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL);
    397 
    398     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    399     if (FAILED(hr))
    400         return hr;
    401 
    402     if (depth_stencil_format(SurfaceFormat))
    403         bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);
    404     else /* render-target */
    405         bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
    406 
    407     pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
    408                                      0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE);
    409 
    410     if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
    411         DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat));
    412         return D3DERR_INVALIDCALL;
    413     }
    414 
    415     pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
    416                                      MultiSampleType, bind, FALSE, FALSE);
    417 
    418     if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
    419         DBG("%s with %u samples not available.\n",
    420             d3dformat_to_string(SurfaceFormat), MultiSampleType);
    421         return D3DERR_NOTAVAILABLE;
    422     }
    423 
    424     if (pQualityLevels) {
    425         /* NONMASKABLE MultiSampleType might have more than one quality level,
    426          * while MASKABLE MultiSampleTypes have only one level.
    427          * Advertise quality levels and map each level to a sample count. */
    428          (void ) d3dmultisample_type_check(screen, SurfaceFormat,
    429                  &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels);
    430          DBG("advertising %u quality levels\n", *pQualityLevels);
    431     }
    432 
    433     return D3D_OK;
    434 }
    435 
    436 HRESULT NINE_WINAPI
    437 NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
    438                                      D3DDEVTYPE DeviceType,
    439                                      D3DFORMAT AdapterFormat,
    440                                      D3DFORMAT RenderTargetFormat,
    441                                      D3DFORMAT DepthStencilFormat )
    442 {
    443     struct pipe_screen *screen;
    444     enum pipe_format dfmt, bfmt, zsfmt;
    445     HRESULT hr;
    446 
    447     DBG("This=%p DeviceType=%s AdapterFormat=%s "
    448         "RenderTargetFormat=%s DepthStencilFormat=%s\n", This,
    449         nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),
    450         d3dformat_to_string(RenderTargetFormat),
    451         d3dformat_to_string(DepthStencilFormat));
    452 
    453     user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);
    454     user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);
    455 
    456     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    457     if (FAILED(hr)) { return hr; }
    458 
    459     dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
    460                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    461     bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat,
    462                                        PIPE_TEXTURE_2D, 0,
    463                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    464     if (RenderTargetFormat == D3DFMT_NULL)
    465         bfmt = dfmt;
    466     zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat,
    467                                         PIPE_TEXTURE_2D, 0,
    468                                         d3d9_get_pipe_depth_format_bindings(DepthStencilFormat),
    469                                         FALSE, FALSE);
    470     if (dfmt == PIPE_FORMAT_NONE ||
    471         bfmt == PIPE_FORMAT_NONE ||
    472         zsfmt == PIPE_FORMAT_NONE) {
    473         return D3DERR_NOTAVAILABLE;
    474     }
    475 
    476     return D3D_OK;
    477 }
    478 
    479 HRESULT NINE_WINAPI
    480 NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,
    481                                           D3DDEVTYPE DeviceType,
    482                                           D3DFORMAT SourceFormat,
    483                                           D3DFORMAT TargetFormat )
    484 {
    485     /* MSDN says this tests whether a certain backbuffer format can be used in
    486      * conjunction with a certain front buffer format. It's a little confusing
    487      * but some one wiser might be able to figure this one out. XXX */
    488     struct pipe_screen *screen;
    489     enum pipe_format dfmt, bfmt;
    490     HRESULT hr;
    491 
    492     DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This,
    493         nine_D3DDEVTYPE_to_str(DeviceType),
    494         d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat));
    495 
    496     user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE),
    497                 D3DERR_NOTAVAILABLE);
    498 
    499     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    500     if (FAILED(hr)) { return hr; }
    501 
    502     dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1,
    503                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    504     bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1,
    505                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
    506 
    507     if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
    508         DBG("%s to %s not supported.\n",
    509             d3dformat_to_string(SourceFormat),
    510             d3dformat_to_string(TargetFormat));
    511         return D3DERR_NOTAVAILABLE;
    512     }
    513 
    514     return D3D_OK;
    515 }
    516 
    517 HRESULT NINE_WINAPI
    518 NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
    519                             D3DDEVTYPE DeviceType,
    520                             D3DCAPS9 *pCaps )
    521 {
    522     struct pipe_screen *screen;
    523     HRESULT hr;
    524 
    525     DBG("This=%p DeviceType=%s pCaps=%p\n", This,
    526         nine_D3DDEVTYPE_to_str(DeviceType), pCaps);
    527 
    528     user_assert(pCaps, D3DERR_INVALIDCALL);
    529 
    530     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
    531     if (FAILED(hr)) {
    532        DBG("Failed to get pipe_screen.\n");
    533        return hr;
    534     }
    535 
    536 #define D3DPIPECAP(pcap, d3dcap) \
    537     (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0)
    538 
    539 #define D3DNPIPECAP(pcap, d3dcap) \
    540     (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))
    541 
    542     pCaps->DeviceType = DeviceType;
    543 
    544     pCaps->AdapterOrdinal = 0;
    545 
    546     pCaps->Caps = 0;
    547 
    548     pCaps->Caps2 = D3DCAPS2_CANMANAGERESOURCE |
    549                 /* D3DCAPS2_CANSHARERESOURCE | */
    550                 /* D3DCAPS2_CANCALIBRATEGAMMA | */
    551                    D3DCAPS2_DYNAMICTEXTURES |
    552                    D3DCAPS2_FULLSCREENGAMMA |
    553                    D3DCAPS2_CANAUTOGENMIPMAP;
    554 
    555     /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the
    556      * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen
    557      * and in discard mode. */
    558     pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
    559                    D3DCAPS3_COPY_TO_VIDMEM |
    560                    D3DCAPS3_COPY_TO_SYSTEMMEM |
    561                    D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION;
    562 
    563     pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT |
    564                                    D3DPRESENT_INTERVAL_ONE |
    565                                    D3DPRESENT_INTERVAL_TWO |
    566                                    D3DPRESENT_INTERVAL_THREE |
    567                                    D3DPRESENT_INTERVAL_FOUR |
    568                                    D3DPRESENT_INTERVAL_IMMEDIATE;
    569     pCaps->CursorCaps = D3DCURSORCAPS_COLOR | D3DCURSORCAPS_LOWRES;
    570 
    571     pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL |
    572                      D3DDEVCAPS_CANRENDERAFTERFLIP |
    573                      D3DDEVCAPS_DRAWPRIMITIVES2 |
    574                      D3DDEVCAPS_DRAWPRIMITIVES2EX |
    575                      D3DDEVCAPS_DRAWPRIMTLVERTEX |
    576                      D3DDEVCAPS_EXECUTESYSTEMMEMORY |
    577                      D3DDEVCAPS_EXECUTEVIDEOMEMORY |
    578                      D3DDEVCAPS_HWRASTERIZATION |
    579                      D3DDEVCAPS_HWTRANSFORMANDLIGHT |
    580                      /*D3DDEVCAPS_NPATCHES |*/
    581                      D3DDEVCAPS_PUREDEVICE |
    582                      /*D3DDEVCAPS_QUINTICRTPATCHES |*/
    583                      /*D3DDEVCAPS_RTPATCHES |*/
    584                      /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/
    585                      /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/
    586                      D3DDEVCAPS_TEXTURENONLOCALVIDMEM |
    587                      /* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/
    588                      D3DDEVCAPS_TEXTUREVIDEOMEMORY |
    589                      D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
    590                      D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
    591 
    592     pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ |
    593                                D3DPMISCCAPS_CULLNONE | /* XXX */
    594                                D3DPMISCCAPS_CULLCW |
    595                                D3DPMISCCAPS_CULLCCW |
    596                                D3DPMISCCAPS_COLORWRITEENABLE |
    597                                D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
    598                                /*D3DPMISCCAPS_CLIPTLVERTS |*/
    599                                D3DPMISCCAPS_TSSARGTEMP |
    600                                D3DPMISCCAPS_BLENDOP |
    601                                D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |
    602                                D3DPMISCCAPS_PERSTAGECONSTANT |
    603                                /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */
    604                                D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */
    605                                D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |
    606                                D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |
    607                                D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |
    608                                D3DPMISCCAPS_FOGVERTEXCLAMPED;
    609     if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION))
    610         pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS;
    611 
    612     pCaps->RasterCaps =
    613         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |
    614         D3DPRASTERCAPS_COLORPERSPECTIVE |
    615         D3DPRASTERCAPS_DITHER |
    616         D3DPRASTERCAPS_DEPTHBIAS |
    617         D3DPRASTERCAPS_FOGRANGE |
    618         D3DPRASTERCAPS_FOGTABLE |
    619         D3DPRASTERCAPS_FOGVERTEX |
    620         D3DPRASTERCAPS_MIPMAPLODBIAS |
    621         D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |
    622         D3DPRASTERCAPS_SCISSORTEST |
    623         D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
    624         /*D3DPRASTERCAPS_WBUFFER |*/
    625         D3DPRASTERCAPS_WFOG |
    626         /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/
    627         D3DPRASTERCAPS_ZFOG |
    628         D3DPRASTERCAPS_ZTEST;
    629 
    630     pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |
    631                       D3DPCMPCAPS_LESS |
    632                       D3DPCMPCAPS_EQUAL |
    633                       D3DPCMPCAPS_LESSEQUAL |
    634                       D3DPCMPCAPS_GREATER |
    635                       D3DPCMPCAPS_NOTEQUAL |
    636                       D3DPCMPCAPS_GREATEREQUAL |
    637                       D3DPCMPCAPS_ALWAYS;
    638 
    639     pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO |
    640                           D3DPBLENDCAPS_ONE |
    641                           D3DPBLENDCAPS_SRCCOLOR |
    642                           D3DPBLENDCAPS_INVSRCCOLOR |
    643                           D3DPBLENDCAPS_SRCALPHA |
    644                           D3DPBLENDCAPS_INVSRCALPHA |
    645                           D3DPBLENDCAPS_DESTALPHA |
    646                           D3DPBLENDCAPS_INVDESTALPHA |
    647                           D3DPBLENDCAPS_DESTCOLOR |
    648                           D3DPBLENDCAPS_INVDESTCOLOR |
    649                           D3DPBLENDCAPS_SRCALPHASAT |
    650                           D3DPBLENDCAPS_BOTHSRCALPHA |
    651                           D3DPBLENDCAPS_BOTHINVSRCALPHA |
    652                           D3DPBLENDCAPS_BLENDFACTOR |
    653                           D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS,
    654                               D3DPBLENDCAPS_INVSRCCOLOR2 |
    655                               D3DPBLENDCAPS_SRCCOLOR2);
    656 
    657     pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
    658 
    659     pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER |
    660                           D3DPCMPCAPS_LESS |
    661                           D3DPCMPCAPS_EQUAL |
    662                           D3DPCMPCAPS_LESSEQUAL |
    663                           D3DPCMPCAPS_GREATER |
    664                           D3DPCMPCAPS_NOTEQUAL |
    665                           D3DPCMPCAPS_GREATEREQUAL |
    666                           D3DPCMPCAPS_ALWAYS;
    667 
    668     /* FLAT caps not legal for D3D9. */
    669     pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB |
    670                        D3DPSHADECAPS_SPECULARGOURAUDRGB |
    671                        D3DPSHADECAPS_ALPHAGOURAUDBLEND |
    672                        D3DPSHADECAPS_FOGGOURAUD;
    673 
    674     pCaps->TextureCaps =
    675         D3DPTEXTURECAPS_ALPHA |
    676         D3DPTEXTURECAPS_ALPHAPALETTE |
    677         D3DPTEXTURECAPS_PERSPECTIVE |
    678         D3DPTEXTURECAPS_PROJECTED |
    679         /*D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE |*/
    680         D3DPTEXTURECAPS_CUBEMAP |
    681         D3DPTEXTURECAPS_VOLUMEMAP |
    682         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) |
    683         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) |
    684         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) |
    685         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) |
    686         D3DPIPECAP(MAX_TEXTURE_2D_LEVELS, D3DPTEXTURECAPS_MIPMAP) |
    687         D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) |
    688         D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP);
    689 
    690     pCaps->TextureFilterCaps =
    691         D3DPTFILTERCAPS_MINFPOINT |
    692         D3DPTFILTERCAPS_MINFLINEAR |
    693         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) |
    694         /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/
    695         /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/
    696         D3DPTFILTERCAPS_MIPFPOINT |
    697         D3DPTFILTERCAPS_MIPFLINEAR |
    698         D3DPTFILTERCAPS_MAGFPOINT |
    699         D3DPTFILTERCAPS_MAGFLINEAR |
    700         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) |
    701         /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/
    702         /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0;
    703 
    704     pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;
    705     pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;
    706 
    707     pCaps->TextureAddressCaps =
    708         D3DPTADDRESSCAPS_BORDER |
    709         D3DPTADDRESSCAPS_INDEPENDENTUV |
    710         D3DPTADDRESSCAPS_WRAP |
    711         D3DPTADDRESSCAPS_MIRROR |
    712         D3DPTADDRESSCAPS_CLAMP |
    713         D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE);
    714 
    715     pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;
    716 
    717     pCaps->LineCaps =
    718         D3DLINECAPS_ALPHACMP |
    719         D3DLINECAPS_BLEND |
    720         D3DLINECAPS_TEXTURE |
    721         D3DLINECAPS_ZTEST |
    722         D3DLINECAPS_FOG;
    723     if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) {
    724         pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS;
    725     }
    726 
    727     pCaps->MaxTextureWidth =
    728         1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
    729     pCaps->MaxTextureHeight = pCaps->MaxTextureWidth;
    730     pCaps->MaxVolumeExtent =
    731         1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1);
    732     /* XXX values from wine */
    733     pCaps->MaxTextureRepeat = 32768;
    734     pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth;
    735 
    736     pCaps->MaxAnisotropy =
    737         (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);
    738 
    739     /* Values for GeForce 9600 GT */
    740     pCaps->MaxVertexW = 1e10f;
    741     pCaps->GuardBandLeft = -1e9f;
    742     pCaps->GuardBandTop = -1e9f;
    743     pCaps->GuardBandRight = 1e9f;
    744     pCaps->GuardBandBottom = 1e9f;
    745     pCaps->ExtentsAdjust = 0.0f;
    746 
    747     pCaps->StencilCaps =
    748         D3DSTENCILCAPS_KEEP |
    749         D3DSTENCILCAPS_ZERO |
    750         D3DSTENCILCAPS_REPLACE |
    751         D3DSTENCILCAPS_INCRSAT |
    752         D3DSTENCILCAPS_DECRSAT |
    753         D3DSTENCILCAPS_INVERT |
    754         D3DSTENCILCAPS_INCR |
    755         D3DSTENCILCAPS_DECR |
    756         D3DPIPECAP(TWO_SIDED_STENCIL, D3DSTENCILCAPS_TWOSIDED);
    757 
    758     pCaps->FVFCaps =
    759         8 | /* 8 textures max */
    760         /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/
    761         D3DFVFCAPS_PSIZE;
    762 
    763     pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |
    764                            D3DTEXOPCAPS_SELECTARG1 |
    765                            D3DTEXOPCAPS_SELECTARG2 |
    766                            D3DTEXOPCAPS_MODULATE |
    767                            D3DTEXOPCAPS_MODULATE2X |
    768                            D3DTEXOPCAPS_MODULATE4X |
    769                            D3DTEXOPCAPS_ADD |
    770                            D3DTEXOPCAPS_ADDSIGNED |
    771                            D3DTEXOPCAPS_ADDSIGNED2X |
    772                            D3DTEXOPCAPS_SUBTRACT |
    773                            D3DTEXOPCAPS_ADDSMOOTH |
    774                            D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
    775                            D3DTEXOPCAPS_BLENDTEXTUREALPHA |
    776                            D3DTEXOPCAPS_BLENDFACTORALPHA |
    777                            D3DTEXOPCAPS_BLENDTEXTUREALPHAPM |
    778                            D3DTEXOPCAPS_BLENDCURRENTALPHA |
    779                            D3DTEXOPCAPS_PREMODULATE |
    780                            D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
    781                            D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
    782                            D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
    783                            D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |
    784                            D3DTEXOPCAPS_BUMPENVMAP |
    785                            D3DTEXOPCAPS_BUMPENVMAPLUMINANCE |
    786                            D3DTEXOPCAPS_DOTPRODUCT3 |
    787                            D3DTEXOPCAPS_MULTIPLYADD |
    788                            D3DTEXOPCAPS_LERP;
    789 
    790     pCaps->MaxTextureBlendStages = 8; /* XXX wine */
    791         (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE);
    792     pCaps->MaxSimultaneousTextures = screen->get_shader_param(screen,
    793         PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS);
    794     if (pCaps->MaxSimultaneousTextures > NINE_MAX_SAMPLERS_PS)
    795         pCaps->MaxSimultaneousTextures = NINE_MAX_SAMPLERS_PS;
    796 
    797     pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN |
    798                                   D3DVTXPCAPS_TEXGEN_SPHEREMAP |
    799                                   D3DVTXPCAPS_MATERIALSOURCE7 |
    800                                   D3DVTXPCAPS_DIRECTIONALLIGHTS |
    801                                   D3DVTXPCAPS_POSITIONALLIGHTS |
    802                                   D3DVTXPCAPS_LOCALVIEWER |
    803                                   D3DVTXPCAPS_TWEENING |
    804                                   /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0;
    805 
    806     pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */
    807     pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES;
    808     pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */
    809     pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */
    810 
    811     pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH);
    812 
    813     pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */
    814     pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */
    815     pCaps->MaxStreams =
    816         _min(screen->get_shader_param(screen,
    817                  PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS),
    818              16);
    819 
    820     pCaps->MaxStreamStride = screen->get_param(screen,
    821             PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);
    822 
    823     pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
    824 
    825     /* VS 2 as well as 3.0 supports a minimum of 256 consts.
    826      * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them,
    827      * advertise 256. Problem is with hw that can only do 256, because
    828      * we need take a few slots for boolean and integer constants. For these
    829      * we'll have to fail later if they use complex shaders. */
    830     pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;
    831 
    832     pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
    833     /* Value for GeForce 9600 GT */
    834     pCaps->PixelShader1xMaxValue = 65504.f;
    835 
    836     pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
    837                       D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |
    838                       D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES |
    839                       /*D3DDEVCAPS2_DMAPNPATCH |*/
    840                       /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/
    841                       /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/
    842                       /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0;
    843 
    844     pCaps->MasterAdapterOrdinal = 0;
    845     pCaps->AdapterOrdinalInGroup = 0;
    846     pCaps->NumberOfAdaptersInGroup = 1;
    847 
    848     /* Undocumented ? */
    849     pCaps->MaxNpatchTessellationLevel = 0.0f;
    850     pCaps->Reserved5 = 0;
    851 
    852     /* XXX: use is_format_supported */
    853     pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
    854                        D3DDTCAPS_UBYTE4N |
    855                        D3DDTCAPS_SHORT2N |
    856                        D3DDTCAPS_SHORT4N |
    857                        D3DDTCAPS_USHORT2N |
    858                        D3DDTCAPS_USHORT4N |
    859                        D3DDTCAPS_UDEC3 |
    860                        D3DDTCAPS_DEC3N |
    861                        D3DDTCAPS_FLOAT16_2 |
    862                        D3DDTCAPS_FLOAT16_4;
    863 
    864     pCaps->NumSimultaneousRTs =
    865         screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS);
    866     if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS)
    867         pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS;
    868 
    869     pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT |
    870                                    D3DPTFILTERCAPS_MINFLINEAR |
    871                                    D3DPTFILTERCAPS_MAGFPOINT |
    872                                    D3DPTFILTERCAPS_MAGFLINEAR;
    873 
    874 
    875     pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
    876     pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
    877         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
    878                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
    879     pCaps->VS20Caps.NumTemps =
    880         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
    881                                  PIPE_SHADER_CAP_MAX_TEMPS);
    882     pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */
    883         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
    884                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
    885 
    886     /* also check for values < 0, because get_shader_param may return unsigned */
    887     if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
    888         || pCaps->VS20Caps.DynamicFlowControlDepth < 0)
    889         pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
    890     if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH
    891         || pCaps->VS20Caps.StaticFlowControlDepth < 0)
    892         pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH;
    893     if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS)
    894         pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
    895     assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH);
    896     assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH);
    897     assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS);
    898 
    899 
    900     pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
    901                            D3DPS20CAPS_GRADIENTINSTRUCTIONS |
    902                            D3DPS20CAPS_PREDICATION;
    903     if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    904                                  PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
    905         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    906                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
    907         pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
    908     if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    909                                  PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
    910         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    911                                  PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS))
    912         pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT;
    913     pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
    914         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    915                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
    916     pCaps->PS20Caps.NumTemps =
    917         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    918                                  PIPE_SHADER_CAP_MAX_TEMPS);
    919     pCaps->PS20Caps.StaticFlowControlDepth =  /* XXX is this static ? */
    920         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    921                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
    922     pCaps->PS20Caps.NumInstructionSlots =
    923         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    924                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
    925 
    926     if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
    927         || pCaps->PS20Caps.DynamicFlowControlDepth < 0)
    928         pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
    929     if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH
    930         || pCaps->PS20Caps.StaticFlowControlDepth < 0)
    931         pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH;
    932     if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS)
    933         pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS;
    934     if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS)
    935         pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS;
    936     assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH);
    937     assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH);
    938     assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS);
    939     assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS);
    940 
    941 
    942     if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
    943                                  PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
    944         pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps &
    945             ~(D3DPTFILTERCAPS_MIPFPOINT |
    946               D3DPTFILTERCAPS_MIPFPOINT); /* XXX */
    947     else
    948         pCaps->VertexTextureFilterCaps = 0;
    949 
    950     pCaps->MaxVertexShader30InstructionSlots =
    951         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
    952                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
    953     pCaps->MaxPixelShader30InstructionSlots =
    954         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
    955                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
    956     if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
    957         pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
    958     if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
    959         pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
    960     assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
    961     assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
    962 
    963     /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */
    964     pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);
    965     pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32);
    966 
    967     if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE))
    968         nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps);
    969 
    970     return D3D_OK;
    971 }
    972 
    973 HRESULT NINE_WINAPI
    974 NineAdapter9_CreateDevice( struct NineAdapter9 *This,
    975                            UINT RealAdapter,
    976                            D3DDEVTYPE DeviceType,
    977                            HWND hFocusWindow,
    978                            DWORD BehaviorFlags,
    979                            D3DPRESENT_PARAMETERS *pPresentationParameters,
    980                            IDirect3D9 *pD3D9,
    981                            ID3DPresentGroup *pPresentationGroup,
    982                            IDirect3DDevice9 **ppReturnedDeviceInterface )
    983 {
    984     struct pipe_screen *screen;
    985     D3DDEVICE_CREATION_PARAMETERS params;
    986     D3DCAPS9 caps;
    987     int major, minor;
    988     HRESULT hr;
    989 
    990     DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
    991         "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p "
    992         "ppReturnedDeviceInterface=%p\n", This,
    993         RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
    994         BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface);
    995 
    996     ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
    997     if (major != 1) {
    998         ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
    999             major, minor);
   1000         return D3DERR_NOTAVAILABLE;
   1001     }
   1002 
   1003     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
   1004     if (FAILED(hr)) {
   1005         DBG("Failed to get pipe_screen.\n");
   1006         return hr;
   1007     }
   1008 
   1009     hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
   1010     if (FAILED(hr)) {
   1011         DBG("Failed to get device caps.\n");
   1012         return hr;
   1013     }
   1014 
   1015     params.AdapterOrdinal = RealAdapter;
   1016     params.DeviceType = DeviceType;
   1017     params.hFocusWindow = hFocusWindow;
   1018     params.BehaviorFlags = BehaviorFlags;
   1019 
   1020     hr = NineDevice9_new(screen, &params, &caps, pPresentationParameters,
   1021                          pD3D9, pPresentationGroup, This->ctx, FALSE, NULL,
   1022                          (struct NineDevice9 **)ppReturnedDeviceInterface,
   1023                          minor);
   1024     if (FAILED(hr)) {
   1025         DBG("Failed to create device.\n");
   1026         return hr;
   1027     }
   1028     DBG("NineDevice9 created successfully.\n");
   1029 
   1030     return D3D_OK;
   1031 }
   1032 
   1033 HRESULT NINE_WINAPI
   1034 NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,
   1035                              UINT RealAdapter,
   1036                              D3DDEVTYPE DeviceType,
   1037                              HWND hFocusWindow,
   1038                              DWORD BehaviorFlags,
   1039                              D3DPRESENT_PARAMETERS *pPresentationParameters,
   1040                              D3DDISPLAYMODEEX *pFullscreenDisplayMode,
   1041                              IDirect3D9Ex *pD3D9Ex,
   1042                              ID3DPresentGroup *pPresentationGroup,
   1043                              IDirect3DDevice9Ex **ppReturnedDeviceInterface )
   1044 {
   1045     struct pipe_screen *screen;
   1046     D3DDEVICE_CREATION_PARAMETERS params;
   1047     D3DCAPS9 caps;
   1048     int major, minor;
   1049     HRESULT hr;
   1050 
   1051     DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
   1052         "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p "
   1053         "ppReturnedDeviceInterface=%p\n", This,
   1054         RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
   1055         BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface);
   1056 
   1057     ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
   1058     if (major != 1) {
   1059         ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
   1060             major, minor);
   1061         return D3DERR_NOTAVAILABLE;
   1062     }
   1063 
   1064     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
   1065     if (FAILED(hr)) {
   1066         DBG("Failed to get pipe_screen.\n");
   1067         return hr;
   1068     }
   1069 
   1070     hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
   1071     if (FAILED(hr)) {
   1072         DBG("Failed to get device caps.\n");
   1073         return hr;
   1074     }
   1075 
   1076     params.AdapterOrdinal = RealAdapter;
   1077     params.DeviceType = DeviceType;
   1078     params.hFocusWindow = hFocusWindow;
   1079     params.BehaviorFlags = BehaviorFlags;
   1080 
   1081     hr = NineDevice9Ex_new(screen, &params, &caps, pPresentationParameters,
   1082                            pFullscreenDisplayMode,
   1083                            pD3D9Ex, pPresentationGroup, This->ctx,
   1084                            (struct NineDevice9Ex **)ppReturnedDeviceInterface,
   1085                            minor);
   1086     if (FAILED(hr)) {
   1087         DBG("Failed to create device.\n");
   1088         return hr;
   1089     }
   1090     DBG("NineDevice9Ex created successfully.\n");
   1091 
   1092     return D3D_OK;
   1093 }
   1094 
   1095 ID3DAdapter9Vtbl NineAdapter9_vtable = {
   1096     (void *)NineUnknown_QueryInterface,
   1097     (void *)NineUnknown_AddRef,
   1098     (void *)NineUnknown_Release,
   1099     (void *)NineAdapter9_GetAdapterIdentifier,
   1100     (void *)NineAdapter9_CheckDeviceType,
   1101     (void *)NineAdapter9_CheckDeviceFormat,
   1102     (void *)NineAdapter9_CheckDeviceMultiSampleType,
   1103     (void *)NineAdapter9_CheckDepthStencilMatch,
   1104     (void *)NineAdapter9_CheckDeviceFormatConversion,
   1105     (void *)NineAdapter9_GetDeviceCaps,
   1106     (void *)NineAdapter9_CreateDevice,
   1107     (void *)NineAdapter9_CreateDeviceEx
   1108 };
   1109 
   1110 static const GUID *NineAdapter9_IIDs[] = {
   1111     &IID_ID3D9Adapter,
   1112     &IID_IUnknown,
   1113     NULL
   1114 };
   1115 
   1116 HRESULT
   1117 NineAdapter9_new( struct d3dadapter9_context *pCTX,
   1118                   struct NineAdapter9 **ppOut )
   1119 {
   1120     NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX);
   1121 }
   1122