"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/state_trackers/nine/adapter9.c" (16 Sep 2020, 47668 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "adapter9.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

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