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