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