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
has_sm3(struct pipe_screen * hal)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
NineAdapter9_ctor(struct NineAdapter9 * This,struct NineUnknownParams * pParams,struct d3dadapter9_context * pCTX)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
NineAdapter9_dtor(struct NineAdapter9 * This)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
NineAdapter9_GetScreen(struct NineAdapter9 * This,D3DDEVTYPE DevType,struct pipe_screen ** ppScreen)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
NineAdapter9_GetAdapterIdentifier(struct NineAdapter9 * This,DWORD Flags,D3DADAPTER_IDENTIFIER9 * pIdentifier)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
backbuffer_format(D3DFORMAT dfmt,D3DFORMAT bfmt,boolean win)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
NineAdapter9_CheckDeviceType(struct NineAdapter9 * This,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed)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
display_format(D3DFORMAT fmt,boolean win)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 static inline boolean
adapter_format(D3DFORMAT fmt)259 adapter_format( D3DFORMAT fmt )
260 {
261     /* Formats that are compatible to display_format (modulo alpha bits) */
262     static const D3DFORMAT allowed[] = {
263         D3DFMT_A2R10G10B10,
264         D3DFMT_X8R8G8B8,
265         D3DFMT_A8R8G8B8,
266         D3DFMT_X1R5G5B5,
267         D3DFMT_A1R5G5B5,
268         D3DFMT_R5G6B5,
269     };
270     unsigned i;
271 
272     for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {
273         if (fmt == allowed[i]) { return TRUE; }
274     }
275     return FALSE;
276 }
277 
278 HRESULT NINE_WINAPI
NineAdapter9_CheckDeviceFormat(struct NineAdapter9 * This,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat)279 NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,
280                                 D3DDEVTYPE DeviceType,
281                                 D3DFORMAT AdapterFormat,
282                                 DWORD Usage,
283                                 D3DRESOURCETYPE RType,
284                                 D3DFORMAT CheckFormat )
285 {
286     struct pipe_screen *screen;
287     HRESULT hr;
288     enum pipe_format pf;
289     enum pipe_texture_target target;
290     unsigned bind = 0;
291     boolean srgb;
292 
293     /* Check adapter format. */
294 
295     DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,
296         nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));
297     DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType,
298         d3dformat_to_string(CheckFormat));
299 
300     /* Wine tests, but suspicious. Needs more tests. */
301     user_assert(adapter_format(AdapterFormat), D3DERR_INVALIDCALL);
302     user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);
303 
304     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
305     if (FAILED(hr))
306         return hr;
307     pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
308                                      PIPE_BIND_DISPLAY_TARGET |
309                                      PIPE_BIND_SHARED, FALSE, FALSE);
310     if (pf == PIPE_FORMAT_NONE) {
311         DBG("AdapterFormat %s not available.\n",
312             d3dformat_to_string(AdapterFormat));
313         return D3DERR_NOTAVAILABLE;
314     }
315 
316     /* Check actual format. */
317 
318     switch (RType) {
319     case D3DRTYPE_SURFACE:       target = PIPE_TEXTURE_2D; break;
320     case D3DRTYPE_TEXTURE:       target = PIPE_TEXTURE_2D; break;
321     case D3DRTYPE_CUBETEXTURE:   target = PIPE_TEXTURE_CUBE; break;
322     case D3DRTYPE_VOLUME:        target = PIPE_TEXTURE_3D; break;
323     case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;
324     case D3DRTYPE_VERTEXBUFFER:  target = PIPE_BUFFER; break;
325     case D3DRTYPE_INDEXBUFFER:   target = PIPE_BUFFER; break;
326     default:
327         user_assert(0, D3DERR_INVALIDCALL);
328     }
329 
330     bind = 0;
331     if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET;
332     if (Usage & D3DUSAGE_DEPTHSTENCIL) {
333         if (!depth_stencil_format(CheckFormat))
334             return D3DERR_NOTAVAILABLE;
335         bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat);
336     }
337 
338     /* API hack because setting RT[0] to NULL is forbidden */
339     if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&
340         (RType == D3DRTYPE_SURFACE ||
341          RType == D3DRTYPE_TEXTURE))
342         return D3D_OK;
343 
344     /* RESZ hack */
345     if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&
346         RType == D3DRTYPE_SURFACE)
347         return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?
348                D3D_OK : D3DERR_NOTAVAILABLE;
349 
350     /* ATOC hack */
351     if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE)
352         return D3D_OK;
353 
354     if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) &&
355         (Usage & D3DUSAGE_RENDERTARGET))
356         bind |= PIPE_BIND_BLENDABLE;
357 
358     if (Usage & D3DUSAGE_DMAP) {
359         DBG("D3DUSAGE_DMAP not available\n");
360         return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */
361     }
362 
363     switch (RType) {
364     case D3DRTYPE_TEXTURE:       bind |= PIPE_BIND_SAMPLER_VIEW; break;
365     case D3DRTYPE_CUBETEXTURE:   bind |= PIPE_BIND_SAMPLER_VIEW; break;
366     case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;
367     case D3DRTYPE_VERTEXBUFFER:  bind |= PIPE_BIND_VERTEX_BUFFER; break;
368     case D3DRTYPE_INDEXBUFFER:   bind |= PIPE_BIND_INDEX_BUFFER; break;
369     case D3DRTYPE_SURFACE:
370         if (!(Usage & D3DUSAGE_DEPTHSTENCIL))
371             bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */
372         /* Offscreen surface support: Usage = 0.
373          * In practice drivers are very restrictive on the formats supported.
374          * Basically a few common formats + YUV and compressed formats. The
375          * reason is that offscreen surface are useful only for directdraw
376          * compatibility (a WONTIMPL of nine) + format conversion (useful in
377          * particular for YUV because the format was not advertised for textures
378          * on NV chips). */
379         if (Usage == 0)
380             bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */
381     default:
382         break;
383     }
384 
385 
386     srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;
387     pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target,
388                                      0, bind, srgb, FALSE);
389     if (pf == PIPE_FORMAT_NONE) {
390         DBG("NOT AVAILABLE\n");
391         return D3DERR_NOTAVAILABLE;
392     }
393 
394     /* we support ATI1 and ATI2 hack only for 2D and Cube textures */
395     if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE &&
396         (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2))
397         return D3DERR_NOTAVAILABLE;
398     /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */
399     /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */
400 
401     if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))
402         return D3DOK_NOAUTOGEN;
403     return D3D_OK;
404 }
405 
406 HRESULT NINE_WINAPI
NineAdapter9_CheckDeviceMultiSampleType(struct NineAdapter9 * This,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD * pQualityLevels)407 NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,
408                                          D3DDEVTYPE DeviceType,
409                                          D3DFORMAT SurfaceFormat,
410                                          BOOL Windowed,
411                                          D3DMULTISAMPLE_TYPE MultiSampleType,
412                                          DWORD *pQualityLevels )
413 {
414     struct pipe_screen *screen;
415     HRESULT hr;
416     enum pipe_format pf;
417     unsigned bind;
418 
419     DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "
420         "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),
421         d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,
422         pQualityLevels);
423 
424     if (pQualityLevels) {
425         /* In error cases return only 1 quality level supported */
426         *pQualityLevels = 1;
427     }
428     user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL);
429 
430     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
431     if (FAILED(hr))
432         return hr;
433 
434     if (depth_stencil_format(SurfaceFormat))
435         bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);
436     else /* render-target */
437         bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
438 
439     pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
440                                      0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE);
441 
442     if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
443         DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat));
444         return D3DERR_INVALIDCALL;
445     }
446 
447     pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,
448                                      MultiSampleType, bind, FALSE, FALSE);
449 
450     if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {
451         DBG("%s with %u samples not available.\n",
452             d3dformat_to_string(SurfaceFormat), MultiSampleType);
453         return D3DERR_NOTAVAILABLE;
454     }
455 
456     if (pQualityLevels) {
457         /* NONMASKABLE MultiSampleType might have more than one quality level,
458          * while MASKABLE MultiSampleTypes have only one level.
459          * Advertise quality levels and map each level to a sample count. */
460          (void ) d3dmultisample_type_check(screen, SurfaceFormat,
461                  &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels);
462          DBG("advertising %u quality levels\n", *pQualityLevels);
463     }
464 
465     return D3D_OK;
466 }
467 
468 HRESULT NINE_WINAPI
NineAdapter9_CheckDepthStencilMatch(struct NineAdapter9 * This,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat)469 NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,
470                                      D3DDEVTYPE DeviceType,
471                                      D3DFORMAT AdapterFormat,
472                                      D3DFORMAT RenderTargetFormat,
473                                      D3DFORMAT DepthStencilFormat )
474 {
475     struct pipe_screen *screen;
476     enum pipe_format dfmt, bfmt, zsfmt;
477     HRESULT hr;
478 
479     DBG("This=%p DeviceType=%s AdapterFormat=%s "
480         "RenderTargetFormat=%s DepthStencilFormat=%s\n", This,
481         nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),
482         d3dformat_to_string(RenderTargetFormat),
483         d3dformat_to_string(DepthStencilFormat));
484 
485     /* TODO: does it check AdapterFormat at all ?
486      * It seems to need to pass at least for A8R8G8B8:
487      * https://github.com/iXit/Mesa-3D/issues/317 */
488     user_assert(adapter_format(AdapterFormat), D3DERR_NOTAVAILABLE);
489     user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);
490 
491     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
492     if (FAILED(hr)) { return hr; }
493 
494     dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,
495                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
496     bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat,
497                                        PIPE_TEXTURE_2D, 0,
498                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
499     if (RenderTargetFormat == D3DFMT_NULL)
500         bfmt = dfmt;
501     zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat,
502                                         PIPE_TEXTURE_2D, 0,
503                                         d3d9_get_pipe_depth_format_bindings(DepthStencilFormat),
504                                         FALSE, FALSE);
505     if (dfmt == PIPE_FORMAT_NONE ||
506         bfmt == PIPE_FORMAT_NONE ||
507         zsfmt == PIPE_FORMAT_NONE) {
508         return D3DERR_NOTAVAILABLE;
509     }
510 
511     return D3D_OK;
512 }
513 
514 HRESULT NINE_WINAPI
NineAdapter9_CheckDeviceFormatConversion(struct NineAdapter9 * This,D3DDEVTYPE DeviceType,D3DFORMAT SourceFormat,D3DFORMAT TargetFormat)515 NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,
516                                           D3DDEVTYPE DeviceType,
517                                           D3DFORMAT SourceFormat,
518                                           D3DFORMAT TargetFormat )
519 {
520     /* MSDN says this tests whether a certain backbuffer format can be used in
521      * conjunction with a certain front buffer format. It's a little confusing
522      * but some one wiser might be able to figure this one out. XXX */
523     struct pipe_screen *screen;
524     enum pipe_format dfmt, bfmt;
525     HRESULT hr;
526 
527     DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This,
528         nine_D3DDEVTYPE_to_str(DeviceType),
529         d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat));
530 
531     user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE),
532                 D3DERR_NOTAVAILABLE);
533 
534     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
535     if (FAILED(hr)) { return hr; }
536 
537     dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1,
538                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
539     bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1,
540                                        NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);
541 
542     if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {
543         DBG("%s to %s not supported.\n",
544             d3dformat_to_string(SourceFormat),
545             d3dformat_to_string(TargetFormat));
546         return D3DERR_NOTAVAILABLE;
547     }
548 
549     return D3D_OK;
550 }
551 
552 HRESULT NINE_WINAPI
NineAdapter9_GetDeviceCaps(struct NineAdapter9 * This,D3DDEVTYPE DeviceType,D3DCAPS9 * pCaps)553 NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,
554                             D3DDEVTYPE DeviceType,
555                             D3DCAPS9 *pCaps )
556 {
557     struct pipe_screen *screen;
558     HRESULT hr;
559 
560     DBG("This=%p DeviceType=%s pCaps=%p\n", This,
561         nine_D3DDEVTYPE_to_str(DeviceType), pCaps);
562 
563     user_assert(pCaps, D3DERR_INVALIDCALL);
564 
565     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
566     if (FAILED(hr)) {
567        DBG("Failed to get pipe_screen.\n");
568        return hr;
569     }
570 
571 #define D3DPIPECAP(pcap, d3dcap) \
572     (screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0)
573 
574 #define D3DNPIPECAP(pcap, d3dcap) \
575     (screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))
576 
577     pCaps->DeviceType = DeviceType;
578 
579     pCaps->AdapterOrdinal = 0;
580 
581     pCaps->Caps = D3DCAPS_READ_SCANLINE;
582 
583     pCaps->Caps2 = /* D3DCAPS2_CANMANAGERESOURCE | */
584                 /* D3DCAPS2_CANSHARERESOURCE | */
585                 /* D3DCAPS2_CANCALIBRATEGAMMA | */
586                    D3DCAPS2_DYNAMICTEXTURES |
587                    D3DCAPS2_FULLSCREENGAMMA |
588                    D3DCAPS2_CANAUTOGENMIPMAP;
589 
590     /* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the
591      * backbuffer can be ARGB (instead of only XRGB) when we are fullscreen
592      * and in discard mode. */
593     pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
594                    D3DCAPS3_COPY_TO_VIDMEM |
595                    D3DCAPS3_COPY_TO_SYSTEMMEM |
596                    D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION;
597 
598     pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT |
599                                    D3DPRESENT_INTERVAL_ONE |
600                                    D3DPRESENT_INTERVAL_TWO |
601                                    D3DPRESENT_INTERVAL_THREE |
602                                    D3DPRESENT_INTERVAL_FOUR |
603                                    D3DPRESENT_INTERVAL_IMMEDIATE;
604     pCaps->CursorCaps = D3DCURSORCAPS_COLOR /* | D3DCURSORCAPS_LOWRES*/;
605 
606     pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL |
607                      D3DDEVCAPS_CANRENDERAFTERFLIP |
608                      D3DDEVCAPS_DRAWPRIMITIVES2 |
609                      D3DDEVCAPS_DRAWPRIMITIVES2EX |
610                      D3DDEVCAPS_DRAWPRIMTLVERTEX |
611                      D3DDEVCAPS_EXECUTESYSTEMMEMORY |
612                      D3DDEVCAPS_EXECUTEVIDEOMEMORY |
613                      D3DDEVCAPS_HWRASTERIZATION |
614                      D3DDEVCAPS_HWTRANSFORMANDLIGHT |
615                      /*D3DDEVCAPS_NPATCHES |*/
616                      D3DDEVCAPS_PUREDEVICE |
617                      /*D3DDEVCAPS_QUINTICRTPATCHES |*/
618                      /*D3DDEVCAPS_RTPATCHES |*/
619                      /*D3DDEVCAPS_RTPATCHHANDLEZERO |*/
620                      /*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/
621                      D3DDEVCAPS_TEXTURENONLOCALVIDMEM |
622                      /* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/
623                      D3DDEVCAPS_TEXTUREVIDEOMEMORY |
624                      D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |
625                      D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
626 
627     pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ |
628                                D3DPMISCCAPS_CULLNONE | /* XXX */
629                                D3DPMISCCAPS_CULLCW |
630                                D3DPMISCCAPS_CULLCCW |
631                                D3DPMISCCAPS_COLORWRITEENABLE |
632                                D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
633                                /*D3DPMISCCAPS_CLIPTLVERTS |*/
634                                D3DPMISCCAPS_TSSARGTEMP |
635                                D3DPMISCCAPS_BLENDOP |
636                                D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |
637                                D3DPMISCCAPS_PERSTAGECONSTANT |
638                                /*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */
639                                D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */
640                                D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |
641                                D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |
642                                D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |
643                                D3DPMISCCAPS_FOGVERTEXCLAMPED;
644     if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION))
645         pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS;
646 
647     pCaps->RasterCaps =
648         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |
649         D3DPRASTERCAPS_COLORPERSPECTIVE |
650         D3DPRASTERCAPS_DITHER |
651         D3DPRASTERCAPS_DEPTHBIAS |
652         D3DPRASTERCAPS_FOGRANGE |
653         D3DPRASTERCAPS_FOGTABLE |
654         D3DPRASTERCAPS_FOGVERTEX |
655         D3DPRASTERCAPS_MIPMAPLODBIAS |
656         D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |
657         D3DPRASTERCAPS_SCISSORTEST |
658         D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
659         /*D3DPRASTERCAPS_WBUFFER |*/
660         D3DPRASTERCAPS_WFOG |
661         /*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/
662         D3DPRASTERCAPS_ZFOG |
663         D3DPRASTERCAPS_ZTEST;
664 
665     pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |
666                       D3DPCMPCAPS_LESS |
667                       D3DPCMPCAPS_EQUAL |
668                       D3DPCMPCAPS_LESSEQUAL |
669                       D3DPCMPCAPS_GREATER |
670                       D3DPCMPCAPS_NOTEQUAL |
671                       D3DPCMPCAPS_GREATEREQUAL |
672                       D3DPCMPCAPS_ALWAYS;
673 
674     pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO |
675                           D3DPBLENDCAPS_ONE |
676                           D3DPBLENDCAPS_SRCCOLOR |
677                           D3DPBLENDCAPS_INVSRCCOLOR |
678                           D3DPBLENDCAPS_SRCALPHA |
679                           D3DPBLENDCAPS_INVSRCALPHA |
680                           D3DPBLENDCAPS_DESTALPHA |
681                           D3DPBLENDCAPS_INVDESTALPHA |
682                           D3DPBLENDCAPS_DESTCOLOR |
683                           D3DPBLENDCAPS_INVDESTCOLOR |
684                           D3DPBLENDCAPS_SRCALPHASAT |
685                           D3DPBLENDCAPS_BOTHSRCALPHA |
686                           D3DPBLENDCAPS_BOTHINVSRCALPHA |
687                           D3DPBLENDCAPS_BLENDFACTOR |
688                           D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS,
689                               D3DPBLENDCAPS_INVSRCCOLOR2 |
690                               D3DPBLENDCAPS_SRCCOLOR2);
691 
692     pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
693 
694     pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER |
695                           D3DPCMPCAPS_LESS |
696                           D3DPCMPCAPS_EQUAL |
697                           D3DPCMPCAPS_LESSEQUAL |
698                           D3DPCMPCAPS_GREATER |
699                           D3DPCMPCAPS_NOTEQUAL |
700                           D3DPCMPCAPS_GREATEREQUAL |
701                           D3DPCMPCAPS_ALWAYS;
702 
703     /* FLAT caps not legal for D3D9. */
704     pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB |
705                        D3DPSHADECAPS_SPECULARGOURAUDRGB |
706                        D3DPSHADECAPS_ALPHAGOURAUDBLEND |
707                        D3DPSHADECAPS_FOGGOURAUD;
708 
709     pCaps->TextureCaps =
710         D3DPTEXTURECAPS_ALPHA |
711         D3DPTEXTURECAPS_ALPHAPALETTE |
712         D3DPTEXTURECAPS_PERSPECTIVE |
713         D3DPTEXTURECAPS_PROJECTED |
714         D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE |
715         D3DPTEXTURECAPS_CUBEMAP |
716         D3DPTEXTURECAPS_VOLUMEMAP |
717         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) |
718         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) |
719         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) |
720         D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) |
721         D3DPIPECAP(MAX_TEXTURE_2D_SIZE, D3DPTEXTURECAPS_MIPMAP) |
722         D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) |
723         D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP);
724 
725     pCaps->TextureFilterCaps =
726         D3DPTFILTERCAPS_MINFPOINT |
727         D3DPTFILTERCAPS_MINFLINEAR |
728         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) |
729         /*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/
730         /*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/
731         D3DPTFILTERCAPS_MIPFPOINT |
732         D3DPTFILTERCAPS_MIPFLINEAR |
733         D3DPTFILTERCAPS_MAGFPOINT |
734         D3DPTFILTERCAPS_MAGFLINEAR |
735         D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) |
736         /*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/
737         /*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0;
738 
739     pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;
740     pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;
741 
742     pCaps->TextureAddressCaps =
743         D3DPTADDRESSCAPS_BORDER |
744         D3DPTADDRESSCAPS_INDEPENDENTUV |
745         D3DPTADDRESSCAPS_WRAP |
746         D3DPTADDRESSCAPS_MIRROR |
747         D3DPTADDRESSCAPS_CLAMP |
748         D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE);
749 
750     pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;
751 
752     pCaps->LineCaps =
753         D3DLINECAPS_ALPHACMP |
754         D3DLINECAPS_BLEND |
755         D3DLINECAPS_TEXTURE |
756         D3DLINECAPS_ZTEST |
757         D3DLINECAPS_FOG;
758     if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) {
759         pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS;
760     }
761 
762     pCaps->MaxTextureWidth =screen->get_param(screen,
763                                               PIPE_CAP_MAX_TEXTURE_2D_SIZE);
764     pCaps->MaxTextureHeight = pCaps->MaxTextureWidth;
765     pCaps->MaxVolumeExtent =
766         1 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1);
767     /* XXX values from wine */
768     pCaps->MaxTextureRepeat = 32768;
769     pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth;
770 
771     pCaps->MaxAnisotropy =
772         (DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);
773 
774     /* Values for GeForce 9600 GT */
775     pCaps->MaxVertexW = 1e10f;
776     pCaps->GuardBandLeft = -1e9f;
777     pCaps->GuardBandTop = -1e9f;
778     pCaps->GuardBandRight = 1e9f;
779     pCaps->GuardBandBottom = 1e9f;
780     pCaps->ExtentsAdjust = 0.0f;
781 
782     pCaps->StencilCaps =
783         D3DSTENCILCAPS_KEEP |
784         D3DSTENCILCAPS_ZERO |
785         D3DSTENCILCAPS_REPLACE |
786         D3DSTENCILCAPS_INCRSAT |
787         D3DSTENCILCAPS_DECRSAT |
788         D3DSTENCILCAPS_INVERT |
789         D3DSTENCILCAPS_INCR |
790         D3DSTENCILCAPS_DECR |
791         D3DSTENCILCAPS_TWOSIDED;
792 
793     pCaps->FVFCaps =
794         8 | /* 8 textures max */
795         /*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/
796         D3DFVFCAPS_PSIZE;
797 
798     pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |
799                            D3DTEXOPCAPS_SELECTARG1 |
800                            D3DTEXOPCAPS_SELECTARG2 |
801                            D3DTEXOPCAPS_MODULATE |
802                            D3DTEXOPCAPS_MODULATE2X |
803                            D3DTEXOPCAPS_MODULATE4X |
804                            D3DTEXOPCAPS_ADD |
805                            D3DTEXOPCAPS_ADDSIGNED |
806                            D3DTEXOPCAPS_ADDSIGNED2X |
807                            D3DTEXOPCAPS_SUBTRACT |
808                            D3DTEXOPCAPS_ADDSMOOTH |
809                            D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
810                            D3DTEXOPCAPS_BLENDTEXTUREALPHA |
811                            D3DTEXOPCAPS_BLENDFACTORALPHA |
812                            D3DTEXOPCAPS_BLENDTEXTUREALPHAPM |
813                            D3DTEXOPCAPS_BLENDCURRENTALPHA |
814                            D3DTEXOPCAPS_PREMODULATE |
815                            D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
816                            D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
817                            D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
818                            D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |
819                            D3DTEXOPCAPS_BUMPENVMAP |
820                            D3DTEXOPCAPS_BUMPENVMAPLUMINANCE |
821                            D3DTEXOPCAPS_DOTPRODUCT3 |
822                            D3DTEXOPCAPS_MULTIPLYADD |
823                            D3DTEXOPCAPS_LERP;
824 
825     pCaps->MaxTextureBlendStages = 8; /* XXX wine */
826         (DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE);
827     pCaps->MaxSimultaneousTextures = 8;
828 
829     pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN |
830                                   D3DVTXPCAPS_TEXGEN_SPHEREMAP |
831                                   D3DVTXPCAPS_MATERIALSOURCE7 |
832                                   D3DVTXPCAPS_DIRECTIONALLIGHTS |
833                                   D3DVTXPCAPS_POSITIONALLIGHTS |
834                                   D3DVTXPCAPS_LOCALVIEWER |
835                                   D3DVTXPCAPS_TWEENING |
836                                   /*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0;
837 
838     pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */
839     pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES;
840     pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */
841     pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */
842 
843     pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH);
844 
845     pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */
846     pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */
847     pCaps->MaxStreams =
848         _min(screen->get_shader_param(screen,
849                  PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS),
850              16);
851 
852     pCaps->MaxStreamStride = screen->get_param(screen,
853             PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);
854 
855     pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
856 
857     /* VS 2 as well as 3.0 supports a minimum of 256 consts.
858      * Wine and d3d9 drivers for dx1x hw advertise 256. Just as them,
859      * advertise 256. Problem is with hw that can only do 256, because
860      * we need take a few slots for boolean and integer constants. For these
861      * we'll have to fail later if they use complex shaders. */
862     pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;
863 
864     pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
865     /* Value for GeForce 9600 GT */
866     pCaps->PixelShader1xMaxValue = 65504.f;
867 
868     pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |
869                       D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |
870                       D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES |
871                       /*D3DDEVCAPS2_DMAPNPATCH |*/
872                       /*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/
873                       /*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/
874                       /*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0;
875 
876     pCaps->MasterAdapterOrdinal = 0;
877     pCaps->AdapterOrdinalInGroup = 0;
878     pCaps->NumberOfAdaptersInGroup = 1;
879 
880     /* Undocumented ? */
881     pCaps->MaxNpatchTessellationLevel = 0.0f;
882     pCaps->Reserved5 = 0;
883 
884     /* XXX: use is_format_supported */
885     pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
886                        D3DDTCAPS_UBYTE4N |
887                        D3DDTCAPS_SHORT2N |
888                        D3DDTCAPS_SHORT4N |
889                        D3DDTCAPS_USHORT2N |
890                        D3DDTCAPS_USHORT4N |
891                        D3DDTCAPS_UDEC3 |
892                        D3DDTCAPS_DEC3N |
893                        D3DDTCAPS_FLOAT16_2 |
894                        D3DDTCAPS_FLOAT16_4;
895 
896     pCaps->NumSimultaneousRTs =
897         screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS);
898     if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS)
899         pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS;
900 
901     pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT |
902                                    D3DPTFILTERCAPS_MINFLINEAR |
903                                    D3DPTFILTERCAPS_MAGFPOINT |
904                                    D3DPTFILTERCAPS_MAGFLINEAR;
905 
906 
907     pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
908     pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
909         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
910                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
911     pCaps->VS20Caps.NumTemps =
912         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
913                                  PIPE_SHADER_CAP_MAX_TEMPS);
914     pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */
915         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
916                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
917 
918     /* also check for values < 0, because get_shader_param may return unsigned */
919     if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
920         || pCaps->VS20Caps.DynamicFlowControlDepth < 0)
921         pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;
922     if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH
923         || pCaps->VS20Caps.StaticFlowControlDepth < 0)
924         pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH;
925     if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS)
926         pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;
927     assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH);
928     assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH);
929     assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS);
930 
931 
932     pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
933                            D3DPS20CAPS_GRADIENTINSTRUCTIONS |
934                            D3DPS20CAPS_PREDICATION;
935     if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
936                                  PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
937         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
938                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
939         pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
940     if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
941                                  PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==
942         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
943                                  PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS))
944         pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT;
945     pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */
946         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
947                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
948     pCaps->PS20Caps.NumTemps =
949         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
950                                  PIPE_SHADER_CAP_MAX_TEMPS);
951     pCaps->PS20Caps.StaticFlowControlDepth =  /* XXX is this static ? */
952         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
953                                  PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
954     pCaps->PS20Caps.NumInstructionSlots =
955         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
956                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
957 
958     if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
959         || pCaps->PS20Caps.DynamicFlowControlDepth < 0)
960         pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;
961     if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH
962         || pCaps->PS20Caps.StaticFlowControlDepth < 0)
963         pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH;
964     if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS)
965         pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS;
966     if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS)
967         pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS;
968     assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH);
969     assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH);
970     assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS);
971     assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS);
972 
973 
974     if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
975                                  PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))
976         pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps &
977             ~(D3DPTFILTERCAPS_MIPFPOINT |
978               D3DPTFILTERCAPS_MIPFPOINT); /* XXX */
979     else
980         pCaps->VertexTextureFilterCaps = 0;
981 
982     pCaps->MaxVertexShader30InstructionSlots =
983         screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
984                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
985     pCaps->MaxPixelShader30InstructionSlots =
986         screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,
987                                  PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
988     if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
989         pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
990     if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)
991         pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;
992     assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
993     assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);
994 
995     /* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */
996     pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);
997     pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32);
998 
999     if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE))
1000         nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps);
1001 
1002     return D3D_OK;
1003 }
1004 
1005 HRESULT NINE_WINAPI
NineAdapter9_CreateDevice(struct NineAdapter9 * This,UINT RealAdapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS * pPresentationParameters,IDirect3D9 * pD3D9,ID3DPresentGroup * pPresentationGroup,IDirect3DDevice9 ** ppReturnedDeviceInterface)1006 NineAdapter9_CreateDevice( struct NineAdapter9 *This,
1007                            UINT RealAdapter,
1008                            D3DDEVTYPE DeviceType,
1009                            HWND hFocusWindow,
1010                            DWORD BehaviorFlags,
1011                            D3DPRESENT_PARAMETERS *pPresentationParameters,
1012                            IDirect3D9 *pD3D9,
1013                            ID3DPresentGroup *pPresentationGroup,
1014                            IDirect3DDevice9 **ppReturnedDeviceInterface )
1015 {
1016     struct pipe_screen *screen;
1017     D3DDEVICE_CREATION_PARAMETERS params;
1018     D3DCAPS9 caps;
1019     int major, minor;
1020     HRESULT hr;
1021 
1022     DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
1023         "BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p "
1024         "ppReturnedDeviceInterface=%p\n", This,
1025         RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
1026         BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface);
1027 
1028     ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
1029     if (major != 1) {
1030         ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
1031             major, minor);
1032         return D3DERR_NOTAVAILABLE;
1033     }
1034 
1035     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
1036     if (FAILED(hr)) {
1037         DBG("Failed to get pipe_screen.\n");
1038         return hr;
1039     }
1040 
1041     hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
1042     if (FAILED(hr)) {
1043         DBG("Failed to get device caps.\n");
1044         return hr;
1045     }
1046 
1047     params.AdapterOrdinal = RealAdapter;
1048     params.DeviceType = DeviceType;
1049     params.hFocusWindow = hFocusWindow;
1050     params.BehaviorFlags = BehaviorFlags;
1051 
1052     hr = NineDevice9_new(screen, &params, &caps, pPresentationParameters,
1053                          pD3D9, pPresentationGroup, This->ctx, FALSE, NULL,
1054                          (struct NineDevice9 **)ppReturnedDeviceInterface,
1055                          minor);
1056     if (FAILED(hr)) {
1057         DBG("Failed to create device.\n");
1058         return hr;
1059     }
1060     DBG("NineDevice9 created successfully.\n");
1061 
1062     return D3D_OK;
1063 }
1064 
1065 HRESULT NINE_WINAPI
NineAdapter9_CreateDeviceEx(struct NineAdapter9 * This,UINT RealAdapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS * pPresentationParameters,D3DDISPLAYMODEEX * pFullscreenDisplayMode,IDirect3D9Ex * pD3D9Ex,ID3DPresentGroup * pPresentationGroup,IDirect3DDevice9Ex ** ppReturnedDeviceInterface)1066 NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,
1067                              UINT RealAdapter,
1068                              D3DDEVTYPE DeviceType,
1069                              HWND hFocusWindow,
1070                              DWORD BehaviorFlags,
1071                              D3DPRESENT_PARAMETERS *pPresentationParameters,
1072                              D3DDISPLAYMODEEX *pFullscreenDisplayMode,
1073                              IDirect3D9Ex *pD3D9Ex,
1074                              ID3DPresentGroup *pPresentationGroup,
1075                              IDirect3DDevice9Ex **ppReturnedDeviceInterface )
1076 {
1077     struct pipe_screen *screen;
1078     D3DDEVICE_CREATION_PARAMETERS params;
1079     D3DCAPS9 caps;
1080     int major, minor;
1081     HRESULT hr;
1082 
1083     DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "
1084         "BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p "
1085         "ppReturnedDeviceInterface=%p\n", This,
1086         RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,
1087         BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface);
1088 
1089     ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);
1090     if (major != 1) {
1091         ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",
1092             major, minor);
1093         return D3DERR_NOTAVAILABLE;
1094     }
1095 
1096     hr = NineAdapter9_GetScreen(This, DeviceType, &screen);
1097     if (FAILED(hr)) {
1098         DBG("Failed to get pipe_screen.\n");
1099         return hr;
1100     }
1101 
1102     hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);
1103     if (FAILED(hr)) {
1104         DBG("Failed to get device caps.\n");
1105         return hr;
1106     }
1107 
1108     params.AdapterOrdinal = RealAdapter;
1109     params.DeviceType = DeviceType;
1110     params.hFocusWindow = hFocusWindow;
1111     params.BehaviorFlags = BehaviorFlags;
1112 
1113     hr = NineDevice9Ex_new(screen, &params, &caps, pPresentationParameters,
1114                            pFullscreenDisplayMode,
1115                            pD3D9Ex, pPresentationGroup, This->ctx,
1116                            (struct NineDevice9Ex **)ppReturnedDeviceInterface,
1117                            minor);
1118     if (FAILED(hr)) {
1119         DBG("Failed to create device.\n");
1120         return hr;
1121     }
1122     DBG("NineDevice9Ex created successfully.\n");
1123 
1124     return D3D_OK;
1125 }
1126 
1127 ID3DAdapter9Vtbl NineAdapter9_vtable = {
1128     (void *)NineUnknown_QueryInterface,
1129     (void *)NineUnknown_AddRef,
1130     (void *)NineUnknown_Release,
1131     (void *)NineAdapter9_GetAdapterIdentifier,
1132     (void *)NineAdapter9_CheckDeviceType,
1133     (void *)NineAdapter9_CheckDeviceFormat,
1134     (void *)NineAdapter9_CheckDeviceMultiSampleType,
1135     (void *)NineAdapter9_CheckDepthStencilMatch,
1136     (void *)NineAdapter9_CheckDeviceFormatConversion,
1137     (void *)NineAdapter9_GetDeviceCaps,
1138     (void *)NineAdapter9_CreateDevice,
1139     (void *)NineAdapter9_CreateDeviceEx
1140 };
1141 
1142 static const GUID *NineAdapter9_IIDs[] = {
1143     &IID_ID3D9Adapter,
1144     &IID_IUnknown,
1145     NULL
1146 };
1147 
1148 HRESULT
NineAdapter9_new(struct d3dadapter9_context * pCTX,struct NineAdapter9 ** ppOut)1149 NineAdapter9_new( struct d3dadapter9_context *pCTX,
1150                   struct NineAdapter9 **ppOut )
1151 {
1152     NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX);
1153 }
1154