Path: blob/21.2-virgl/src/gallium/frontends/nine/adapter9.c
4561 views
/*1* Copyright 2011 Joakim Sindholt <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE. */2122#include "adapter9.h"23#include "device9ex.h"24#include "nine_helpers.h"25#include "nine_defines.h"26#include "nine_pipe.h"27#include "nine_dump.h"28#include "util/u_math.h"29#include "util/format/u_format.h"30#include "util/u_dump.h"3132#include "pipe/p_screen.h"3334#define DBG_CHANNEL DBG_ADAPTER3536static bool37has_sm3(struct pipe_screen *hal)38{39return hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD) &&40hal->get_param(hal, PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES) &&41hal->get_param(hal, PIPE_CAP_VERTEX_SHADER_SATURATE);42}4344HRESULT45NineAdapter9_ctor( struct NineAdapter9 *This,46struct NineUnknownParams *pParams,47struct d3dadapter9_context *pCTX )48{49struct pipe_screen *hal = pCTX->hal;50HRESULT hr = NineUnknown_ctor(&This->base, pParams);51if (FAILED(hr)) { return hr; }5253DBG("This=%p pParams=%p pCTX=%p\n", This, pParams, pCTX);54nine_dump_D3DADAPTER_IDENTIFIER9(DBG_CHANNEL, &pCTX->identifier);5556This->ctx = pCTX;57if (!hal->get_param(hal, PIPE_CAP_CLIP_HALFZ)) {58ERR("Driver doesn't support d3d9 coordinates\n");59return D3DERR_DRIVERINTERNALERROR;60}61if (This->ctx->ref &&62!This->ctx->ref->get_param(This->ctx->ref, PIPE_CAP_CLIP_HALFZ)) {63ERR("Warning: Sotware rendering driver doesn't support d3d9 coordinates\n");64}65/* Old cards had tricks to bypass some restrictions to implement66* everything and fit tight the requirements: number of constants,67* number of temp registers, special behaviours, etc. Since we don't68* have access to all this, we need a bit more than what dx9 required.69* For example we have to use more than 32 temp registers to emulate70* behaviours, while some dx9 hw don't have more. As for sm2 hardware,71* we could support vs2 / ps2 for them but it needs some more care, and72* as these are very old, we choose to drop support for them */7374/* checks minimum requirements, most are vs3/ps3 strict requirements */75if (!has_sm3(hal) ||76hal->get_shader_param(hal, PIPE_SHADER_VERTEX,77PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 256 * sizeof(float[4]) ||78hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,79PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 244 * sizeof(float[4]) ||80hal->get_shader_param(hal, PIPE_SHADER_VERTEX,81PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||82hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,83PIPE_SHADER_CAP_MAX_TEMPS) < 32 ||84hal->get_shader_param(hal, PIPE_SHADER_VERTEX,85PIPE_SHADER_CAP_MAX_INPUTS) < 16 ||86hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,87PIPE_SHADER_CAP_MAX_INPUTS) < 10 ||88hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,89PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS) < 16) {90ERR("Your card is not supported by Gallium Nine. Minimum requirement "91"is >= r500, >= nv50, >= i965\n");92return D3DERR_DRIVERINTERNALERROR;93}94/* for r500 */95if (hal->get_shader_param(hal, PIPE_SHADER_VERTEX,96PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) < 276 * sizeof(float[4]) || /* we put bool and int constants with float constants */97hal->get_shader_param(hal, PIPE_SHADER_VERTEX,98PIPE_SHADER_CAP_MAX_TEMPS) < 40 || /* we use some more temp registers */99hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,100PIPE_SHADER_CAP_MAX_TEMPS) < 40 ||101hal->get_shader_param(hal, PIPE_SHADER_FRAGMENT,102PIPE_SHADER_CAP_MAX_INPUTS) < 20) /* we don't pack inputs as much as we could */103ERR("Your card is at the limit of Gallium Nine requirements. Some games "104"may run into issues because requirements are too tight\n");105return D3D_OK;106}107108void109NineAdapter9_dtor( struct NineAdapter9 *This )110{111struct d3dadapter9_context *ctx = This->ctx;112113DBG("This=%p\n", This);114115NineUnknown_dtor(&This->base);116117/* special case, call backend-specific dtor AFTER destroying this object118* completely. */119if (ctx) {120if (ctx->destroy) { ctx->destroy(ctx); }121}122}123124static HRESULT125NineAdapter9_GetScreen( struct NineAdapter9 *This,126D3DDEVTYPE DevType,127struct pipe_screen **ppScreen )128{129const char *force_sw = getenv("D3D_ALWAYS_SOFTWARE");130switch (DevType) {131case D3DDEVTYPE_HAL:132if (force_sw && !strcmp(force_sw, "1") && This->ctx->ref) {133*ppScreen = This->ctx->ref;134break;135}136*ppScreen = This->ctx->hal;137break;138139case D3DDEVTYPE_REF:140case D3DDEVTYPE_NULLREF:141case D3DDEVTYPE_SW:142if (force_sw && !strcmp(force_sw, "0")) {143*ppScreen = This->ctx->hal;144break;145}146*ppScreen = This->ctx->ref;147break;148149default:150user_assert(!"Invalid device type", D3DERR_INVALIDCALL);151}152153if (!*ppScreen) { return D3DERR_NOTAVAILABLE; }154155return D3D_OK;156}157158HRESULT NINE_WINAPI159NineAdapter9_GetAdapterIdentifier( struct NineAdapter9 *This,160DWORD Flags,161D3DADAPTER_IDENTIFIER9 *pIdentifier )162{163DBG("This=%p Flags=%x pIdentifier=%p\n", This, Flags, pIdentifier);164165/* regarding flags, MSDN has this to say:166* Flags sets the WHQLLevel member of D3DADAPTER_IDENTIFIER9. Flags can be167* set to either 0 or D3DENUM_WHQL_LEVEL. If D3DENUM_WHQL_LEVEL is168* specified, this call can connect to the Internet to download new169* Microsoft Windows Hardware Quality Labs (WHQL) certificates.170* so let's just ignore it. */171*pIdentifier = This->ctx->identifier;172return D3D_OK;173}174175static inline boolean176backbuffer_format( D3DFORMAT dfmt,177D3DFORMAT bfmt,178boolean win )179{180if (dfmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }181182if ((dfmt == D3DFMT_A2R10G10B10 && bfmt == dfmt) ||183(dfmt == D3DFMT_X8R8G8B8 && (bfmt == dfmt ||184bfmt == D3DFMT_A8R8G8B8)) ||185(dfmt == D3DFMT_X1R5G5B5 && (bfmt == dfmt ||186bfmt == D3DFMT_A1R5G5B5)) ||187(dfmt == D3DFMT_R5G6B5 && bfmt == dfmt)) {188return TRUE;189}190191return FALSE;192}193194HRESULT NINE_WINAPI195NineAdapter9_CheckDeviceType( struct NineAdapter9 *This,196D3DDEVTYPE DevType,197D3DFORMAT AdapterFormat,198D3DFORMAT BackBufferFormat,199BOOL bWindowed )200{201struct pipe_screen *screen;202enum pipe_format dfmt, bfmt;203HRESULT hr;204205DBG("This=%p DevType=%s AdapterFormat=%s BackBufferFormat=%s "206"bWindowed=%i\n", This, nine_D3DDEVTYPE_to_str(DevType),207d3dformat_to_string(AdapterFormat),208d3dformat_to_string(BackBufferFormat), bWindowed);209210user_assert(backbuffer_format(AdapterFormat, BackBufferFormat, bWindowed),211D3DERR_NOTAVAILABLE);212213hr = NineAdapter9_GetScreen(This, DevType, &screen);214if (FAILED(hr)) { return hr; }215216/* The display format is not handled in Nine. We always present an XRGB8888217* buffer (and the display server will eventually do the conversion). We probably218* don't need to check for anything for the adapter format support, since if the219* display server advertise support, it will likely be able to do the conversion.220* We do the approximation that a format is available in the display server if221* the format passes with NINE_BIND_BACKBUFFER_FLAGS */222dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D,2231,224NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);225bfmt = d3d9_to_pipe_format_checked(screen, BackBufferFormat, PIPE_TEXTURE_2D,2261,227NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);228if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {229DBG("Unsupported Adapter/BackBufferFormat.\n");230return D3DERR_NOTAVAILABLE;231}232233return D3D_OK;234}235236static inline boolean237display_format( D3DFORMAT fmt,238boolean win )239{240/* http://msdn.microsoft.com/en-us/library/bb172558(v=VS.85).aspx#BackBuffer_or_Display_Formats */241static const D3DFORMAT allowed[] = {242D3DFMT_A2R10G10B10,243D3DFMT_X8R8G8B8,244D3DFMT_X1R5G5B5,245D3DFMT_R5G6B5,246};247unsigned i;248249if (fmt == D3DFMT_A2R10G10B10 && win) { return FALSE; }250251for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {252if (fmt == allowed[i]) { return TRUE; }253}254return FALSE;255}256257static inline boolean258adapter_format( D3DFORMAT fmt )259{260/* Formats that are compatible to display_format (modulo alpha bits) */261static const D3DFORMAT allowed[] = {262D3DFMT_A2R10G10B10,263D3DFMT_X8R8G8B8,264D3DFMT_A8R8G8B8,265D3DFMT_X1R5G5B5,266D3DFMT_A1R5G5B5,267D3DFMT_R5G6B5,268};269unsigned i;270271for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) {272if (fmt == allowed[i]) { return TRUE; }273}274return FALSE;275}276277HRESULT NINE_WINAPI278NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This,279D3DDEVTYPE DeviceType,280D3DFORMAT AdapterFormat,281DWORD Usage,282D3DRESOURCETYPE RType,283D3DFORMAT CheckFormat )284{285struct pipe_screen *screen;286HRESULT hr;287enum pipe_format pf;288enum pipe_texture_target target;289unsigned bind = 0;290boolean srgb;291292/* Check adapter format. */293294DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This,295nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat));296DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType,297d3dformat_to_string(CheckFormat));298299/* Wine tests, but suspicious. Needs more tests. */300user_assert(adapter_format(AdapterFormat), D3DERR_INVALIDCALL);301user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE);302303hr = NineAdapter9_GetScreen(This, DeviceType, &screen);304if (FAILED(hr))305return hr;306pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,307PIPE_BIND_DISPLAY_TARGET |308PIPE_BIND_SHARED, FALSE, FALSE);309if (pf == PIPE_FORMAT_NONE) {310DBG("AdapterFormat %s not available.\n",311d3dformat_to_string(AdapterFormat));312return D3DERR_NOTAVAILABLE;313}314315/* Check actual format. */316317switch (RType) {318case D3DRTYPE_SURFACE: target = PIPE_TEXTURE_2D; break;319case D3DRTYPE_TEXTURE: target = PIPE_TEXTURE_2D; break;320case D3DRTYPE_CUBETEXTURE: target = PIPE_TEXTURE_CUBE; break;321case D3DRTYPE_VOLUME: target = PIPE_TEXTURE_3D; break;322case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break;323case D3DRTYPE_VERTEXBUFFER: target = PIPE_BUFFER; break;324case D3DRTYPE_INDEXBUFFER: target = PIPE_BUFFER; break;325default:326user_assert(0, D3DERR_INVALIDCALL);327}328329bind = 0;330if (Usage & D3DUSAGE_RENDERTARGET) {331if (depth_stencil_format(CheckFormat))332return D3DERR_NOTAVAILABLE;333bind |= PIPE_BIND_RENDER_TARGET;334}335if (Usage & D3DUSAGE_DEPTHSTENCIL) {336if (!depth_stencil_format(CheckFormat))337return D3DERR_NOTAVAILABLE;338bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat);339}340341/* API hack because setting RT[0] to NULL is forbidden */342if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET &&343(RType == D3DRTYPE_SURFACE ||344RType == D3DRTYPE_TEXTURE))345return D3D_OK;346347/* RESZ hack */348if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET &&349RType == D3DRTYPE_SURFACE)350return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ?351D3D_OK : D3DERR_NOTAVAILABLE;352353/* ATOC hack */354if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE)355return D3D_OK;356357if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) &&358(Usage & D3DUSAGE_RENDERTARGET))359bind |= PIPE_BIND_BLENDABLE;360361if (Usage & D3DUSAGE_DMAP) {362DBG("D3DUSAGE_DMAP not available\n");363return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */364}365366switch (RType) {367case D3DRTYPE_TEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;368case D3DRTYPE_CUBETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;369case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break;370case D3DRTYPE_VERTEXBUFFER: bind |= PIPE_BIND_VERTEX_BUFFER; break;371case D3DRTYPE_INDEXBUFFER: bind |= PIPE_BIND_INDEX_BUFFER; break;372case D3DRTYPE_SURFACE:373if (!(Usage & D3DUSAGE_DEPTHSTENCIL))374bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */375/* Offscreen surface support: Usage = 0.376* In practice drivers are very restrictive on the formats supported.377* Basically a few common formats + YUV and compressed formats. The378* reason is that offscreen surface are useful only for directdraw379* compatibility (a WONTIMPL of nine) + format conversion (useful in380* particular for YUV because the format was not advertised for textures381* on NV chips). */382if (Usage == 0)383bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */384break;385default:386break;387}388389390srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;391pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target,3920, bind, srgb, FALSE);393if (pf == PIPE_FORMAT_NONE) {394DBG("NOT AVAILABLE\n");395return D3DERR_NOTAVAILABLE;396}397398/* we support ATI1 and ATI2 hack only for 2D and Cube textures */399if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE &&400(CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2))401return D3DERR_NOTAVAILABLE;402/* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */403/* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */404405if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW))406return D3DOK_NOAUTOGEN;407return D3D_OK;408}409410HRESULT NINE_WINAPI411NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This,412D3DDEVTYPE DeviceType,413D3DFORMAT SurfaceFormat,414BOOL Windowed,415D3DMULTISAMPLE_TYPE MultiSampleType,416DWORD *pQualityLevels )417{418struct pipe_screen *screen;419HRESULT hr;420enum pipe_format pf;421unsigned bind;422423DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u "424"pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType),425d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType,426pQualityLevels);427428if (pQualityLevels) {429/* In error cases return only 1 quality level supported */430*pQualityLevels = 1;431}432user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL);433434hr = NineAdapter9_GetScreen(This, DeviceType, &screen);435if (FAILED(hr))436return hr;437438if (depth_stencil_format(SurfaceFormat))439bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat);440else /* render-target */441bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;442443pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,4440, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE);445446if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {447DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat));448return D3DERR_INVALIDCALL;449}450451pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D,452MultiSampleType, bind, FALSE, FALSE);453454if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) {455DBG("%s with %u samples not available.\n",456d3dformat_to_string(SurfaceFormat), MultiSampleType);457return D3DERR_NOTAVAILABLE;458}459460if (pQualityLevels) {461/* NONMASKABLE MultiSampleType might have more than one quality level,462* while MASKABLE MultiSampleTypes have only one level.463* Advertise quality levels and map each level to a sample count. */464(void ) d3dmultisample_type_check(screen, SurfaceFormat,465&MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels);466DBG("advertising %u quality levels\n", *pQualityLevels);467}468469return D3D_OK;470}471472HRESULT NINE_WINAPI473NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This,474D3DDEVTYPE DeviceType,475D3DFORMAT AdapterFormat,476D3DFORMAT RenderTargetFormat,477D3DFORMAT DepthStencilFormat )478{479struct pipe_screen *screen;480enum pipe_format dfmt, bfmt, zsfmt;481HRESULT hr;482483DBG("This=%p DeviceType=%s AdapterFormat=%s "484"RenderTargetFormat=%s DepthStencilFormat=%s\n", This,485nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat),486d3dformat_to_string(RenderTargetFormat),487d3dformat_to_string(DepthStencilFormat));488489/* TODO: does it check AdapterFormat at all ?490* It seems to need to pass at least for A8R8G8B8:491* https://github.com/iXit/Mesa-3D/issues/317 */492user_assert(adapter_format(AdapterFormat), D3DERR_NOTAVAILABLE);493user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE);494495hr = NineAdapter9_GetScreen(This, DeviceType, &screen);496if (FAILED(hr)) { return hr; }497498dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0,499NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);500bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat,501PIPE_TEXTURE_2D, 0,502NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);503if (RenderTargetFormat == D3DFMT_NULL)504bfmt = dfmt;505zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat,506PIPE_TEXTURE_2D, 0,507d3d9_get_pipe_depth_format_bindings(DepthStencilFormat),508FALSE, FALSE);509if (dfmt == PIPE_FORMAT_NONE ||510bfmt == PIPE_FORMAT_NONE ||511zsfmt == PIPE_FORMAT_NONE) {512return D3DERR_NOTAVAILABLE;513}514515return D3D_OK;516}517518HRESULT NINE_WINAPI519NineAdapter9_CheckDeviceFormatConversion( struct NineAdapter9 *This,520D3DDEVTYPE DeviceType,521D3DFORMAT SourceFormat,522D3DFORMAT TargetFormat )523{524/* MSDN says this tests whether a certain backbuffer format can be used in525* conjunction with a certain front buffer format. It's a little confusing526* but some one wiser might be able to figure this one out. XXX */527struct pipe_screen *screen;528enum pipe_format dfmt, bfmt;529HRESULT hr;530531DBG("This=%p DeviceType=%s SourceFormat=%s TargetFormat=%s\n", This,532nine_D3DDEVTYPE_to_str(DeviceType),533d3dformat_to_string(SourceFormat), d3dformat_to_string(TargetFormat));534535user_assert(backbuffer_format(TargetFormat, SourceFormat, FALSE),536D3DERR_NOTAVAILABLE);537538hr = NineAdapter9_GetScreen(This, DeviceType, &screen);539if (FAILED(hr)) { return hr; }540541dfmt = d3d9_to_pipe_format_checked(screen, TargetFormat, PIPE_TEXTURE_2D, 1,542NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);543bfmt = d3d9_to_pipe_format_checked(screen, SourceFormat, PIPE_TEXTURE_2D, 1,544NINE_BIND_BACKBUFFER_FLAGS, FALSE, FALSE);545546if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE) {547DBG("%s to %s not supported.\n",548d3dformat_to_string(SourceFormat),549d3dformat_to_string(TargetFormat));550return D3DERR_NOTAVAILABLE;551}552553return D3D_OK;554}555556HRESULT NINE_WINAPI557NineAdapter9_GetDeviceCaps( struct NineAdapter9 *This,558D3DDEVTYPE DeviceType,559D3DCAPS9 *pCaps )560{561struct pipe_screen *screen;562HRESULT hr;563564DBG("This=%p DeviceType=%s pCaps=%p\n", This,565nine_D3DDEVTYPE_to_str(DeviceType), pCaps);566567user_assert(pCaps, D3DERR_INVALIDCALL);568569hr = NineAdapter9_GetScreen(This, DeviceType, &screen);570if (FAILED(hr)) {571DBG("Failed to get pipe_screen.\n");572return hr;573}574575#define D3DPIPECAP(pcap, d3dcap) \576(screen->get_param(screen, PIPE_CAP_##pcap) ? (d3dcap) : 0)577578#define D3DNPIPECAP(pcap, d3dcap) \579(screen->get_param(screen, PIPE_CAP_##pcap) ? 0 : (d3dcap))580581pCaps->DeviceType = DeviceType;582583pCaps->AdapterOrdinal = 0;584585pCaps->Caps = D3DCAPS_READ_SCANLINE;586587pCaps->Caps2 = /* D3DCAPS2_CANMANAGERESOURCE | */588/* D3DCAPS2_CANSHARERESOURCE | */589/* D3DCAPS2_CANCALIBRATEGAMMA | */590D3DCAPS2_DYNAMICTEXTURES |591D3DCAPS2_FULLSCREENGAMMA |592D3DCAPS2_CANAUTOGENMIPMAP;593594/* Note: D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD just means the595* backbuffer can be ARGB (instead of only XRGB) when we are fullscreen596* and in discard mode. */597pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |598D3DCAPS3_COPY_TO_VIDMEM |599D3DCAPS3_COPY_TO_SYSTEMMEM |600D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION;601602pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT |603D3DPRESENT_INTERVAL_ONE |604D3DPRESENT_INTERVAL_TWO |605D3DPRESENT_INTERVAL_THREE |606D3DPRESENT_INTERVAL_FOUR |607D3DPRESENT_INTERVAL_IMMEDIATE;608pCaps->CursorCaps = D3DCURSORCAPS_COLOR /* | D3DCURSORCAPS_LOWRES*/;609610pCaps->DevCaps = D3DDEVCAPS_CANBLTSYSTONONLOCAL |611D3DDEVCAPS_CANRENDERAFTERFLIP |612D3DDEVCAPS_DRAWPRIMITIVES2 |613D3DDEVCAPS_DRAWPRIMITIVES2EX |614D3DDEVCAPS_DRAWPRIMTLVERTEX |615D3DDEVCAPS_EXECUTESYSTEMMEMORY |616D3DDEVCAPS_EXECUTEVIDEOMEMORY |617D3DDEVCAPS_HWRASTERIZATION |618D3DDEVCAPS_HWTRANSFORMANDLIGHT |619/*D3DDEVCAPS_NPATCHES |*/620D3DDEVCAPS_PUREDEVICE |621/*D3DDEVCAPS_QUINTICRTPATCHES |*/622/*D3DDEVCAPS_RTPATCHES |*/623/*D3DDEVCAPS_RTPATCHHANDLEZERO |*/624/*D3DDEVCAPS_SEPARATETEXTUREMEMORIES |*/625D3DDEVCAPS_TEXTURENONLOCALVIDMEM |626/* D3DDEVCAPS_TEXTURESYSTEMMEMORY |*/627D3DDEVCAPS_TEXTUREVIDEOMEMORY |628D3DDEVCAPS_TLVERTEXSYSTEMMEMORY |629D3DDEVCAPS_TLVERTEXVIDEOMEMORY;630631pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ |632D3DPMISCCAPS_CULLNONE | /* XXX */633D3DPMISCCAPS_CULLCW |634D3DPMISCCAPS_CULLCCW |635D3DPMISCCAPS_COLORWRITEENABLE |636D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |637/*D3DPMISCCAPS_CLIPTLVERTS |*/638D3DPMISCCAPS_TSSARGTEMP |639D3DPMISCCAPS_BLENDOP |640D3DPIPECAP(INDEP_BLEND_ENABLE, D3DPMISCCAPS_INDEPENDENTWRITEMASKS) |641D3DPMISCCAPS_PERSTAGECONSTANT |642/*D3DPMISCCAPS_POSTBLENDSRGBCONVERT |*/ /* TODO: advertise if Ex and dx10 able card */643D3DPMISCCAPS_FOGANDSPECULARALPHA | /* Note: documentation of the flag is wrong */644D3DPIPECAP(BLEND_EQUATION_SEPARATE, D3DPMISCCAPS_SEPARATEALPHABLEND) |645D3DPIPECAP(MIXED_COLORBUFFER_FORMATS, D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS) |646D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING |647D3DPMISCCAPS_FOGVERTEXCLAMPED;648if (!screen->get_param(screen, PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION))649pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_CLIPTLVERTS;650651pCaps->RasterCaps =652D3DPIPECAP(ANISOTROPIC_FILTER, D3DPRASTERCAPS_ANISOTROPY) |653D3DPRASTERCAPS_COLORPERSPECTIVE |654D3DPRASTERCAPS_DITHER |655D3DPRASTERCAPS_DEPTHBIAS |656D3DPRASTERCAPS_FOGRANGE |657D3DPRASTERCAPS_FOGTABLE |658D3DPRASTERCAPS_FOGVERTEX |659D3DPRASTERCAPS_MIPMAPLODBIAS |660D3DPRASTERCAPS_MULTISAMPLE_TOGGLE |661D3DPRASTERCAPS_SCISSORTEST |662D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |663/*D3DPRASTERCAPS_WBUFFER |*/664D3DPRASTERCAPS_WFOG |665/*D3DPRASTERCAPS_ZBUFFERLESSHSR |*/666D3DPRASTERCAPS_ZFOG |667D3DPRASTERCAPS_ZTEST;668669pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER |670D3DPCMPCAPS_LESS |671D3DPCMPCAPS_EQUAL |672D3DPCMPCAPS_LESSEQUAL |673D3DPCMPCAPS_GREATER |674D3DPCMPCAPS_NOTEQUAL |675D3DPCMPCAPS_GREATEREQUAL |676D3DPCMPCAPS_ALWAYS;677678pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO |679D3DPBLENDCAPS_ONE |680D3DPBLENDCAPS_SRCCOLOR |681D3DPBLENDCAPS_INVSRCCOLOR |682D3DPBLENDCAPS_SRCALPHA |683D3DPBLENDCAPS_INVSRCALPHA |684D3DPBLENDCAPS_DESTALPHA |685D3DPBLENDCAPS_INVDESTALPHA |686D3DPBLENDCAPS_DESTCOLOR |687D3DPBLENDCAPS_INVDESTCOLOR |688D3DPBLENDCAPS_SRCALPHASAT |689D3DPBLENDCAPS_BOTHSRCALPHA |690D3DPBLENDCAPS_BOTHINVSRCALPHA |691D3DPBLENDCAPS_BLENDFACTOR |692D3DPIPECAP(MAX_DUAL_SOURCE_RENDER_TARGETS,693D3DPBLENDCAPS_INVSRCCOLOR2 |694D3DPBLENDCAPS_SRCCOLOR2);695696pCaps->DestBlendCaps = pCaps->SrcBlendCaps;697698pCaps->AlphaCmpCaps = D3DPCMPCAPS_NEVER |699D3DPCMPCAPS_LESS |700D3DPCMPCAPS_EQUAL |701D3DPCMPCAPS_LESSEQUAL |702D3DPCMPCAPS_GREATER |703D3DPCMPCAPS_NOTEQUAL |704D3DPCMPCAPS_GREATEREQUAL |705D3DPCMPCAPS_ALWAYS;706707/* FLAT caps not legal for D3D9. */708pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB |709D3DPSHADECAPS_SPECULARGOURAUDRGB |710D3DPSHADECAPS_ALPHAGOURAUDBLEND |711D3DPSHADECAPS_FOGGOURAUD;712713pCaps->TextureCaps =714D3DPTEXTURECAPS_ALPHA |715D3DPTEXTURECAPS_ALPHAPALETTE |716D3DPTEXTURECAPS_PERSPECTIVE |717D3DPTEXTURECAPS_PROJECTED |718D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE |719D3DPTEXTURECAPS_CUBEMAP |720D3DPTEXTURECAPS_VOLUMEMAP |721D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_POW2) |722D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_NONPOW2CONDITIONAL) |723D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_CUBEMAP_POW2) |724D3DNPIPECAP(NPOT_TEXTURES, D3DPTEXTURECAPS_VOLUMEMAP_POW2) |725D3DPIPECAP(MAX_TEXTURE_2D_SIZE, D3DPTEXTURECAPS_MIPMAP) |726D3DPIPECAP(MAX_TEXTURE_3D_LEVELS, D3DPTEXTURECAPS_MIPVOLUMEMAP) |727D3DPIPECAP(MAX_TEXTURE_CUBE_LEVELS, D3DPTEXTURECAPS_MIPCUBEMAP);728729pCaps->TextureFilterCaps =730D3DPTFILTERCAPS_MINFPOINT |731D3DPTFILTERCAPS_MINFLINEAR |732D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MINFANISOTROPIC) |733/*D3DPTFILTERCAPS_MINFPYRAMIDALQUAD |*/734/*D3DPTFILTERCAPS_MINFGAUSSIANQUAD |*/735D3DPTFILTERCAPS_MIPFPOINT |736D3DPTFILTERCAPS_MIPFLINEAR |737D3DPTFILTERCAPS_MAGFPOINT |738D3DPTFILTERCAPS_MAGFLINEAR |739D3DPIPECAP(ANISOTROPIC_FILTER, D3DPTFILTERCAPS_MAGFANISOTROPIC) |740/*D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD |*/741/*D3DPTFILTERCAPS_MAGFGAUSSIANQUAD*/0;742743pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;744pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;745746pCaps->TextureAddressCaps =747D3DPTADDRESSCAPS_BORDER |748D3DPTADDRESSCAPS_INDEPENDENTUV |749D3DPTADDRESSCAPS_WRAP |750D3DPTADDRESSCAPS_MIRROR |751D3DPTADDRESSCAPS_CLAMP |752D3DPIPECAP(TEXTURE_MIRROR_CLAMP, D3DPTADDRESSCAPS_MIRRORONCE);753754pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;755756pCaps->LineCaps =757D3DLINECAPS_ALPHACMP |758D3DLINECAPS_BLEND |759D3DLINECAPS_TEXTURE |760D3DLINECAPS_ZTEST |761D3DLINECAPS_FOG;762if (screen->get_paramf(screen, PIPE_CAPF_MAX_LINE_WIDTH_AA) > 0.0) {763pCaps->LineCaps |= D3DLINECAPS_ANTIALIAS;764}765766pCaps->MaxTextureWidth =screen->get_param(screen,767PIPE_CAP_MAX_TEXTURE_2D_SIZE);768pCaps->MaxTextureHeight = pCaps->MaxTextureWidth;769pCaps->MaxVolumeExtent =7701 << (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS) - 1);771/* XXX values from wine */772pCaps->MaxTextureRepeat = 32768;773pCaps->MaxTextureAspectRatio = pCaps->MaxTextureWidth;774775pCaps->MaxAnisotropy =776(DWORD)screen->get_paramf(screen, PIPE_CAPF_MAX_TEXTURE_ANISOTROPY);777778/* Values for GeForce 9600 GT */779pCaps->MaxVertexW = 1e10f;780pCaps->GuardBandLeft = -1e9f;781pCaps->GuardBandTop = -1e9f;782pCaps->GuardBandRight = 1e9f;783pCaps->GuardBandBottom = 1e9f;784pCaps->ExtentsAdjust = 0.0f;785786pCaps->StencilCaps =787D3DSTENCILCAPS_KEEP |788D3DSTENCILCAPS_ZERO |789D3DSTENCILCAPS_REPLACE |790D3DSTENCILCAPS_INCRSAT |791D3DSTENCILCAPS_DECRSAT |792D3DSTENCILCAPS_INVERT |793D3DSTENCILCAPS_INCR |794D3DSTENCILCAPS_DECR |795D3DSTENCILCAPS_TWOSIDED;796797pCaps->FVFCaps =7988 | /* 8 textures max */799/*D3DFVFCAPS_DONOTSTRIPELEMENTS |*/800D3DFVFCAPS_PSIZE;801802pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE |803D3DTEXOPCAPS_SELECTARG1 |804D3DTEXOPCAPS_SELECTARG2 |805D3DTEXOPCAPS_MODULATE |806D3DTEXOPCAPS_MODULATE2X |807D3DTEXOPCAPS_MODULATE4X |808D3DTEXOPCAPS_ADD |809D3DTEXOPCAPS_ADDSIGNED |810D3DTEXOPCAPS_ADDSIGNED2X |811D3DTEXOPCAPS_SUBTRACT |812D3DTEXOPCAPS_ADDSMOOTH |813D3DTEXOPCAPS_BLENDDIFFUSEALPHA |814D3DTEXOPCAPS_BLENDTEXTUREALPHA |815D3DTEXOPCAPS_BLENDFACTORALPHA |816D3DTEXOPCAPS_BLENDTEXTUREALPHAPM |817D3DTEXOPCAPS_BLENDCURRENTALPHA |818D3DTEXOPCAPS_PREMODULATE |819D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |820D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |821D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |822D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA |823D3DTEXOPCAPS_BUMPENVMAP |824D3DTEXOPCAPS_BUMPENVMAPLUMINANCE |825D3DTEXOPCAPS_DOTPRODUCT3 |826D3DTEXOPCAPS_MULTIPLYADD |827D3DTEXOPCAPS_LERP;828829pCaps->MaxTextureBlendStages = 8; /* XXX wine */830(DWORD)screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE);831pCaps->MaxSimultaneousTextures = 8;832833pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN |834D3DVTXPCAPS_TEXGEN_SPHEREMAP |835D3DVTXPCAPS_MATERIALSOURCE7 |836D3DVTXPCAPS_DIRECTIONALLIGHTS |837D3DVTXPCAPS_POSITIONALLIGHTS |838D3DVTXPCAPS_LOCALVIEWER |839D3DVTXPCAPS_TWEENING |840/*D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/0;841842pCaps->MaxActiveLights = NINE_MAX_LIGHTS_ACTIVE; /* like GL_LIGHTi */843pCaps->MaxUserClipPlanes = PIPE_MAX_CLIP_PLANES;844pCaps->MaxVertexBlendMatrices = 4; /* 1 vec4 BLENDWEIGHT/INDICES input */845pCaps->MaxVertexBlendMatrixIndex = 8; /* D3DTS_WORLDMATRIX(0..8) */846847pCaps->MaxPointSize = screen->get_paramf(screen, PIPE_CAPF_MAX_POINT_WIDTH);848849pCaps->MaxPrimitiveCount = 0x555555; /* <- wine, really 0xFFFFFFFF; */850pCaps->MaxVertexIndex = 0xFFFFFF; /* <- wine, really 0xFFFFFFFF */851pCaps->MaxStreams =852_min(screen->get_shader_param(screen,853PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_MAX_INPUTS),85416);855856pCaps->MaxStreamStride = screen->get_param(screen,857PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE);858859pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);860861/* VS 2 as well as 3.0 supports a minimum of 256 consts.862* Wine and d3d9 drivers for dx1x hw advertise 256. Just as them,863* advertise 256. Problem is with hw that can only do 256, because864* we need take a few slots for boolean and integer constants. For these865* we'll have to fail later if they use complex shaders. */866pCaps->MaxVertexShaderConst = NINE_MAX_CONST_F;867868pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);869/* Value for GeForce 9600 GT */870pCaps->PixelShader1xMaxValue = 65504.f;871872pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET |873D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET |874D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES |875/*D3DDEVCAPS2_DMAPNPATCH |*/876/*D3DDEVCAPS2_ADAPTIVETESSRTPATCH |*/877/*D3DDEVCAPS2_ADAPTIVETESSNPATCH |*/878/*D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH*/0;879880pCaps->MasterAdapterOrdinal = 0;881pCaps->AdapterOrdinalInGroup = 0;882pCaps->NumberOfAdaptersInGroup = 1;883884/* Undocumented ? */885pCaps->MaxNpatchTessellationLevel = 0.0f;886pCaps->Reserved5 = 0;887888/* XXX: use is_format_supported */889pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |890D3DDTCAPS_UBYTE4N |891D3DDTCAPS_SHORT2N |892D3DDTCAPS_SHORT4N |893D3DDTCAPS_USHORT2N |894D3DDTCAPS_USHORT4N |895D3DDTCAPS_UDEC3 |896D3DDTCAPS_DEC3N |897D3DDTCAPS_FLOAT16_2 |898D3DDTCAPS_FLOAT16_4;899900pCaps->NumSimultaneousRTs =901screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS);902if (pCaps->NumSimultaneousRTs > NINE_MAX_SIMULTANEOUS_RENDERTARGETS)903pCaps->NumSimultaneousRTs = NINE_MAX_SIMULTANEOUS_RENDERTARGETS;904905pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT |906D3DPTFILTERCAPS_MINFLINEAR |907D3DPTFILTERCAPS_MAGFPOINT |908D3DPTFILTERCAPS_MAGFLINEAR;909910911pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;912pCaps->VS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */913screen->get_shader_param(screen, PIPE_SHADER_VERTEX,914PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);915pCaps->VS20Caps.NumTemps =916screen->get_shader_param(screen, PIPE_SHADER_VERTEX,917PIPE_SHADER_CAP_MAX_TEMPS);918pCaps->VS20Caps.StaticFlowControlDepth = /* XXX is this static ? */919screen->get_shader_param(screen, PIPE_SHADER_VERTEX,920PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);921922/* also check for values < 0, because get_shader_param may return unsigned */923if (pCaps->VS20Caps.DynamicFlowControlDepth > D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH924|| pCaps->VS20Caps.DynamicFlowControlDepth < 0)925pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH;926if (pCaps->VS20Caps.StaticFlowControlDepth > D3DVS20_MAX_STATICFLOWCONTROLDEPTH927|| pCaps->VS20Caps.StaticFlowControlDepth < 0)928pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH;929if (pCaps->VS20Caps.NumTemps > D3DVS20_MAX_NUMTEMPS)930pCaps->VS20Caps.NumTemps = D3DVS20_MAX_NUMTEMPS;931assert(pCaps->VS20Caps.DynamicFlowControlDepth >= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH);932assert(pCaps->VS20Caps.StaticFlowControlDepth >= D3DVS20_MIN_STATICFLOWCONTROLDEPTH);933assert(pCaps->VS20Caps.NumTemps >= D3DVS20_MIN_NUMTEMPS);934935936pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |937D3DPS20CAPS_GRADIENTINSTRUCTIONS |938D3DPS20CAPS_PREDICATION;939if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,940PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==941screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,942PIPE_SHADER_CAP_MAX_INSTRUCTIONS))943pCaps->PS20Caps.Caps |= D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;944if (screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,945PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS) ==946screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,947PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS))948pCaps->PS20Caps.Caps |= D3DPS20CAPS_NODEPENDENTREADLIMIT;949pCaps->PS20Caps.DynamicFlowControlDepth = /* XXX is this dynamic ? */950screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,951PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);952pCaps->PS20Caps.NumTemps =953screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,954PIPE_SHADER_CAP_MAX_TEMPS);955pCaps->PS20Caps.StaticFlowControlDepth = /* XXX is this static ? */956screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,957PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);958pCaps->PS20Caps.NumInstructionSlots =959screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,960PIPE_SHADER_CAP_MAX_INSTRUCTIONS);961962if (pCaps->PS20Caps.DynamicFlowControlDepth > D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH963|| pCaps->PS20Caps.DynamicFlowControlDepth < 0)964pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH;965if (pCaps->PS20Caps.StaticFlowControlDepth > D3DPS20_MAX_STATICFLOWCONTROLDEPTH966|| pCaps->PS20Caps.StaticFlowControlDepth < 0)967pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH;968if (pCaps->PS20Caps.NumTemps > D3DPS20_MAX_NUMTEMPS)969pCaps->PS20Caps.NumTemps = D3DPS20_MAX_NUMTEMPS;970if (pCaps->PS20Caps.NumInstructionSlots > D3DPS20_MAX_NUMINSTRUCTIONSLOTS)971pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS;972assert(pCaps->PS20Caps.DynamicFlowControlDepth >= D3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH);973assert(pCaps->PS20Caps.StaticFlowControlDepth >= D3DPS20_MIN_STATICFLOWCONTROLDEPTH);974assert(pCaps->PS20Caps.NumTemps >= D3DPS20_MIN_NUMTEMPS);975assert(pCaps->PS20Caps.NumInstructionSlots >= D3DPS20_MIN_NUMINSTRUCTIONSLOTS);976977978if (screen->get_shader_param(screen, PIPE_SHADER_VERTEX,979PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS))980pCaps->VertexTextureFilterCaps = pCaps->TextureFilterCaps &981~(D3DPTFILTERCAPS_MIPFPOINT |982D3DPTFILTERCAPS_MIPFPOINT); /* XXX */983else984pCaps->VertexTextureFilterCaps = 0;985986pCaps->MaxVertexShader30InstructionSlots =987screen->get_shader_param(screen, PIPE_SHADER_VERTEX,988PIPE_SHADER_CAP_MAX_INSTRUCTIONS);989pCaps->MaxPixelShader30InstructionSlots =990screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT,991PIPE_SHADER_CAP_MAX_INSTRUCTIONS);992if (pCaps->MaxVertexShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)993pCaps->MaxVertexShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;994if (pCaps->MaxPixelShader30InstructionSlots > D3DMAX30SHADERINSTRUCTIONS)995pCaps->MaxPixelShader30InstructionSlots = D3DMAX30SHADERINSTRUCTIONS;996assert(pCaps->MaxVertexShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);997assert(pCaps->MaxPixelShader30InstructionSlots >= D3DMIN30SHADERINSTRUCTIONS);998999/* 65535 is required, advertise more for GPUs with >= 2048 instruction slots */1000pCaps->MaxVShaderInstructionsExecuted = MAX2(65535, pCaps->MaxVertexShader30InstructionSlots * 32);1001pCaps->MaxPShaderInstructionsExecuted = MAX2(65535, pCaps->MaxPixelShader30InstructionSlots * 32);10021003if (debug_get_bool_option("NINE_DUMP_CAPS", FALSE))1004nine_dump_D3DCAPS9(DBG_CHANNEL, pCaps);10051006return D3D_OK;1007}10081009HRESULT NINE_WINAPI1010NineAdapter9_CreateDevice( struct NineAdapter9 *This,1011UINT RealAdapter,1012D3DDEVTYPE DeviceType,1013HWND hFocusWindow,1014DWORD BehaviorFlags,1015D3DPRESENT_PARAMETERS *pPresentationParameters,1016IDirect3D9 *pD3D9,1017ID3DPresentGroup *pPresentationGroup,1018IDirect3DDevice9 **ppReturnedDeviceInterface )1019{1020struct pipe_screen *screen;1021D3DDEVICE_CREATION_PARAMETERS params;1022D3DCAPS9 caps;1023int major, minor;1024HRESULT hr;10251026DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "1027"BehaviourFlags=%x " "pD3D9=%p pPresentationGroup=%p "1028"ppReturnedDeviceInterface=%p\n", This,1029RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,1030BehaviorFlags, pD3D9, pPresentationGroup, ppReturnedDeviceInterface);10311032ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);1033if (major != 1) {1034ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",1035major, minor);1036return D3DERR_NOTAVAILABLE;1037}10381039hr = NineAdapter9_GetScreen(This, DeviceType, &screen);1040if (FAILED(hr)) {1041DBG("Failed to get pipe_screen.\n");1042return hr;1043}10441045hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);1046if (FAILED(hr)) {1047DBG("Failed to get device caps.\n");1048return hr;1049}10501051params.AdapterOrdinal = RealAdapter;1052params.DeviceType = DeviceType;1053params.hFocusWindow = hFocusWindow;1054params.BehaviorFlags = BehaviorFlags;10551056hr = NineDevice9_new(screen, ¶ms, &caps, pPresentationParameters,1057pD3D9, pPresentationGroup, This->ctx, FALSE, NULL,1058(struct NineDevice9 **)ppReturnedDeviceInterface,1059minor);1060if (FAILED(hr)) {1061DBG("Failed to create device.\n");1062return hr;1063}1064DBG("NineDevice9 created successfully.\n");10651066return D3D_OK;1067}10681069HRESULT NINE_WINAPI1070NineAdapter9_CreateDeviceEx( struct NineAdapter9 *This,1071UINT RealAdapter,1072D3DDEVTYPE DeviceType,1073HWND hFocusWindow,1074DWORD BehaviorFlags,1075D3DPRESENT_PARAMETERS *pPresentationParameters,1076D3DDISPLAYMODEEX *pFullscreenDisplayMode,1077IDirect3D9Ex *pD3D9Ex,1078ID3DPresentGroup *pPresentationGroup,1079IDirect3DDevice9Ex **ppReturnedDeviceInterface )1080{1081struct pipe_screen *screen;1082D3DDEVICE_CREATION_PARAMETERS params;1083D3DCAPS9 caps;1084int major, minor;1085HRESULT hr;10861087DBG("This=%p RealAdapter=%u DeviceType=%s hFocusWindow=%p "1088"BehaviourFlags=%x " "pD3D9Ex=%p pPresentationGroup=%p "1089"ppReturnedDeviceInterface=%p\n", This,1090RealAdapter, nine_D3DDEVTYPE_to_str(DeviceType), hFocusWindow,1091BehaviorFlags, pD3D9Ex, pPresentationGroup, ppReturnedDeviceInterface);10921093ID3DPresentGroup_GetVersion(pPresentationGroup, &major, &minor);1094if (major != 1) {1095ERR("Doesn't support the ID3DPresentGroup version %d %d. Expected 1\n",1096major, minor);1097return D3DERR_NOTAVAILABLE;1098}10991100hr = NineAdapter9_GetScreen(This, DeviceType, &screen);1101if (FAILED(hr)) {1102DBG("Failed to get pipe_screen.\n");1103return hr;1104}11051106hr = NineAdapter9_GetDeviceCaps(This, DeviceType, &caps);1107if (FAILED(hr)) {1108DBG("Failed to get device caps.\n");1109return hr;1110}11111112params.AdapterOrdinal = RealAdapter;1113params.DeviceType = DeviceType;1114params.hFocusWindow = hFocusWindow;1115params.BehaviorFlags = BehaviorFlags;11161117hr = NineDevice9Ex_new(screen, ¶ms, &caps, pPresentationParameters,1118pFullscreenDisplayMode,1119pD3D9Ex, pPresentationGroup, This->ctx,1120(struct NineDevice9Ex **)ppReturnedDeviceInterface,1121minor);1122if (FAILED(hr)) {1123DBG("Failed to create device.\n");1124return hr;1125}1126DBG("NineDevice9Ex created successfully.\n");11271128return D3D_OK;1129}11301131ID3DAdapter9Vtbl NineAdapter9_vtable = {1132(void *)NineUnknown_QueryInterface,1133(void *)NineUnknown_AddRef,1134(void *)NineUnknown_Release,1135(void *)NineAdapter9_GetAdapterIdentifier,1136(void *)NineAdapter9_CheckDeviceType,1137(void *)NineAdapter9_CheckDeviceFormat,1138(void *)NineAdapter9_CheckDeviceMultiSampleType,1139(void *)NineAdapter9_CheckDepthStencilMatch,1140(void *)NineAdapter9_CheckDeviceFormatConversion,1141(void *)NineAdapter9_GetDeviceCaps,1142(void *)NineAdapter9_CreateDevice,1143(void *)NineAdapter9_CreateDeviceEx1144};11451146static const GUID *NineAdapter9_IIDs[] = {1147&IID_ID3D9Adapter,1148&IID_IUnknown,1149NULL1150};11511152HRESULT1153NineAdapter9_new( struct d3dadapter9_context *pCTX,1154struct NineAdapter9 **ppOut )1155{1156NINE_NEW(Adapter9, ppOut, FALSE, /* args */ pCTX);1157}115811591160