Path: blob/21.2-virgl/src/gallium/frontends/nine/device9.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 "device9.h"23#include "stateblock9.h"24#include "surface9.h"25#include "swapchain9.h"26#include "swapchain9ex.h"27#include "indexbuffer9.h"28#include "vertexbuffer9.h"29#include "vertexdeclaration9.h"30#include "vertexshader9.h"31#include "pixelshader9.h"32#include "query9.h"33#include "texture9.h"34#include "cubetexture9.h"35#include "volumetexture9.h"36#include "nine_buffer_upload.h"37#include "nine_helpers.h"38#include "nine_memory_helper.h"39#include "nine_pipe.h"40#include "nine_ff.h"41#include "nine_dump.h"42#include "nine_limits.h"4344#include "pipe/p_screen.h"45#include "pipe/p_context.h"46#include "pipe/p_config.h"47#include "util/macros.h"48#include "util/u_math.h"49#include "util/u_inlines.h"50#include "util/u_hash_table.h"51#include "util/format/u_format.h"52#include "util/u_surface.h"53#include "util/u_upload_mgr.h"54#include "hud/hud_context.h"55#include "compiler/glsl_types.h"5657#include "cso_cache/cso_context.h"5859#define DBG_CHANNEL DBG_DEVICE6061#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))6263static void nine_setup_fpu()64{65uint16_t c;6667__asm__ __volatile__ ("fnstcw %0" : "=m" (*&c));6869/* clear the control word */70c &= 0xF0C0;71/* d3d9 doc/wine tests: mask all exceptions, use single-precision72* and round to nearest */73c |= 0x003F;7475__asm__ __volatile__ ("fldcw %0" : : "m" (*&c));76}7778static void nine_setup_set_fpu(uint16_t val)79{80__asm__ __volatile__ ("fldcw %0" : : "m" (*&val));81}8283static uint16_t nine_setup_get_fpu()84{85uint16_t c;8687__asm__ __volatile__ ("fnstcw %0" : "=m" (*&c));88return c;89}9091#else9293static void nine_setup_fpu(void)94{95WARN_ONCE("FPU setup not supported on non-x86 platforms\n");96}9798static void nine_setup_set_fpu(UNUSED uint16_t val)99{100WARN_ONCE("FPU setup not supported on non-x86 platforms\n");101}102103static uint16_t nine_setup_get_fpu()104{105WARN_ONCE("FPU setup not supported on non-x86 platforms\n");106return 0;107}108109#endif110111struct pipe_resource *112nine_resource_create_with_retry( struct NineDevice9 *This,113struct pipe_screen *screen,114const struct pipe_resource *templat )115{116struct pipe_resource *res;117res = screen->resource_create(screen, templat);118if (res)119return res;120/* Allocation failed, retry after freeing some resources121* Note: Shouldn't be called from the worker thread */122if (!This)123return NULL;124/* Evict resources we can evict */125NineDevice9_EvictManagedResourcesInternal(This);126/* Execute anything pending, such that some127* deleted resources can be actually freed */128nine_csmt_process(This);129/* We could also finish the context, if needed */130return screen->resource_create(screen, templat);131}132133void134NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )135{136struct NineSurface9 *refSurf = NULL;137138DBG("This=%p is_reset=%d\n", This, (int) is_reset);139140assert(!This->is_recording);141142nine_state_set_defaults(This, &This->caps, is_reset);143144refSurf = This->swapchains[0]->buffers[0];145assert(refSurf);146147This->state.viewport.X = 0;148This->state.viewport.Y = 0;149This->state.viewport.Width = refSurf->desc.Width;150This->state.viewport.Height = refSurf->desc.Height;151152nine_context_set_viewport(This, &This->state.viewport);153154This->state.scissor.minx = 0;155This->state.scissor.miny = 0;156This->state.scissor.maxx = refSurf->desc.Width;157This->state.scissor.maxy = refSurf->desc.Height;158159nine_context_set_scissor(This, &This->state.scissor);160161if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) {162nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE);163This->state.rs_advertised[D3DRS_ZENABLE] = TRUE;164}165if (This->state.rs_advertised[D3DRS_ZENABLE])166NineDevice9_SetDepthStencilSurface(167This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);168}169170#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)171HRESULT172NineDevice9_ctor( struct NineDevice9 *This,173struct NineUnknownParams *pParams,174struct pipe_screen *pScreen,175D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,176D3DCAPS9 *pCaps,177D3DPRESENT_PARAMETERS *pPresentationParameters,178IDirect3D9 *pD3D9,179ID3DPresentGroup *pPresentationGroup,180struct d3dadapter9_context *pCTX,181boolean ex,182D3DDISPLAYMODEEX *pFullscreenDisplayMode,183int minorVersionNum )184{185unsigned i;186uint16_t fpu_cw = 0;187HRESULT hr = NineUnknown_ctor(&This->base, pParams);188189DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "190"pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",191This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9,192pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode);193194if (FAILED(hr)) { return hr; }195196/* NIR shaders need to use GLSL types so let's initialize them here */197glsl_type_singleton_init_or_ref();198199list_inithead(&This->update_buffers);200list_inithead(&This->update_textures);201list_inithead(&This->managed_buffers);202list_inithead(&This->managed_textures);203204This->screen = pScreen;205This->screen_sw = pCTX->ref;206This->caps = *pCaps;207This->d3d9 = pD3D9;208This->params = *pCreationParameters;209This->ex = ex;210This->present = pPresentationGroup;211This->minor_version_num = minorVersionNum;212213/* Ex */214This->gpu_priority = 0;215This->max_frame_latency = 3;216217IDirect3D9_AddRef(This->d3d9);218ID3DPresentGroup_AddRef(This->present);219220if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)) {221nine_setup_fpu();222} else {223/* Software renderer initialization needs exceptions masked */224fpu_cw = nine_setup_get_fpu();225nine_setup_set_fpu(fpu_cw | 0x007f);226}227228if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) {229DBG("Application asked full Software Vertex Processing.\n");230This->swvp = true;231This->may_swvp = true;232} else233This->swvp = false;234if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) {235DBG("Application asked mixed Software Vertex Processing.\n");236This->may_swvp = true;237}238This->context.swvp = This->swvp;239/* TODO: check if swvp is resetted by device Resets */240241if (This->may_swvp &&242(This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX,243PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE)244< (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) ||245This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX,246PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) {247/* Note: We just go on, some apps never use the abilities of248* swvp, and just set more constants than allowed at init.249* Only cards we support that are affected are the r500 */250WARN("Card unable to handle Software Vertex Processing. Game may fail\n");251}252253/* When may_swvp, SetConstant* limits are different */254if (This->may_swvp)255This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP;256257This->pure = !!(This->params.BehaviorFlags & D3DCREATE_PUREDEVICE);258259This->context.pipe = This->screen->context_create(This->screen, NULL, 0);260This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0);261if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */262This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0);263if (!This->pipe_sw) { return E_OUTOFMEMORY; }264265This->context.cso = cso_create_context(This->context.pipe, 0);266if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */267This->cso_sw = cso_create_context(This->pipe_sw, 0);268if (!This->cso_sw) { return E_OUTOFMEMORY; }269270/* Create first, it messes up our state. */271This->hud = hud_create(This->context.cso, NULL, NULL); /* NULL result is fine */272273This->allocator = nine_allocator_create(This, pCTX->memfd_virtualsizelimit);274275/* Available memory counter. Updated only for allocations with this device276* instance. This is the Win 7 behavior.277* Win XP shares this counter across multiple devices. */278This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY);279This->available_texture_mem = (pCTX->override_vram_size >= 0) ?280(long long)pCTX->override_vram_size : This->available_texture_mem;281This->available_texture_mem <<= 20;282283/* We cap texture memory usage to 95% of what is reported free initially284* This helps get closer Win behaviour. For example VertexBuffer allocation285* still succeeds when texture allocation fails. */286This->available_texture_limit = This->available_texture_mem * 5LL / 100LL;287288This->frame_count = 0; /* Used to check if events occur the same frame */289290/* create implicit swapchains */291This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present);292This->swapchains = CALLOC(This->nswapchains,293sizeof(struct NineSwapChain9 *));294if (!This->swapchains) { return E_OUTOFMEMORY; }295296for (i = 0; i < This->nswapchains; ++i) {297ID3DPresent *present;298299hr = ID3DPresentGroup_GetPresent(This->present, i, &present);300if (FAILED(hr))301return hr;302303if (ex) {304D3DDISPLAYMODEEX *mode = NULL;305struct NineSwapChain9Ex **ret =306(struct NineSwapChain9Ex **)&This->swapchains[i];307308if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);309/* when this is a Device9Ex, it should create SwapChain9Exs */310hr = NineSwapChain9Ex_new(This, TRUE, present,311&pPresentationParameters[i], pCTX,312This->params.hFocusWindow, mode, ret);313} else {314hr = NineSwapChain9_new(This, TRUE, present,315&pPresentationParameters[i], pCTX,316This->params.hFocusWindow,317&This->swapchains[i]);318}319320ID3DPresent_Release(present);321if (FAILED(hr))322return hr;323NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i]));324325hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0,326D3DBACKBUFFER_TYPE_MONO,327(IDirect3DSurface9 **)328&This->state.rt[i]);329if (FAILED(hr))330return hr;331NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));332nine_bind(&This->context.rt[i], This->state.rt[i]);333}334335/* Initialize CSMT */336/* r600, radeonsi and iris are thread safe. */337if (pCTX->csmt_force == 1)338This->csmt_active = true;339else if (pCTX->csmt_force == 0)340This->csmt_active = false;341else if (strstr(pScreen->get_name(pScreen), "AMD") != NULL)342This->csmt_active = true;343else if (strstr(pScreen->get_name(pScreen), "Intel") != NULL)344This->csmt_active = true;345346/* We rely on u_upload_mgr using persistent coherent buffers (which don't347* require flush to work in multi-pipe_context scenario) for vertex and348* index buffers */349if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT))350This->csmt_active = false;351352if (This->csmt_active) {353This->csmt_ctx = nine_csmt_create(This);354if (!This->csmt_ctx)355return E_OUTOFMEMORY;356}357358if (This->csmt_active)359DBG("\033[1;32mCSMT is active\033[0m\n");360361This->workarounds.dynamic_texture_workaround = pCTX->dynamic_texture_workaround;362363/* Due to the pb_cache, in some cases the buffer_upload path can increase GTT usage/virtual memory.364* As the performance gain is negligible when csmt is off, disable it in this case.365* That way csmt_force=0 can be used as a workaround to reduce GTT usage/virtual memory. */366This->buffer_upload = This->csmt_active ? nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4) : NULL;367368/* Initialize a dummy VBO to be used when a vertex declaration does not369* specify all the inputs needed by vertex shader, on win default behavior370* is to pass 0,0,0,0 to the shader */371{372struct pipe_transfer *transfer;373struct pipe_resource tmpl;374struct pipe_box box;375unsigned char *data;376377memset(&tmpl, 0, sizeof(tmpl));378tmpl.target = PIPE_BUFFER;379tmpl.format = PIPE_FORMAT_R8_UNORM;380tmpl.width0 = 16; /* 4 floats */381tmpl.height0 = 1;382tmpl.depth0 = 1;383tmpl.array_size = 1;384tmpl.last_level = 0;385tmpl.nr_samples = 0;386tmpl.usage = PIPE_USAGE_DEFAULT;387tmpl.bind = PIPE_BIND_VERTEX_BUFFER;388tmpl.flags = 0;389This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl);390391if (!This->dummy_vbo)392return D3DERR_OUTOFVIDEOMEMORY;393394u_box_1d(0, 16, &box);395data = This->context.pipe->buffer_map(This->context.pipe, This->dummy_vbo, 0,396PIPE_MAP_WRITE |397PIPE_MAP_DISCARD_WHOLE_RESOURCE,398&box, &transfer);399assert(data);400assert(transfer);401memset(data, 0, 16);402This->context.pipe->buffer_unmap(This->context.pipe, transfer);403}404405This->cursor.software = FALSE;406This->cursor.hotspot.x = -1;407This->cursor.hotspot.y = -1;408This->cursor.w = This->cursor.h = 0;409This->cursor.visible = FALSE;410if (ID3DPresent_GetCursorPos(This->swapchains[0]->present, &This->cursor.pos) != S_OK) {411This->cursor.pos.x = 0;412This->cursor.pos.y = 0;413}414415{416struct pipe_resource tmpl;417memset(&tmpl, 0, sizeof(tmpl));418tmpl.target = PIPE_TEXTURE_2D;419tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM;420tmpl.width0 = 64;421tmpl.height0 = 64;422tmpl.depth0 = 1;423tmpl.array_size = 1;424tmpl.last_level = 0;425tmpl.nr_samples = 0;426tmpl.usage = PIPE_USAGE_DEFAULT;427tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW;428tmpl.flags = 0;429430This->cursor.image = pScreen->resource_create(pScreen, &tmpl);431if (!This->cursor.image)432return D3DERR_OUTOFVIDEOMEMORY;433434/* For uploading 32x32 (argb) cursor */435This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32);436if (!This->cursor.hw_upload_temp)437return D3DERR_OUTOFVIDEOMEMORY;438}439440/* Create constant buffers. */441{442unsigned max_const_vs, max_const_ps;443444/* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,445* we have to take in some more slots for int and bool*/446max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,447PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /448sizeof(float[4]),449NINE_MAX_CONST_ALL);450/* ps 3.0: 224 float constants. All cards supported support at least451* 256 constants for ps */452max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);453454This->max_vs_const_f = max_const_vs -455(NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);456This->max_ps_const_f = max_const_ps -457(NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);458459This->vs_const_size = max_const_vs * sizeof(float[4]);460This->ps_const_size = max_const_ps * sizeof(float[4]);461/* Include space for I,B constants for user constbuf. */462if (This->may_swvp) {463This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);464This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);465if (!This->context.vs_const_f_swvp)466return E_OUTOFMEMORY;467This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);468This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);469This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1);470This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1);471This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1);472This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1);473} else {474This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1);475This->context.vs_const_f_swvp = NULL;476This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1);477This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1);478This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1);479This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1);480This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1);481This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1);482}483This->context.vs_const_f = CALLOC(This->vs_const_size, 1);484This->state.ps_const_f = CALLOC(This->ps_const_size, 1);485This->context.ps_const_f = CALLOC(This->ps_const_size, 1);486This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1);487if (!This->state.vs_const_f || !This->context.vs_const_f ||488!This->state.ps_const_f || !This->context.ps_const_f ||489!This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp ||490!This->context.ps_lconstf_temp ||491!This->state.vs_const_i || !This->context.vs_const_i ||492!This->state.vs_const_b || !This->context.vs_const_b)493return E_OUTOFMEMORY;494495if (strstr(pScreen->get_name(pScreen), "AMD") ||496strstr(pScreen->get_name(pScreen), "ATI")) {497This->driver_bugs.buggy_barycentrics = TRUE;498}499}500501/* allocate dummy texture/sampler for when there are missing ones bound */502{503struct pipe_resource tmplt;504struct pipe_sampler_view templ;505struct pipe_sampler_state samp;506memset(&tmplt, 0, sizeof(tmplt));507memset(&samp, 0, sizeof(samp));508509tmplt.target = PIPE_TEXTURE_2D;510tmplt.width0 = 1;511tmplt.height0 = 1;512tmplt.depth0 = 1;513tmplt.last_level = 0;514tmplt.array_size = 1;515tmplt.usage = PIPE_USAGE_DEFAULT;516tmplt.flags = 0;517tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM;518tmplt.bind = PIPE_BIND_SAMPLER_VIEW;519tmplt.nr_samples = 0;520521This->dummy_texture = This->screen->resource_create(This->screen, &tmplt);522if (!This->dummy_texture)523return D3DERR_DRIVERINTERNALERROR;524525templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;526templ.u.tex.first_layer = 0;527templ.u.tex.last_layer = 0;528templ.u.tex.first_level = 0;529templ.u.tex.last_level = 0;530templ.swizzle_r = PIPE_SWIZZLE_0;531templ.swizzle_g = PIPE_SWIZZLE_0;532templ.swizzle_b = PIPE_SWIZZLE_0;533templ.swizzle_a = PIPE_SWIZZLE_1;534templ.target = This->dummy_texture->target;535536This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ);537if (!This->dummy_sampler_view)538return D3DERR_DRIVERINTERNALERROR;539540samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;541samp.max_lod = 15.0f;542samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;543samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;544samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;545samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;546samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;547samp.compare_mode = PIPE_TEX_COMPARE_NONE;548samp.compare_func = PIPE_FUNC_LEQUAL;549samp.normalized_coords = 1;550samp.seamless_cube_map = 0;551This->dummy_sampler_state = samp;552}553554/* Allocate upload helper for drivers that suck (from st pov ;). */555556This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS);557This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader;558This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);559This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS);560This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS);561This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED);562563This->context.inline_constants = pCTX->shader_inline_constants;564/* Code would be needed when integers are not available to correctly565* handle the conversion of integer constants */566This->context.inline_constants &= This->driver_caps.vs_integer && This->driver_caps.ps_integer;567568nine_ff_init(This); /* initialize fixed function code */569570NineDevice9_SetDefaultState(This, FALSE);571572{573struct pipe_poly_stipple stipple;574memset(&stipple, ~0, sizeof(stipple));575This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple);576}577578This->update = &This->state;579580nine_state_init_sw(This);581582ID3DPresentGroup_Release(This->present);583nine_context_update_state(This); /* Some drivers needs states to be initialized */584nine_csmt_process(This);585586if (This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)587nine_setup_set_fpu(fpu_cw);588589return D3D_OK;590}591#undef GET_PCAP592593void594NineDevice9_dtor( struct NineDevice9 *This )595{596unsigned i;597598DBG("This=%p\n", This);599600/* Flush all pending commands to get refcount right,601* and properly release bound objects. It is ok to still602* execute commands while we are in device dtor, because603* we haven't released anything yet. Note that no pending604* command can increase the device refcount. */605if (This->csmt_active && This->csmt_ctx) {606nine_csmt_process(This);607nine_csmt_destroy(This, This->csmt_ctx);608This->csmt_active = FALSE;609This->csmt_ctx = NULL;610}611612nine_ff_fini(This);613nine_state_destroy_sw(This);614nine_device_state_clear(This);615nine_context_clear(This);616617nine_bind(&This->record, NULL);618619pipe_sampler_view_reference(&This->dummy_sampler_view, NULL);620pipe_resource_reference(&This->dummy_texture, NULL);621pipe_resource_reference(&This->dummy_vbo, NULL);622FREE(This->state.vs_const_f);623FREE(This->context.vs_const_f);624FREE(This->state.ps_const_f);625FREE(This->context.ps_const_f);626FREE(This->state.vs_lconstf_temp);627FREE(This->context.vs_lconstf_temp);628FREE(This->context.ps_lconstf_temp);629FREE(This->state.vs_const_i);630FREE(This->context.vs_const_i);631FREE(This->state.vs_const_b);632FREE(This->context.vs_const_b);633FREE(This->context.vs_const_f_swvp);634635pipe_resource_reference(&This->cursor.image, NULL);636FREE(This->cursor.hw_upload_temp);637638if (This->swapchains) {639for (i = 0; i < This->nswapchains; ++i)640if (This->swapchains[i])641NineUnknown_Unbind(NineUnknown(This->swapchains[i]));642FREE(This->swapchains);643}644645if (This->buffer_upload)646nine_upload_destroy(This->buffer_upload);647648if (This->allocator)649nine_allocator_destroy(This->allocator);650651/* Destroy cso first */652if (This->context.cso) { cso_destroy_context(This->context.cso); }653if (This->cso_sw) { cso_destroy_context(This->cso_sw); }654if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); }655if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); }656if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); }657658if (This->present) { ID3DPresentGroup_Release(This->present); }659if (This->d3d9) { IDirect3D9_Release(This->d3d9); }660661NineUnknown_dtor(&This->base);662glsl_type_singleton_decref();663}664665struct pipe_screen *666NineDevice9_GetScreen( struct NineDevice9 *This )667{668return This->screen;669}670671struct pipe_context *672NineDevice9_GetPipe( struct NineDevice9 *This )673{674return nine_context_get_pipe(This);675}676677const D3DCAPS9 *678NineDevice9_GetCaps( struct NineDevice9 *This )679{680return &This->caps;681}682683static inline void684NineDevice9_PauseRecording( struct NineDevice9 *This )685{686if (This->record) {687This->update = &This->state;688This->is_recording = FALSE;689}690}691692static inline void693NineDevice9_ResumeRecording( struct NineDevice9 *This )694{695if (This->record) {696This->update = &This->record->state;697This->is_recording = TRUE;698}699}700701HRESULT NINE_WINAPI702NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )703{704if (NineSwapChain9_GetOccluded(This->swapchains[0])) {705This->device_needs_reset = TRUE;706return D3DERR_DEVICELOST;707} else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) {708This->device_needs_reset = TRUE;709return D3DERR_DEVICENOTRESET;710} else if (This->device_needs_reset) {711return D3DERR_DEVICENOTRESET;712}713714return D3D_OK;715}716717UINT NINE_WINAPI718NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )719{720/* To prevent overflows - Not sure how this should be handled */721return (UINT)MIN2(This->available_texture_mem, (long long)(UINT_MAX - (64 << 20))); /* 64 MB margin */722}723724void725NineDevice9_EvictManagedResourcesInternal( struct NineDevice9 *This )726{727struct NineBaseTexture9 *tex;728729DBG("This=%p\n", This);730731/* This function is called internally when an allocation fails.732* We are supposed to release old unused managed textures/buffers,733* until we have enough space for the allocation.734* For now just release everything, except the bound textures,735* as this function can be called when uploading bound textures.736*/737LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) {738if (!tex->bind_count)739NineBaseTexture9_UnLoad(tex);740}741}742743HRESULT NINE_WINAPI744NineDevice9_EvictManagedResources( struct NineDevice9 *This )745{746struct NineBaseTexture9 *tex;747struct NineBuffer9 *buf;748749DBG("This=%p\n", This);750LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) {751NineBaseTexture9_UnLoad(tex);752}753/* Vertex/index buffers don't take a lot of space and aren't accounted754* for d3d memory usage. Instead of actually freeing from memory,755* just mark the buffer dirty to trigger a re-upload later. We756* could just ignore, but some bad behaving apps could rely on it (if757* they write outside the locked regions typically). */758LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) {759NineBuffer9_SetDirty(buf);760}761762return D3D_OK;763}764765HRESULT NINE_WINAPI766NineDevice9_GetDirect3D( struct NineDevice9 *This,767IDirect3D9 **ppD3D9 )768{769user_assert(ppD3D9 != NULL, E_POINTER);770IDirect3D9_AddRef(This->d3d9);771*ppD3D9 = This->d3d9;772return D3D_OK;773}774775HRESULT NINE_WINAPI776NineDevice9_GetDeviceCaps( struct NineDevice9 *This,777D3DCAPS9 *pCaps )778{779user_assert(pCaps != NULL, D3DERR_INVALIDCALL);780*pCaps = This->caps;781return D3D_OK;782}783784HRESULT NINE_WINAPI785NineDevice9_GetDisplayMode( struct NineDevice9 *This,786UINT iSwapChain,787D3DDISPLAYMODE *pMode )788{789DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode);790791user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);792793return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode);794}795796HRESULT NINE_WINAPI797NineDevice9_GetCreationParameters( struct NineDevice9 *This,798D3DDEVICE_CREATION_PARAMETERS *pParameters )799{800user_assert(pParameters != NULL, D3DERR_INVALIDCALL);801*pParameters = This->params;802return D3D_OK;803}804805HRESULT NINE_WINAPI806NineDevice9_SetCursorProperties( struct NineDevice9 *This,807UINT XHotSpot,808UINT YHotSpot,809IDirect3DSurface9 *pCursorBitmap )810{811struct NineSurface9 *surf = NineSurface9(pCursorBitmap);812struct pipe_context *pipe = NineDevice9_GetPipe(This);813struct pipe_box box;814struct pipe_transfer *transfer;815BOOL hw_cursor;816void *ptr;817818DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "819"pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap);820821user_assert(pCursorBitmap, D3DERR_INVALIDCALL);822user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);823824if (This->swapchains[0]->params.Windowed) {825This->cursor.w = MIN2(surf->desc.Width, 32);826This->cursor.h = MIN2(surf->desc.Height, 32);827hw_cursor = 1; /* always use hw cursor for windowed mode */828} else {829This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);830This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);831hw_cursor = This->cursor.w == 32 && This->cursor.h == 32;832}833834u_box_origin_2d(This->cursor.w, This->cursor.h, &box);835836ptr = pipe->texture_map(pipe, This->cursor.image, 0,837PIPE_MAP_WRITE |838PIPE_MAP_DISCARD_WHOLE_RESOURCE,839&box, &transfer);840if (!ptr)841ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR);842843This->cursor.hotspot.x = XHotSpot;844This->cursor.hotspot.y = YHotSpot;845846/* Copy cursor image to internal storage. */847{848D3DLOCKED_RECT lock;849HRESULT hr;850851hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY);852if (FAILED(hr))853ret_err("Failed to map cursor source image.\n",854D3DERR_DRIVERINTERNALERROR);855856util_format_unpack_rgba_8unorm_rect(surf->base.info.format, ptr, transfer->stride,857lock.pBits, lock.Pitch,858This->cursor.w, This->cursor.h);859860if (hw_cursor) {861void *data = lock.pBits;862/* SetCursor assumes 32x32 argb with pitch 128 */863if (lock.Pitch != 128) {864util_format_unpack_rgba_8unorm_rect(surf->base.info.format,865This->cursor.hw_upload_temp, 128,866lock.pBits, lock.Pitch,86732, 32);868data = This->cursor.hw_upload_temp;869}870hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present,871data,872&This->cursor.hotspot,873This->cursor.visible) == D3D_OK;874}875876NineSurface9_UnlockRect(surf);877}878pipe->texture_unmap(pipe, transfer);879880/* hide cursor if we emulate it */881if (!hw_cursor)882ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE);883This->cursor.software = !hw_cursor;884885return D3D_OK;886}887888void NINE_WINAPI889NineDevice9_SetCursorPosition( struct NineDevice9 *This,890int X,891int Y,892DWORD Flags )893{894struct NineSwapChain9 *swap = This->swapchains[0];895896DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags);897898/* present >= v1.4 handles this itself */899if (This->minor_version_num < 4) {900if (This->cursor.pos.x == X && This->cursor.pos.y == Y)901return;902}903904This->cursor.pos.x = X;905This->cursor.pos.y = Y;906907if (!This->cursor.software)908This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK;909}910911BOOL NINE_WINAPI912NineDevice9_ShowCursor( struct NineDevice9 *This,913BOOL bShow )914{915BOOL old = This->cursor.visible;916917DBG("This=%p bShow=%d\n", This, (int) bShow);918919/* No-op until a cursor is set in d3d */920if (This->cursor.hotspot.x == -1)921return old;922923This->cursor.visible = bShow;924/* Note: Don't optimize by avoiding the call if This->cursor.visible925* hasn't changed. One has to keep in mind the app may do SetCursor926* calls outside d3d, thus such an optimization affects behaviour. */927if (!This->cursor.software)928This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;929930return old;931}932933HRESULT NINE_WINAPI934NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,935D3DPRESENT_PARAMETERS *pPresentationParameters,936IDirect3DSwapChain9 **pSwapChain )937{938struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0];939ID3DPresent *present;940HRESULT hr;941942DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",943This, pPresentationParameters, pSwapChain);944945user_assert(pPresentationParameters, D3DERR_INVALIDCALL);946user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);947user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL);948949/* TODO: this deserves more tests */950if (!pPresentationParameters->hDeviceWindow)951pPresentationParameters->hDeviceWindow = This->params.hFocusWindow;952953hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present);954955if (FAILED(hr))956return hr;957958hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters,959tmplt->actx,960tmplt->params.hDeviceWindow,961&swapchain);962if (FAILED(hr))963return hr;964965*pSwapChain = (IDirect3DSwapChain9 *)swapchain;966return D3D_OK;967}968969HRESULT NINE_WINAPI970NineDevice9_GetSwapChain( struct NineDevice9 *This,971UINT iSwapChain,972IDirect3DSwapChain9 **pSwapChain )973{974user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);975976*pSwapChain = NULL;977user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);978979NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain]));980*pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain];981982return D3D_OK;983}984985UINT NINE_WINAPI986NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )987{988return This->nswapchains;989}990991HRESULT NINE_WINAPI992NineDevice9_Reset( struct NineDevice9 *This,993D3DPRESENT_PARAMETERS *pPresentationParameters )994{995HRESULT hr = D3D_OK;996unsigned i;997998DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);9991000user_assert(pPresentationParameters != NULL, D3DERR_INVALIDCALL);10011002if (NineSwapChain9_GetOccluded(This->swapchains[0])) {1003This->device_needs_reset = TRUE;1004return D3DERR_DEVICELOST;1005}10061007for (i = 0; i < This->nswapchains; ++i) {1008D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];1009hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);1010if (hr != D3D_OK)1011break;1012}10131014nine_csmt_process(This);1015nine_device_state_clear(This);1016nine_context_clear(This);10171018NineDevice9_SetDefaultState(This, TRUE);1019NineDevice9_SetRenderTarget(1020This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);1021/* XXX: better use GetBackBuffer here ? */10221023This->device_needs_reset = (hr != D3D_OK);1024return hr;1025}10261027HRESULT NINE_WINAPI1028NineDevice9_Present( struct NineDevice9 *This,1029const RECT *pSourceRect,1030const RECT *pDestRect,1031HWND hDestWindowOverride,1032const RGNDATA *pDirtyRegion )1033{1034unsigned i;1035HRESULT hr;10361037DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",1038This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);10391040/* XXX is this right? */1041for (i = 0; i < This->nswapchains; ++i) {1042hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect,1043hDestWindowOverride, pDirtyRegion, 0);1044if (FAILED(hr)) { return hr; }1045}10461047return D3D_OK;1048}10491050HRESULT NINE_WINAPI1051NineDevice9_GetBackBuffer( struct NineDevice9 *This,1052UINT iSwapChain,1053UINT iBackBuffer,1054D3DBACKBUFFER_TYPE Type,1055IDirect3DSurface9 **ppBackBuffer )1056{1057user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);1058/* return NULL on error */1059*ppBackBuffer = NULL;1060user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);10611062return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain],1063iBackBuffer, Type, ppBackBuffer);1064}10651066HRESULT NINE_WINAPI1067NineDevice9_GetRasterStatus( struct NineDevice9 *This,1068UINT iSwapChain,1069D3DRASTER_STATUS *pRasterStatus )1070{1071user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL);1072user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);10731074return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain],1075pRasterStatus);1076}10771078HRESULT NINE_WINAPI1079NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,1080BOOL bEnableDialogs )1081{1082STUB(D3DERR_INVALIDCALL);1083}10841085void NINE_WINAPI1086NineDevice9_SetGammaRamp( struct NineDevice9 *This,1087UINT iSwapChain,1088DWORD Flags,1089const D3DGAMMARAMP *pRamp )1090{1091DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This,1092iSwapChain, Flags, pRamp);10931094user_warn(iSwapChain >= This->nswapchains);1095user_warn(!pRamp);10961097if (pRamp && (iSwapChain < This->nswapchains)) {1098struct NineSwapChain9 *swap = This->swapchains[iSwapChain];1099swap->gamma = *pRamp;1100ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow);1101}1102}11031104void NINE_WINAPI1105NineDevice9_GetGammaRamp( struct NineDevice9 *This,1106UINT iSwapChain,1107D3DGAMMARAMP *pRamp )1108{1109DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp);11101111user_warn(iSwapChain >= This->nswapchains);1112user_warn(!pRamp);11131114if (pRamp && (iSwapChain < This->nswapchains))1115*pRamp = This->swapchains[iSwapChain]->gamma;1116}11171118HRESULT NINE_WINAPI1119NineDevice9_CreateTexture( struct NineDevice9 *This,1120UINT Width,1121UINT Height,1122UINT Levels,1123DWORD Usage,1124D3DFORMAT Format,1125D3DPOOL Pool,1126IDirect3DTexture9 **ppTexture,1127HANDLE *pSharedHandle )1128{1129struct NineTexture9 *tex;1130HRESULT hr;11311132DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "1133"ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels,1134nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),1135nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle);11361137user_assert(ppTexture != NULL, D3DERR_INVALIDCALL);11381139Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP |1140D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |1141D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI;11421143*ppTexture = NULL;11441145hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool,1146&tex, pSharedHandle);1147if (SUCCEEDED(hr))1148*ppTexture = (IDirect3DTexture9 *)tex;11491150return hr;1151}11521153HRESULT NINE_WINAPI1154NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,1155UINT Width,1156UINT Height,1157UINT Depth,1158UINT Levels,1159DWORD Usage,1160D3DFORMAT Format,1161D3DPOOL Pool,1162IDirect3DVolumeTexture9 **ppVolumeTexture,1163HANDLE *pSharedHandle )1164{1165struct NineVolumeTexture9 *tex;1166HRESULT hr;11671168DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "1169"ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels,1170nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),1171nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle);11721173user_assert(ppVolumeTexture != NULL, D3DERR_INVALIDCALL);11741175Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |1176D3DUSAGE_SOFTWAREPROCESSING;11771178*ppVolumeTexture = NULL;11791180hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels,1181Usage, Format, Pool, &tex, pSharedHandle);1182if (SUCCEEDED(hr))1183*ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex;11841185return hr;1186}11871188HRESULT NINE_WINAPI1189NineDevice9_CreateCubeTexture( struct NineDevice9 *This,1190UINT EdgeLength,1191UINT Levels,1192DWORD Usage,1193D3DFORMAT Format,1194D3DPOOL Pool,1195IDirect3DCubeTexture9 **ppCubeTexture,1196HANDLE *pSharedHandle )1197{1198struct NineCubeTexture9 *tex;1199HRESULT hr;12001201DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "1202"pSharedHandle=%p\n", This, EdgeLength, Levels,1203nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),1204nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle);12051206user_assert(ppCubeTexture != NULL, D3DERR_INVALIDCALL);12071208Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC |1209D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |1210D3DUSAGE_SOFTWAREPROCESSING;12111212*ppCubeTexture = NULL;12131214hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool,1215&tex, pSharedHandle);1216if (SUCCEEDED(hr))1217*ppCubeTexture = (IDirect3DCubeTexture9 *)tex;12181219return hr;1220}12211222HRESULT NINE_WINAPI1223NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,1224UINT Length,1225DWORD Usage,1226DWORD FVF,1227D3DPOOL Pool,1228IDirect3DVertexBuffer9 **ppVertexBuffer,1229HANDLE *pSharedHandle )1230{1231struct NineVertexBuffer9 *buf;1232HRESULT hr;1233D3DVERTEXBUFFER_DESC desc;12341235DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",1236This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);12371238user_assert(ppVertexBuffer != NULL, D3DERR_INVALIDCALL);1239user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);12401241desc.Format = D3DFMT_VERTEXDATA;1242desc.Type = D3DRTYPE_VERTEXBUFFER;1243desc.Usage = Usage &1244(D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |1245D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |1246D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI |1247D3DUSAGE_WRITEONLY);1248desc.Pool = Pool;1249desc.Size = Length;1250desc.FVF = FVF;12511252user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);1253user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);12541255hr = NineVertexBuffer9_new(This, &desc, &buf);1256if (SUCCEEDED(hr))1257*ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf;1258return hr;1259}12601261HRESULT NINE_WINAPI1262NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,1263UINT Length,1264DWORD Usage,1265D3DFORMAT Format,1266D3DPOOL Pool,1267IDirect3DIndexBuffer9 **ppIndexBuffer,1268HANDLE *pSharedHandle )1269{1270struct NineIndexBuffer9 *buf;1271HRESULT hr;1272D3DINDEXBUFFER_DESC desc;12731274DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "1275"pSharedHandle=%p\n", This, Length, Usage,1276d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle);12771278user_assert(ppIndexBuffer != NULL, D3DERR_INVALIDCALL);1279user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);12801281desc.Format = Format;1282desc.Type = D3DRTYPE_INDEXBUFFER;1283desc.Usage = Usage &1284(D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |1285D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |1286D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY);1287desc.Pool = Pool;1288desc.Size = Length;12891290user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);1291user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);12921293hr = NineIndexBuffer9_new(This, &desc, &buf);1294if (SUCCEEDED(hr))1295*ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf;1296return hr;1297}12981299static HRESULT1300create_zs_or_rt_surface(struct NineDevice9 *This,1301unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */1302D3DPOOL Pool,1303UINT Width, UINT Height,1304D3DFORMAT Format,1305D3DMULTISAMPLE_TYPE MultiSample,1306DWORD MultisampleQuality,1307BOOL Discard_or_Lockable,1308IDirect3DSurface9 **ppSurface,1309HANDLE *pSharedHandle)1310{1311struct NineSurface9 *surface;1312HRESULT hr;1313D3DSURFACE_DESC desc;13141315DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "1316"Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",1317This, type, nine_D3DPOOL_to_str(Pool), Width, Height,1318d3dformat_to_string(Format), MultiSample, MultisampleQuality,1319Discard_or_Lockable, ppSurface, pSharedHandle);13201321if (pSharedHandle)1322DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");13231324user_assert(Width && Height, D3DERR_INVALIDCALL);1325user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);13261327desc.Format = Format;1328desc.Type = D3DRTYPE_SURFACE;1329desc.Usage = 0;1330desc.Pool = Pool;1331desc.MultiSampleType = MultiSample;1332desc.MultiSampleQuality = MultisampleQuality;1333desc.Width = Width;1334desc.Height = Height;1335switch (type) {1336case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;1337case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;1338default: assert(type == 2); break;1339}13401341hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface);1342if (SUCCEEDED(hr)) {1343*ppSurface = (IDirect3DSurface9 *)surface;13441345if (surface->base.resource && Discard_or_Lockable && (type != 1))1346surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;1347}13481349return hr;1350}13511352HRESULT NINE_WINAPI1353NineDevice9_CreateRenderTarget( struct NineDevice9 *This,1354UINT Width,1355UINT Height,1356D3DFORMAT Format,1357D3DMULTISAMPLE_TYPE MultiSample,1358DWORD MultisampleQuality,1359BOOL Lockable,1360IDirect3DSurface9 **ppSurface,1361HANDLE *pSharedHandle )1362{1363user_assert(ppSurface != NULL, D3DERR_INVALIDCALL);1364*ppSurface = NULL;1365return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT,1366Width, Height, Format,1367MultiSample, MultisampleQuality,1368Lockable, ppSurface, pSharedHandle);1369}13701371HRESULT NINE_WINAPI1372NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,1373UINT Width,1374UINT Height,1375D3DFORMAT Format,1376D3DMULTISAMPLE_TYPE MultiSample,1377DWORD MultisampleQuality,1378BOOL Discard,1379IDirect3DSurface9 **ppSurface,1380HANDLE *pSharedHandle )1381{1382user_assert(ppSurface != NULL, D3DERR_INVALIDCALL);1383*ppSurface = NULL;1384if (!depth_stencil_format(Format))1385return D3DERR_NOTAVAILABLE;1386return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT,1387Width, Height, Format,1388MultiSample, MultisampleQuality,1389Discard, ppSurface, pSharedHandle);1390}13911392HRESULT NINE_WINAPI1393NineDevice9_UpdateSurface( struct NineDevice9 *This,1394IDirect3DSurface9 *pSourceSurface,1395const RECT *pSourceRect,1396IDirect3DSurface9 *pDestinationSurface,1397const POINT *pDestPoint )1398{1399struct NineSurface9 *dst = NineSurface9(pDestinationSurface);1400struct NineSurface9 *src = NineSurface9(pSourceSurface);1401int copy_width, copy_height;1402RECT destRect;14031404DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "1405"pSourceRect=%p pDestPoint=%p\n", This,1406pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint);1407if (pSourceRect)1408DBG("pSourceRect = (%u,%u)-(%u,%u)\n",1409pSourceRect->left, pSourceRect->top,1410pSourceRect->right, pSourceRect->bottom);1411if (pDestPoint)1412DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);14131414user_assert(dst && src, D3DERR_INVALIDCALL);14151416user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);1417user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);14181419user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);1420user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);14211422user_assert(!src->lock_count, D3DERR_INVALIDCALL);1423user_assert(!dst->lock_count, D3DERR_INVALIDCALL);14241425user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL);1426user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL);14271428if (pSourceRect) {1429copy_width = pSourceRect->right - pSourceRect->left;1430copy_height = pSourceRect->bottom - pSourceRect->top;14311432user_assert(pSourceRect->left >= 0 &&1433copy_width > 0 &&1434pSourceRect->right <= src->desc.Width &&1435pSourceRect->top >= 0 &&1436copy_height > 0 &&1437pSourceRect->bottom <= src->desc.Height,1438D3DERR_INVALIDCALL);1439} else {1440copy_width = src->desc.Width;1441copy_height = src->desc.Height;1442}14431444destRect.right = copy_width;1445destRect.bottom = copy_height;14461447if (pDestPoint) {1448user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0,1449D3DERR_INVALIDCALL);1450destRect.right += pDestPoint->x;1451destRect.bottom += pDestPoint->y;1452}14531454user_assert(destRect.right <= dst->desc.Width &&1455destRect.bottom <= dst->desc.Height,1456D3DERR_INVALIDCALL);14571458if (compressed_format(dst->desc.Format)) {1459const unsigned w = util_format_get_blockwidth(dst->base.info.format);1460const unsigned h = util_format_get_blockheight(dst->base.info.format);14611462if (pDestPoint) {1463user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h),1464D3DERR_INVALIDCALL);1465}14661467if (pSourceRect) {1468user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h),1469D3DERR_INVALIDCALL);1470}1471if (!(copy_width == src->desc.Width &&1472copy_width == dst->desc.Width &&1473copy_height == src->desc.Height &&1474copy_height == dst->desc.Height)) {1475user_assert(!(copy_width % w) && !(copy_height % h),1476D3DERR_INVALIDCALL);1477}1478}14791480NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect);14811482return D3D_OK;1483}14841485HRESULT NINE_WINAPI1486NineDevice9_UpdateTexture( struct NineDevice9 *This,1487IDirect3DBaseTexture9 *pSourceTexture,1488IDirect3DBaseTexture9 *pDestinationTexture )1489{1490struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);1491struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);1492unsigned l, m;1493unsigned last_src_level, last_dst_level;1494RECT rect;14951496DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,1497pSourceTexture, pDestinationTexture);14981499user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL);1500user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);15011502user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);1503user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);1504user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);1505user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ||1506dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL);15071508/* Spec: Failure if1509* . Different formats1510* . Fewer src levels than dst levels (if the opposite, only matching levels1511* are supposed to be copied)1512* . Levels do not match1513* DDI: Actually the above should pass because of legacy applications1514* Do what you want about these, but you shouldn't crash.1515* However driver can expect that the top dimension is greater for src than dst.1516* Wine tests: Every combination that passes the initial checks should pass.1517* . Different formats => conversion driver and format dependent.1518* . 1 level, but size not matching => copy is done (and even crash if src bigger1519* than dst. For the case where dst bigger, wine doesn't test if a stretch is applied1520* or if a subrect is copied).1521* . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect1522* copied to 7x7.1523*1524* From these, the proposal is:1525* . Different formats -> use util_format_translate to translate if possible for surfaces.1526* Accept ARGB/XRGB for Volumes. Do nothing for the other combinations1527* . First level copied -> the first level such that src is smaller or equal to dst first level1528* . number of levels copied -> as long as it fits and textures have levels1529* That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)1530*/15311532last_src_level = srcb->level_count-1;1533last_dst_level = dstb->level_count-1;15341535for (m = 0; m <= last_src_level; ++m) {1536unsigned w = u_minify(srcb->base.info.width0, m);1537unsigned h = u_minify(srcb->base.info.height0, m);1538unsigned d = u_minify(srcb->base.info.depth0, m);15391540if (w <= dstb->base.info.width0 &&1541h <= dstb->base.info.height0 &&1542d <= dstb->base.info.depth0)1543break;1544}1545user_assert(m <= last_src_level, D3D_OK);15461547last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level);15481549if (dstb->base.type == D3DRTYPE_TEXTURE) {1550struct NineTexture9 *dst = NineTexture9(dstb);1551struct NineTexture9 *src = NineTexture9(srcb);15521553if (src->dirty_rect.width == 0)1554return D3D_OK;15551556pipe_box_to_rect(&rect, &src->dirty_rect);1557for (l = 0; l < m; ++l)1558rect_minify_inclusive(&rect);15591560for (l = 0; l <= last_dst_level; ++l, ++m) {1561fit_rect_format_inclusive(dst->base.base.info.format,1562&rect,1563dst->surfaces[l]->desc.Width,1564dst->surfaces[l]->desc.Height);1565NineSurface9_CopyMemToDefault(dst->surfaces[l],1566src->surfaces[m],1567(POINT *)&rect,1568&rect);1569rect_minify_inclusive(&rect);1570}1571u_box_origin_2d(0, 0, &src->dirty_rect);1572} else1573if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {1574struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);1575struct NineCubeTexture9 *src = NineCubeTexture9(srcb);1576unsigned z;15771578/* GPUs usually have them stored as arrays of mip-mapped 2D textures. */1579for (z = 0; z < 6; ++z) {1580if (src->dirty_rect[z].width == 0)1581continue;15821583pipe_box_to_rect(&rect, &src->dirty_rect[z]);1584for (l = 0; l < m; ++l)1585rect_minify_inclusive(&rect);15861587for (l = 0; l <= last_dst_level; ++l, ++m) {1588fit_rect_format_inclusive(dst->base.base.info.format,1589&rect,1590dst->surfaces[l * 6 + z]->desc.Width,1591dst->surfaces[l * 6 + z]->desc.Height);1592NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z],1593src->surfaces[m * 6 + z],1594(POINT *)&rect,1595&rect);1596rect_minify_inclusive(&rect);1597}1598u_box_origin_2d(0, 0, &src->dirty_rect[z]);1599m -= l;1600}1601} else1602if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) {1603struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);1604struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);16051606if (src->dirty_box.width == 0)1607return D3D_OK;1608for (l = 0; l <= last_dst_level; ++l, ++m)1609NineVolume9_CopyMemToDefault(dst->volumes[l],1610src->volumes[m], 0, 0, 0, NULL);1611u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box);1612} else{1613assert(!"invalid texture type");1614}16151616if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {1617dstb->dirty_mip = TRUE;1618NineBaseTexture9_GenerateMipSubLevels(dstb);1619}16201621return D3D_OK;1622}16231624HRESULT NINE_WINAPI1625NineDevice9_GetRenderTargetData( struct NineDevice9 *This,1626IDirect3DSurface9 *pRenderTarget,1627IDirect3DSurface9 *pDestSurface )1628{1629struct NineSurface9 *dst = NineSurface9(pDestSurface);1630struct NineSurface9 *src = NineSurface9(pRenderTarget);16311632DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",1633This, pRenderTarget, pDestSurface);16341635user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL);16361637user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);1638user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);16391640user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);1641user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);16421643user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL);1644user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL);16451646user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL);16471648NineSurface9_CopyDefaultToMem(dst, src);16491650return D3D_OK;1651}16521653HRESULT NINE_WINAPI1654NineDevice9_GetFrontBufferData( struct NineDevice9 *This,1655UINT iSwapChain,1656IDirect3DSurface9 *pDestSurface )1657{1658DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This,1659iSwapChain, pDestSurface);16601661user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL);1662user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);16631664return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain],1665pDestSurface);1666}16671668HRESULT NINE_WINAPI1669NineDevice9_StretchRect( struct NineDevice9 *This,1670IDirect3DSurface9 *pSourceSurface,1671const RECT *pSourceRect,1672IDirect3DSurface9 *pDestSurface,1673const RECT *pDestRect,1674D3DTEXTUREFILTERTYPE Filter )1675{1676struct pipe_screen *screen = This->screen;1677struct NineSurface9 *dst = NineSurface9(pDestSurface);1678struct NineSurface9 *src = NineSurface9(pSourceSurface);1679struct pipe_resource *dst_res, *src_res;1680boolean zs;1681struct pipe_blit_info blit;1682boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE;16831684DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "1685"pDestRect=%p Filter=%u\n",1686This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);1687if (pSourceRect)1688DBG("pSourceRect=(%u,%u)-(%u,%u)\n",1689pSourceRect->left, pSourceRect->top,1690pSourceRect->right, pSourceRect->bottom);1691if (pDestRect)1692DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top,1693pDestRect->right, pDestRect->bottom);16941695user_assert(pSourceSurface && pDestSurface, D3DERR_INVALIDCALL);1696user_assert(dst->base.pool == D3DPOOL_DEFAULT &&1697src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);16981699dst_res = NineSurface9_GetResource(dst);1700src_res = NineSurface9_GetResource(src);1701zs = util_format_is_depth_or_stencil(dst_res->format);1702user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL);1703user_assert(!zs || !pSourceRect ||1704(pSourceRect->left == 0 &&1705pSourceRect->top == 0 &&1706pSourceRect->right == src->desc.Width &&1707pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL);1708user_assert(!zs || !pDestRect ||1709(pDestRect->left == 0 &&1710pDestRect->top == 0 &&1711pDestRect->right == dst->desc.Width &&1712pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL);1713user_assert(!zs ||1714(dst->desc.Width == src->desc.Width &&1715dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL);1716user_assert(zs || !util_format_is_depth_or_stencil(src_res->format),1717D3DERR_INVALIDCALL);1718user_assert(!zs || dst->desc.Format == src->desc.Format,1719D3DERR_INVALIDCALL);1720user_assert(screen->is_format_supported(screen, src_res->format,1721src_res->target,1722src_res->nr_samples,1723src_res->nr_storage_samples,1724PIPE_BIND_SAMPLER_VIEW),1725D3DERR_INVALIDCALL);17261727/* We might want to permit these, but wine thinks we shouldn't. */1728user_assert(!pDestRect ||1729(pDestRect->left <= pDestRect->right &&1730pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL);1731user_assert(!pSourceRect ||1732(pSourceRect->left <= pSourceRect->right &&1733pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL);17341735memset(&blit, 0, sizeof(blit));1736blit.dst.resource = dst_res;1737blit.dst.level = dst->level;1738blit.dst.box.z = dst->layer;1739blit.dst.box.depth = 1;1740blit.dst.format = dst_res->format;1741if (pDestRect) {1742flip_x = pDestRect->left > pDestRect->right;1743if (flip_x) {1744blit.dst.box.x = pDestRect->right;1745blit.dst.box.width = pDestRect->left - pDestRect->right;1746} else {1747blit.dst.box.x = pDestRect->left;1748blit.dst.box.width = pDestRect->right - pDestRect->left;1749}1750flip_y = pDestRect->top > pDestRect->bottom;1751if (flip_y) {1752blit.dst.box.y = pDestRect->bottom;1753blit.dst.box.height = pDestRect->top - pDestRect->bottom;1754} else {1755blit.dst.box.y = pDestRect->top;1756blit.dst.box.height = pDestRect->bottom - pDestRect->top;1757}1758} else {1759blit.dst.box.x = 0;1760blit.dst.box.y = 0;1761blit.dst.box.width = dst->desc.Width;1762blit.dst.box.height = dst->desc.Height;1763}1764blit.src.resource = src_res;1765blit.src.level = src->level;1766blit.src.box.z = src->layer;1767blit.src.box.depth = 1;1768blit.src.format = src_res->format;1769if (pSourceRect) {1770if (flip_x ^ (pSourceRect->left > pSourceRect->right)) {1771blit.src.box.x = pSourceRect->right;1772blit.src.box.width = pSourceRect->left - pSourceRect->right;1773} else {1774blit.src.box.x = pSourceRect->left;1775blit.src.box.width = pSourceRect->right - pSourceRect->left;1776}1777if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) {1778blit.src.box.y = pSourceRect->bottom;1779blit.src.box.height = pSourceRect->top - pSourceRect->bottom;1780} else {1781blit.src.box.y = pSourceRect->top;1782blit.src.box.height = pSourceRect->bottom - pSourceRect->top;1783}1784} else {1785blit.src.box.x = flip_x ? src->desc.Width : 0;1786blit.src.box.y = flip_y ? src->desc.Height : 0;1787blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width;1788blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height;1789}1790blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA;1791blit.filter = Filter == D3DTEXF_LINEAR ?1792PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;1793blit.scissor_enable = FALSE;1794blit.alpha_blend = FALSE;17951796/* If both of a src and dst dimension are negative, flip them. */1797if (blit.dst.box.width < 0 && blit.src.box.width < 0) {1798blit.dst.box.width = -blit.dst.box.width;1799blit.src.box.width = -blit.src.box.width;1800}1801if (blit.dst.box.height < 0 && blit.src.box.height < 0) {1802blit.dst.box.height = -blit.dst.box.height;1803blit.src.box.height = -blit.src.box.height;1804}1805scaled =1806blit.dst.box.width != blit.src.box.width ||1807blit.dst.box.height != blit.src.box.height;18081809user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);1810user_assert(!scaled ||1811!NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL);1812user_assert(!NineSurface9_IsOffscreenPlain(dst) ||1813NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);1814user_assert(NineSurface9_IsOffscreenPlain(dst) ||1815dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL),1816D3DERR_INVALIDCALL);1817user_assert(!scaled ||1818(!util_format_is_compressed(dst->base.info.format) &&1819!util_format_is_compressed(src->base.info.format)),1820D3DERR_INVALIDCALL);18211822user_warn(src == dst &&1823u_box_test_intersection_2d(&blit.src.box, &blit.dst.box));18241825/* Check for clipping/clamping: */1826{1827struct pipe_box box;1828int xy;18291830xy = u_box_clip_2d(&box, &blit.dst.box,1831dst->desc.Width, dst->desc.Height);1832if (xy < 0)1833return D3D_OK;1834if (xy == 0)1835xy = u_box_clip_2d(&box, &blit.src.box,1836src->desc.Width, src->desc.Height);1837clamped = !!xy;1838}18391840ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) ||1841(dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality);18421843if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) {1844DBG("using pipe->blit()\n");1845/* TODO: software scaling */1846user_assert(screen->is_format_supported(screen, dst_res->format,1847dst_res->target,1848dst_res->nr_samples,1849dst_res->nr_storage_samples,1850zs ? PIPE_BIND_DEPTH_STENCIL :1851PIPE_BIND_RENDER_TARGET),1852D3DERR_INVALIDCALL);18531854nine_context_blit(This, (struct NineUnknown *)dst,1855(struct NineUnknown *)src, &blit);1856} else {1857assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&1858blit.src.box.x >= 0 && blit.src.box.y >= 0 &&1859blit.dst.box.x + blit.dst.box.width <= dst->desc.Width &&1860blit.src.box.x + blit.src.box.width <= src->desc.Width &&1861blit.dst.box.y + blit.dst.box.height <= dst->desc.Height &&1862blit.src.box.y + blit.src.box.height <= src->desc.Height);1863/* Or drivers might crash ... */1864DBG("Using resource_copy_region.\n");1865nine_context_resource_copy_region(This, (struct NineUnknown *)dst,1866(struct NineUnknown *)src,1867blit.dst.resource, blit.dst.level,1868&blit.dst.box,1869blit.src.resource, blit.src.level,1870&blit.src.box);1871}18721873/* Communicate the container it needs to update sublevels - if apply */1874NineSurface9_MarkContainerDirty(dst);18751876return D3D_OK;1877}18781879HRESULT NINE_WINAPI1880NineDevice9_ColorFill( struct NineDevice9 *This,1881IDirect3DSurface9 *pSurface,1882const RECT *pRect,1883D3DCOLOR color )1884{1885struct NineSurface9 *surf = NineSurface9(pSurface);1886unsigned x, y, w, h;18871888DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,1889pSurface, pRect, color);1890if (pRect)1891DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top,1892pRect->right, pRect->bottom);18931894user_assert(pSurface != NULL, D3DERR_INVALIDCALL);18951896user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);18971898user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) ||1899NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL);19001901user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK);19021903if (pRect) {1904x = pRect->left;1905y = pRect->top;1906w = pRect->right - pRect->left;1907h = pRect->bottom - pRect->top;1908/* Wine tests: */1909if (compressed_format(surf->desc.Format)) {1910const unsigned bw = util_format_get_blockwidth(surf->base.info.format);1911const unsigned bh = util_format_get_blockheight(surf->base.info.format);19121913user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh),1914D3DERR_INVALIDCALL);1915}1916} else{1917x = 0;1918y = 0;1919w = surf->desc.Width;1920h = surf->desc.Height;1921}19221923if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) {1924nine_context_clear_render_target(This, surf, color, x, y, w, h);1925} else {1926D3DLOCKED_RECT lock;1927union util_color uc;1928HRESULT hr;1929/* XXX: lock pRect and fix util_fill_rect */1930hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD);1931if (FAILED(hr))1932return hr;1933util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,1934surf->base.info.format, &uc);1935util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch,1936x, y, w, h, &uc);1937NineSurface9_UnlockRect(surf);1938}19391940return D3D_OK;1941}19421943HRESULT NINE_WINAPI1944NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,1945UINT Width,1946UINT Height,1947D3DFORMAT Format,1948D3DPOOL Pool,1949IDirect3DSurface9 **ppSurface,1950HANDLE *pSharedHandle )1951{1952HRESULT hr;19531954DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "1955"ppSurface=%p pSharedHandle=%p\n", This,1956Width, Height, d3dformat_to_string(Format), Format, Pool,1957ppSurface, pSharedHandle);19581959user_assert(ppSurface != NULL, D3DERR_INVALIDCALL);1960*ppSurface = NULL;1961user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT1962|| Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);1963user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);19641965/* Can be used with StretchRect and ColorFill. It's also always lockable.1966*/1967hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height,1968Format,1969D3DMULTISAMPLE_NONE, 0,1970TRUE,1971ppSurface, pSharedHandle);1972if (FAILED(hr))1973DBG("Failed to create surface.\n");1974return hr;1975}19761977HRESULT NINE_WINAPI1978NineDevice9_SetRenderTarget( struct NineDevice9 *This,1979DWORD RenderTargetIndex,1980IDirect3DSurface9 *pRenderTarget )1981{1982struct NineSurface9 *rt = NineSurface9(pRenderTarget);1983const unsigned i = RenderTargetIndex;19841985DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This,1986RenderTargetIndex, pRenderTarget);19871988user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);1989user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL);1990user_assert(!pRenderTarget ||1991rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL);19921993if (i == 0) {1994This->state.viewport.X = 0;1995This->state.viewport.Y = 0;1996This->state.viewport.Width = rt->desc.Width;1997This->state.viewport.Height = rt->desc.Height;1998This->state.viewport.MinZ = 0.0f;1999This->state.viewport.MaxZ = 1.0f;20002001This->state.scissor.minx = 0;2002This->state.scissor.miny = 0;2003This->state.scissor.maxx = rt->desc.Width;2004This->state.scissor.maxy = rt->desc.Height;2005nine_context_set_viewport(This, &This->state.viewport);2006nine_context_set_scissor(This, &This->state.scissor);2007}20082009if (This->state.rt[i] != NineSurface9(pRenderTarget))2010nine_bind(&This->state.rt[i], pRenderTarget);20112012nine_context_set_render_target(This, i, rt);2013return D3D_OK;2014}20152016HRESULT NINE_WINAPI2017NineDevice9_GetRenderTarget( struct NineDevice9 *This,2018DWORD RenderTargetIndex,2019IDirect3DSurface9 **ppRenderTarget )2020{2021const unsigned i = RenderTargetIndex;20222023user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);2024user_assert(ppRenderTarget, D3DERR_INVALIDCALL);20252026*ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i];2027if (!This->state.rt[i])2028return D3DERR_NOTFOUND;20292030NineUnknown_AddRef(NineUnknown(This->state.rt[i]));2031return D3D_OK;2032}20332034HRESULT NINE_WINAPI2035NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,2036IDirect3DSurface9 *pNewZStencil )2037{2038struct NineSurface9 *ds = NineSurface9(pNewZStencil);2039DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil);20402041user_assert(!ds || util_format_is_depth_or_stencil(ds->base.info.format),2042D3DERR_INVALIDCALL);20432044if (This->state.ds != ds) {2045nine_bind(&This->state.ds, ds);2046nine_context_set_depth_stencil(This, ds);2047}2048return D3D_OK;2049}20502051HRESULT NINE_WINAPI2052NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,2053IDirect3DSurface9 **ppZStencilSurface )2054{2055user_assert(ppZStencilSurface, D3DERR_INVALIDCALL);20562057*ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds;2058if (!This->state.ds)2059return D3DERR_NOTFOUND;20602061NineUnknown_AddRef(NineUnknown(This->state.ds));2062return D3D_OK;2063}20642065HRESULT NINE_WINAPI2066NineDevice9_BeginScene( struct NineDevice9 *This )2067{2068DBG("This=%p\n", This);2069user_assert(!This->in_scene, D3DERR_INVALIDCALL);2070This->in_scene = TRUE;2071/* Do we want to do anything else here ? */2072return D3D_OK;2073}20742075HRESULT NINE_WINAPI2076NineDevice9_EndScene( struct NineDevice9 *This )2077{2078DBG("This=%p\n", This);2079user_assert(This->in_scene, D3DERR_INVALIDCALL);2080This->in_scene = FALSE;2081This->end_scene_since_present++;2082/* EndScene() is supposed to flush the GPU commands.2083* The idea is to flush ahead of the Present() call.2084* (Apps could take advantage of this by inserting CPU2085* work between EndScene() and Present()).2086* Most apps will have one EndScene per frame.2087* Some will have 2 or 3.2088* Some bad behaving apps do a lot of them.2089* As flushing has a cost, do it only once. */2090if (This->end_scene_since_present <= 1) {2091nine_context_pipe_flush(This);2092nine_csmt_flush(This);2093}2094return D3D_OK;2095}20962097HRESULT NINE_WINAPI2098NineDevice9_Clear( struct NineDevice9 *This,2099DWORD Count,2100const D3DRECT *pRects,2101DWORD Flags,2102D3DCOLOR Color,2103float Z,2104DWORD Stencil )2105{2106struct NineSurface9 *zsbuf_surf = This->state.ds;21072108DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",2109This, Count, pRects, Flags, Color, Z, Stencil);21102111user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL),2112D3DERR_INVALIDCALL);2113user_assert(!(Flags & D3DCLEAR_STENCIL) ||2114(zsbuf_surf &&2115util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)),2116D3DERR_INVALIDCALL);2117#ifdef NINE_STRICT2118user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL);2119#else2120user_warn((pRects && !Count) || (!pRects && Count));2121if (pRects && !Count)2122return D3D_OK;2123if (!pRects)2124Count = 0;2125#endif21262127nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil);2128return D3D_OK;2129}21302131static void2132nine_D3DMATRIX_print(const D3DMATRIX *M)2133{2134DBG("\n(%f %f %f %f)\n"2135"(%f %f %f %f)\n"2136"(%f %f %f %f)\n"2137"(%f %f %f %f)\n",2138M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3],2139M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3],2140M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3],2141M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]);2142}21432144HRESULT NINE_WINAPI2145NineDevice9_SetTransform( struct NineDevice9 *This,2146D3DTRANSFORMSTATETYPE State,2147const D3DMATRIX *pMatrix )2148{2149struct nine_state *state = This->update;2150D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE);21512152DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);21532154user_assert(pMatrix, D3DERR_INVALIDCALL);2155user_assert(M, D3DERR_INVALIDCALL);2156nine_D3DMATRIX_print(pMatrix);21572158*M = *pMatrix;2159if (unlikely(This->is_recording)) {2160state->ff.changed.transform[State / 32] |= 1 << (State % 32);2161state->changed.group |= NINE_STATE_FF_VSTRANSF;2162} else2163nine_context_set_transform(This, State, pMatrix);21642165return D3D_OK;2166}21672168HRESULT NINE_WINAPI2169NineDevice9_GetTransform( struct NineDevice9 *This,2170D3DTRANSFORMSTATETYPE State,2171D3DMATRIX *pMatrix )2172{2173D3DMATRIX *M;21742175user_assert(!This->pure, D3DERR_INVALIDCALL);2176M = nine_state_access_transform(&This->state.ff, State, FALSE);2177user_assert(pMatrix, D3DERR_INVALIDCALL);2178user_assert(M, D3DERR_INVALIDCALL);2179*pMatrix = *M;2180return D3D_OK;2181}21822183HRESULT NINE_WINAPI2184NineDevice9_MultiplyTransform( struct NineDevice9 *This,2185D3DTRANSFORMSTATETYPE State,2186const D3DMATRIX *pMatrix )2187{2188struct nine_state *state = This->update;2189D3DMATRIX T;2190D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE);21912192DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);21932194user_assert(pMatrix, D3DERR_INVALIDCALL);2195user_assert(M, D3DERR_INVALIDCALL);21962197nine_d3d_matrix_matrix_mul(&T, pMatrix, M);2198return NineDevice9_SetTransform(This, State, &T);2199}22002201HRESULT NINE_WINAPI2202NineDevice9_SetViewport( struct NineDevice9 *This,2203const D3DVIEWPORT9 *pViewport )2204{2205struct nine_state *state = This->update;22062207DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",2208pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height,2209pViewport->MinZ, pViewport->MaxZ);22102211user_assert(pViewport != NULL, D3DERR_INVALIDCALL);2212state->viewport = *pViewport;2213nine_context_set_viewport(This, pViewport);22142215return D3D_OK;2216}22172218HRESULT NINE_WINAPI2219NineDevice9_GetViewport( struct NineDevice9 *This,2220D3DVIEWPORT9 *pViewport )2221{2222user_assert(pViewport != NULL, D3DERR_INVALIDCALL);2223*pViewport = This->state.viewport;2224return D3D_OK;2225}22262227HRESULT NINE_WINAPI2228NineDevice9_SetMaterial( struct NineDevice9 *This,2229const D3DMATERIAL9 *pMaterial )2230{2231struct nine_state *state = This->update;22322233DBG("This=%p pMaterial=%p\n", This, pMaterial);2234if (pMaterial)2235nine_dump_D3DMATERIAL9(DBG_FF, pMaterial);22362237user_assert(pMaterial, E_POINTER);22382239state->ff.material = *pMaterial;2240if (unlikely(This->is_recording))2241state->changed.group |= NINE_STATE_FF_MATERIAL;2242else2243nine_context_set_material(This, pMaterial);22442245return D3D_OK;2246}22472248HRESULT NINE_WINAPI2249NineDevice9_GetMaterial( struct NineDevice9 *This,2250D3DMATERIAL9 *pMaterial )2251{2252user_assert(!This->pure, D3DERR_INVALIDCALL);2253user_assert(pMaterial, E_POINTER);2254*pMaterial = This->state.ff.material;2255return D3D_OK;2256}22572258HRESULT NINE_WINAPI2259NineDevice9_SetLight( struct NineDevice9 *This,2260DWORD Index,2261const D3DLIGHT9 *pLight )2262{2263struct nine_state *state = This->update;2264HRESULT hr;22652266DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight);2267if (pLight)2268nine_dump_D3DLIGHT9(DBG_FF, pLight);22692270user_assert(pLight, D3DERR_INVALIDCALL);2271user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL);22722273user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */22742275hr = nine_state_set_light(&state->ff, Index, pLight);2276if (hr != D3D_OK)2277return hr;22782279if (pLight->Type != D3DLIGHT_DIRECTIONAL &&2280pLight->Attenuation0 == 0.0f &&2281pLight->Attenuation1 == 0.0f &&2282pLight->Attenuation2 == 0.0f) {2283DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");2284}22852286if (unlikely(This->is_recording))2287state->changed.group |= NINE_STATE_FF_LIGHTING;2288else2289nine_context_set_light(This, Index, pLight);22902291return D3D_OK;2292}22932294HRESULT NINE_WINAPI2295NineDevice9_GetLight( struct NineDevice9 *This,2296DWORD Index,2297D3DLIGHT9 *pLight )2298{2299const struct nine_state *state = &This->state;23002301user_assert(!This->pure, D3DERR_INVALIDCALL);2302user_assert(pLight, D3DERR_INVALIDCALL);2303user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);2304user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,2305D3DERR_INVALIDCALL);23062307*pLight = state->ff.light[Index];23082309return D3D_OK;2310}23112312HRESULT NINE_WINAPI2313NineDevice9_LightEnable( struct NineDevice9 *This,2314DWORD Index,2315BOOL Enable )2316{2317struct nine_state *state = This->update;23182319DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable);23202321if (Index >= state->ff.num_lights ||2322state->ff.light[Index].Type == NINED3DLIGHT_INVALID) {2323/* This should create a default light. */2324D3DLIGHT9 light;2325memset(&light, 0, sizeof(light));2326light.Type = D3DLIGHT_DIRECTIONAL;2327light.Diffuse.r = 1.0f;2328light.Diffuse.g = 1.0f;2329light.Diffuse.b = 1.0f;2330light.Direction.z = 1.0f;2331NineDevice9_SetLight(This, Index, &light);2332}23332334nine_state_light_enable(&state->ff, Index, Enable);2335if (likely(!This->is_recording))2336nine_context_light_enable(This, Index, Enable);2337else2338state->changed.group |= NINE_STATE_FF_LIGHTING;23392340return D3D_OK;2341}23422343HRESULT NINE_WINAPI2344NineDevice9_GetLightEnable( struct NineDevice9 *This,2345DWORD Index,2346BOOL *pEnable )2347{2348const struct nine_state *state = &This->state;2349unsigned i;23502351user_assert(!This->pure, D3DERR_INVALIDCALL);2352user_assert(pEnable != NULL, D3DERR_INVALIDCALL);2353user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);2354user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,2355D3DERR_INVALIDCALL);23562357for (i = 0; i < state->ff.num_lights_active; ++i)2358if (state->ff.active_light[i] == Index)2359break;23602361*pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine23622363return D3D_OK;2364}23652366HRESULT NINE_WINAPI2367NineDevice9_SetClipPlane( struct NineDevice9 *This,2368DWORD Index,2369const float *pPlane )2370{2371struct nine_state *state = This->update;23722373user_assert(pPlane, D3DERR_INVALIDCALL);23742375DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index,2376pPlane[0], pPlane[1],2377pPlane[2], pPlane[3]);23782379user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);23802381memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0]));2382if (unlikely(This->is_recording))2383state->changed.ucp |= 1 << Index;2384else2385nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane);23862387return D3D_OK;2388}23892390HRESULT NINE_WINAPI2391NineDevice9_GetClipPlane( struct NineDevice9 *This,2392DWORD Index,2393float *pPlane )2394{2395const struct nine_state *state = &This->state;23962397user_assert(!This->pure, D3DERR_INVALIDCALL);2398user_assert(pPlane != NULL, D3DERR_INVALIDCALL);2399user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);24002401memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0]));2402return D3D_OK;2403}24042405HRESULT NINE_WINAPI2406NineDevice9_SetRenderState( struct NineDevice9 *This,2407D3DRENDERSTATETYPE State,2408DWORD Value )2409{2410struct nine_state *state = This->update;24112412DBG("This=%p State=%u(%s) Value=%08x\n", This,2413State, nine_d3drs_to_string(State), Value);24142415user_assert(State < D3DRS_COUNT, D3D_OK);24162417if (unlikely(This->is_recording)) {2418state->rs_advertised[State] = Value;2419/* only need to record changed render states for stateblocks */2420state->changed.rs[State / 32] |= 1 << (State % 32);2421return D3D_OK;2422}24232424if (state->rs_advertised[State] == Value)2425return D3D_OK;24262427state->rs_advertised[State] = Value;2428nine_context_set_render_state(This, State, Value);24292430return D3D_OK;2431}24322433HRESULT NINE_WINAPI2434NineDevice9_GetRenderState( struct NineDevice9 *This,2435D3DRENDERSTATETYPE State,2436DWORD *pValue )2437{2438user_assert(!This->pure, D3DERR_INVALIDCALL);2439user_assert(pValue != NULL, D3DERR_INVALIDCALL);2440/* TODO: This needs tests */2441if (State >= D3DRS_COUNT) {2442*pValue = 0;2443return D3D_OK;2444}24452446*pValue = This->state.rs_advertised[State];2447return D3D_OK;2448}24492450HRESULT NINE_WINAPI2451NineDevice9_CreateStateBlock( struct NineDevice9 *This,2452D3DSTATEBLOCKTYPE Type,2453IDirect3DStateBlock9 **ppSB )2454{2455struct NineStateBlock9 *nsb;2456struct nine_state *dst;2457HRESULT hr;2458enum nine_stateblock_type type;2459unsigned s;24602461DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB);24622463user_assert(ppSB != NULL, D3DERR_INVALIDCALL);2464user_assert(Type == D3DSBT_ALL ||2465Type == D3DSBT_VERTEXSTATE ||2466Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL);24672468switch (Type) {2469case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break;2470case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break;2471default:2472type = NINESBT_ALL;2473break;2474}24752476hr = NineStateBlock9_new(This, &nsb, type);2477if (FAILED(hr))2478return hr;2479*ppSB = (IDirect3DStateBlock9 *)nsb;2480dst = &nsb->state;24812482dst->changed.group = NINE_STATE_SAMPLER;24832484if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) {2485dst->changed.group |=2486NINE_STATE_FF_LIGHTING |2487NINE_STATE_VS | NINE_STATE_VS_CONST |2488NINE_STATE_VDECL;2489/* TODO: texture/sampler state */2490memcpy(dst->changed.rs,2491nine_render_states_vertex, sizeof(dst->changed.rs));2492nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f,2493&This->range_pool);2494nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I,2495&This->range_pool);2496nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B,2497&This->range_pool);2498for (s = 0; s < NINE_MAX_SAMPLERS; ++s)2499dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET;2500if (This->state.ff.num_lights) {2501dst->ff.num_lights = This->state.ff.num_lights;2502/* zero'd -> light type won't be NINED3DLIGHT_INVALID, so2503* all currently existing lights will be captured2504*/2505dst->ff.light = CALLOC(This->state.ff.num_lights,2506sizeof(D3DLIGHT9));2507if (!dst->ff.light) {2508nine_bind(ppSB, NULL);2509return E_OUTOFMEMORY;2510}2511}2512}2513if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) {2514dst->changed.group |=2515NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_FF_PS_CONSTS;2516memcpy(dst->changed.rs,2517nine_render_states_pixel, sizeof(dst->changed.rs));2518nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f,2519&This->range_pool);2520dst->changed.ps_const_i = 0xffff;2521dst->changed.ps_const_b = 0xffff;2522for (s = 0; s < NINE_MAX_SAMPLERS; ++s)2523dst->changed.sampler[s] |= 0x1ffe;2524for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) {2525dst->ff.changed.tex_stage[s][0] |= 0xffffffff;2526dst->ff.changed.tex_stage[s][1] |= 0xffffffff;2527}2528}2529if (Type == D3DSBT_ALL) {2530dst->changed.group |=2531NINE_STATE_VIEWPORT |2532NINE_STATE_SCISSOR |2533NINE_STATE_IDXBUF |2534NINE_STATE_FF_MATERIAL |2535NINE_STATE_FF_VSTRANSF;2536memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t));2537dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1;2538dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;2539dst->changed.stream_freq = dst->changed.vtxbuf;2540dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;2541dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1;2542/* The doc says the projection, world, view and texture matrices2543* are saved, which would translate to:2544* dst->ff.changed.transform[0] = 0x00FF000C;2545* dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32);2546* However we assume they meant save everything (which is basically just the2547* above plus the other world matrices).2548*/2549dst->ff.changed.transform[0] = 0x00FF000C;2550for (s = 0; s < 8; s++)2551dst->ff.changed.transform[8+s] = ~0;2552}2553NineStateBlock9_Capture(NineStateBlock9(*ppSB));25542555/* TODO: fixed function state */25562557return D3D_OK;2558}25592560HRESULT NINE_WINAPI2561NineDevice9_BeginStateBlock( struct NineDevice9 *This )2562{2563HRESULT hr;25642565DBG("This=%p\n", This);25662567user_assert(!This->record, D3DERR_INVALIDCALL);25682569hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM);2570if (FAILED(hr))2571return hr;2572NineUnknown_ConvertRefToBind(NineUnknown(This->record));25732574This->update = &This->record->state;2575This->is_recording = TRUE;25762577return D3D_OK;2578}25792580HRESULT NINE_WINAPI2581NineDevice9_EndStateBlock( struct NineDevice9 *This,2582IDirect3DStateBlock9 **ppSB )2583{2584DBG("This=%p ppSB=%p\n", This, ppSB);25852586user_assert(This->record, D3DERR_INVALIDCALL);2587user_assert(ppSB != NULL, D3DERR_INVALIDCALL);25882589This->update = &This->state;2590This->is_recording = FALSE;25912592NineUnknown_AddRef(NineUnknown(This->record));2593*ppSB = (IDirect3DStateBlock9 *)This->record;2594NineUnknown_Unbind(NineUnknown(This->record));2595This->record = NULL;25962597return D3D_OK;2598}25992600HRESULT NINE_WINAPI2601NineDevice9_SetClipStatus( struct NineDevice9 *This,2602const D3DCLIPSTATUS9 *pClipStatus )2603{2604user_assert(pClipStatus, D3DERR_INVALIDCALL);2605return D3D_OK;2606}26072608HRESULT NINE_WINAPI2609NineDevice9_GetClipStatus( struct NineDevice9 *This,2610D3DCLIPSTATUS9 *pClipStatus )2611{2612user_assert(pClipStatus, D3DERR_INVALIDCALL);2613/* Set/GetClipStatus is supposed to get the app some infos2614* about vertices being clipped if it is using the software2615* vertex rendering. It would be too complicated to implement.2616* Probably the info is for developpers when working on their2617* applications. Else it could be for apps to know if it is worth2618* drawing some elements. In that case it makes sense to send2619* 0 for ClipUnion and 0xFFFFFFFF for ClipIntersection (basically2620* means not all vertices are clipped). Those values are known to2621* be the default if SetClipStatus is not set. Else we could return2622* what was set with SetClipStatus unchanged. */2623pClipStatus->ClipUnion = 0;2624pClipStatus->ClipIntersection = 0xFFFFFFFF;2625return D3D_OK;2626}26272628HRESULT NINE_WINAPI2629NineDevice9_GetTexture( struct NineDevice9 *This,2630DWORD Stage,2631IDirect3DBaseTexture9 **ppTexture )2632{2633user_assert(Stage < NINE_MAX_SAMPLERS_PS ||2634Stage == D3DDMAPSAMPLER ||2635(Stage >= D3DVERTEXTEXTURESAMPLER0 &&2636Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);2637user_assert(ppTexture, D3DERR_INVALIDCALL);26382639if (Stage >= D3DDMAPSAMPLER)2640Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;26412642*ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage];26432644if (This->state.texture[Stage])2645NineUnknown_AddRef(NineUnknown(This->state.texture[Stage]));2646return D3D_OK;2647}26482649HRESULT NINE_WINAPI2650NineDevice9_SetTexture( struct NineDevice9 *This,2651DWORD Stage,2652IDirect3DBaseTexture9 *pTexture )2653{2654struct nine_state *state = This->update;2655struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture);2656struct NineBaseTexture9 *old;26572658DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture);26592660user_assert(Stage < NINE_MAX_SAMPLERS_PS ||2661Stage == D3DDMAPSAMPLER ||2662(Stage >= D3DVERTEXTEXTURESAMPLER0 &&2663Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);2664user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH &&2665tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL);26662667if (Stage >= D3DDMAPSAMPLER)2668Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;26692670if (This->is_recording) {2671state->changed.texture |= 1 << Stage;2672nine_bind(&state->texture[Stage], pTexture);2673return D3D_OK;2674}26752676old = state->texture[Stage];2677if (old == tex)2678return D3D_OK;26792680NineBindTextureToDevice(This, &state->texture[Stage], tex);26812682nine_context_set_texture(This, Stage, tex);26832684return D3D_OK;2685}26862687HRESULT NINE_WINAPI2688NineDevice9_GetTextureStageState( struct NineDevice9 *This,2689DWORD Stage,2690D3DTEXTURESTAGESTATETYPE Type,2691DWORD *pValue )2692{2693const struct nine_state *state = &This->state;26942695user_assert(!This->pure, D3DERR_INVALIDCALL);2696user_assert(pValue != NULL, D3DERR_INVALIDCALL);2697user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);2698user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);26992700*pValue = state->ff.tex_stage[Stage][Type];27012702return D3D_OK;2703}27042705HRESULT NINE_WINAPI2706NineDevice9_SetTextureStageState( struct NineDevice9 *This,2707DWORD Stage,2708D3DTEXTURESTAGESTATETYPE Type,2709DWORD Value )2710{2711struct nine_state *state = This->update;27122713DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);2714nine_dump_D3DTSS_value(DBG_FF, Type, Value);27152716user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);2717user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);27182719state->ff.tex_stage[Stage][Type] = Value;27202721if (unlikely(This->is_recording)) {2722state->changed.group |= NINE_STATE_FF_PS_CONSTS;2723state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);2724} else2725nine_context_set_texture_stage_state(This, Stage, Type, Value);27262727return D3D_OK;2728}27292730HRESULT NINE_WINAPI2731NineDevice9_GetSamplerState( struct NineDevice9 *This,2732DWORD Sampler,2733D3DSAMPLERSTATETYPE Type,2734DWORD *pValue )2735{2736user_assert(!This->pure, D3DERR_INVALIDCALL);2737user_assert(pValue != NULL, D3DERR_INVALIDCALL);2738user_assert(Sampler < NINE_MAX_SAMPLERS_PS ||2739Sampler == D3DDMAPSAMPLER ||2740(Sampler >= D3DVERTEXTEXTURESAMPLER0 &&2741Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);27422743if (Sampler >= D3DDMAPSAMPLER)2744Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;27452746*pValue = This->state.samp_advertised[Sampler][Type];2747return D3D_OK;2748}27492750HRESULT NINE_WINAPI2751NineDevice9_SetSamplerState( struct NineDevice9 *This,2752DWORD Sampler,2753D3DSAMPLERSTATETYPE Type,2754DWORD Value )2755{2756struct nine_state *state = This->update;27572758DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This,2759Sampler, nine_D3DSAMP_to_str(Type), Value);27602761user_assert(Sampler < NINE_MAX_SAMPLERS_PS ||2762Sampler == D3DDMAPSAMPLER ||2763(Sampler >= D3DVERTEXTEXTURESAMPLER0 &&2764Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);27652766if (Sampler >= D3DDMAPSAMPLER)2767Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;27682769if (unlikely(This->is_recording)) {2770state->samp_advertised[Sampler][Type] = Value;2771state->changed.group |= NINE_STATE_SAMPLER;2772state->changed.sampler[Sampler] |= 1 << Type;2773return D3D_OK;2774}27752776if (state->samp_advertised[Sampler][Type] == Value)2777return D3D_OK;27782779state->samp_advertised[Sampler][Type] = Value;2780nine_context_set_sampler_state(This, Sampler, Type, Value);27812782return D3D_OK;2783}27842785HRESULT NINE_WINAPI2786NineDevice9_ValidateDevice( struct NineDevice9 *This,2787DWORD *pNumPasses )2788{2789const struct nine_state *state = &This->state;2790unsigned i;2791unsigned w = 0, h = 0;27922793DBG("This=%p pNumPasses=%p\n", This, pNumPasses);27942795for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) {2796if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||2797state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)2798return D3DERR_UNSUPPORTEDTEXTUREFILTER;2799}28002801for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {2802if (!state->rt[i])2803continue;2804if (w == 0) {2805w = state->rt[i]->desc.Width;2806h = state->rt[i]->desc.Height;2807} else2808if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) {2809return D3DERR_CONFLICTINGRENDERSTATE;2810}2811}2812if (state->ds &&2813(state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) {2814if (w != 0 &&2815(state->ds->desc.Width != w || state->ds->desc.Height != h))2816return D3DERR_CONFLICTINGRENDERSTATE;2817}28182819if (pNumPasses)2820*pNumPasses = 1;28212822return D3D_OK;2823}28242825HRESULT NINE_WINAPI2826NineDevice9_SetPaletteEntries( struct NineDevice9 *This,2827UINT PaletteNumber,2828const PALETTEENTRY *pEntries )2829{2830STUB(D3D_OK); /* like wine */2831}28322833HRESULT NINE_WINAPI2834NineDevice9_GetPaletteEntries( struct NineDevice9 *This,2835UINT PaletteNumber,2836PALETTEENTRY *pEntries )2837{2838STUB(D3DERR_INVALIDCALL);2839}28402841HRESULT NINE_WINAPI2842NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,2843UINT PaletteNumber )2844{2845STUB(D3D_OK); /* like wine */2846}28472848HRESULT NINE_WINAPI2849NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,2850UINT *PaletteNumber )2851{2852STUB(D3DERR_INVALIDCALL);2853}28542855HRESULT NINE_WINAPI2856NineDevice9_SetScissorRect( struct NineDevice9 *This,2857const RECT *pRect )2858{2859struct nine_state *state = This->update;28602861user_assert(pRect != NULL, D3DERR_INVALIDCALL);28622863DBG("x=(%u..%u) y=(%u..%u)\n",2864pRect->left, pRect->top, pRect->right, pRect->bottom);28652866state->scissor.minx = pRect->left;2867state->scissor.miny = pRect->top;2868state->scissor.maxx = pRect->right;2869state->scissor.maxy = pRect->bottom;28702871if (unlikely(This->is_recording))2872state->changed.group |= NINE_STATE_SCISSOR;2873else2874nine_context_set_scissor(This, &state->scissor);28752876return D3D_OK;2877}28782879HRESULT NINE_WINAPI2880NineDevice9_GetScissorRect( struct NineDevice9 *This,2881RECT *pRect )2882{2883user_assert(pRect != NULL, D3DERR_INVALIDCALL);28842885pRect->left = This->state.scissor.minx;2886pRect->top = This->state.scissor.miny;2887pRect->right = This->state.scissor.maxx;2888pRect->bottom = This->state.scissor.maxy;28892890return D3D_OK;2891}28922893HRESULT NINE_WINAPI2894NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,2895BOOL bSoftware )2896{2897if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) {2898This->swvp = bSoftware;2899nine_context_set_swvp(This, bSoftware);2900return D3D_OK;2901} else2902return D3D_OK; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */2903}29042905BOOL NINE_WINAPI2906NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )2907{2908return This->swvp;2909}29102911HRESULT NINE_WINAPI2912NineDevice9_SetNPatchMode( struct NineDevice9 *This,2913float nSegments )2914{2915return D3D_OK; /* Nothing to do because we don't advertise NPatch support */2916}29172918float NINE_WINAPI2919NineDevice9_GetNPatchMode( struct NineDevice9 *This )2920{2921STUB(0);2922}29232924/* TODO: only go through dirty textures */2925static void2926validate_textures(struct NineDevice9 *device)2927{2928struct NineBaseTexture9 *tex, *ptr;2929LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {2930list_delinit(&tex->list);2931NineBaseTexture9_Validate(tex);2932}2933}29342935static void2936update_managed_buffers(struct NineDevice9 *device)2937{2938struct NineBuffer9 *buf, *ptr;2939LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) {2940list_delinit(&buf->managed.list);2941NineBuffer9_Upload(buf);2942}2943}29442945static void2946NineBeforeDraw( struct NineDevice9 *This )2947{2948/* Upload Managed dirty content */2949validate_textures(This); /* may clobber state */2950update_managed_buffers(This);2951}29522953static void2954NineAfterDraw( struct NineDevice9 *This )2955{2956unsigned i;2957struct nine_state *state = &This->state;2958unsigned ps_mask = state->ps ? state->ps->rt_mask : 1;29592960/* Flag render-targets with autogenmipmap for mipmap regeneration */2961for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {2962struct NineSurface9 *rt = state->rt[i];29632964if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) &&2965rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) {2966assert(rt->texture == D3DRTYPE_TEXTURE ||2967rt->texture == D3DRTYPE_CUBETEXTURE);2968NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;2969}2970}2971}29722973#define IS_SYSTEMMEM_DYNAMIC(t) ((t) && (t)->base.pool == D3DPOOL_SYSTEMMEM && (t)->base.usage & D3DUSAGE_DYNAMIC)29742975/* Indicates the region needed right now for these buffers and add them to the list2976* of buffers to process in NineBeforeDraw.2977* The reason we don't call the upload right now is to generate smaller code (no2978* duplication of the NineBuffer9_Upload inline) and to have one upload (of the correct size)2979* if a vertex buffer is twice input of the draw call. */2980static void2981NineTrackSystemmemDynamic( struct NineBuffer9 *This, unsigned start, unsigned width )2982{2983struct pipe_box box;29842985u_box_1d(start, width, &box);2986u_box_union_1d(&This->managed.required_valid_region,2987&This->managed.required_valid_region,2988&box);2989This->managed.dirty = TRUE;2990BASEBUF_REGISTER_UPDATE(This);2991}29922993HRESULT NINE_WINAPI2994NineDevice9_DrawPrimitive( struct NineDevice9 *This,2995D3DPRIMITIVETYPE PrimitiveType,2996UINT StartVertex,2997UINT PrimitiveCount )2998{2999unsigned i;3000DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",3001This, PrimitiveType, StartVertex, PrimitiveCount);30023003/* Tracking for dynamic SYSTEMMEM */3004for (i = 0; i < This->caps.MaxStreams; i++) {3005unsigned stride = This->state.vtxbuf[i].stride;3006if (IS_SYSTEMMEM_DYNAMIC((struct NineBuffer9*)This->state.stream[i])) {3007unsigned start = This->state.vtxbuf[i].buffer_offset + StartVertex * stride;3008unsigned full_size = This->state.stream[i]->base.size;3009unsigned num_vertices = prim_count_to_vertex_count(PrimitiveType, PrimitiveCount);3010unsigned size = MIN2(full_size-start, num_vertices * stride);3011if (!stride) /* Instancing. Not sure what to do. Require all */3012size = full_size;3013NineTrackSystemmemDynamic(&This->state.stream[i]->base, start, size);3014}3015}30163017NineBeforeDraw(This);3018nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount);3019NineAfterDraw(This);30203021return D3D_OK;3022}30233024HRESULT NINE_WINAPI3025NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,3026D3DPRIMITIVETYPE PrimitiveType,3027INT BaseVertexIndex,3028UINT MinVertexIndex,3029UINT NumVertices,3030UINT StartIndex,3031UINT PrimitiveCount )3032{3033unsigned i, num_indices;3034DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "3035"NumVertices %u, StartIndex %u, PrimitiveCount %u\n",3036This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,3037StartIndex, PrimitiveCount);30383039user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);3040user_assert(This->state.vdecl, D3DERR_INVALIDCALL);30413042num_indices = prim_count_to_vertex_count(PrimitiveType, PrimitiveCount);30433044/* Tracking for dynamic SYSTEMMEM */3045if (IS_SYSTEMMEM_DYNAMIC(&This->state.idxbuf->base))3046NineTrackSystemmemDynamic(&This->state.idxbuf->base,3047StartIndex * This->state.idxbuf->index_size,3048num_indices * This->state.idxbuf->index_size);30493050for (i = 0; i < This->caps.MaxStreams; i++) {3051if (IS_SYSTEMMEM_DYNAMIC((struct NineBuffer9*)This->state.stream[i])) {3052uint32_t stride = This->state.vtxbuf[i].stride;3053uint32_t full_size = This->state.stream[i]->base.size;3054uint32_t start, stop;30553056start = MAX2(0, This->state.vtxbuf[i].buffer_offset+(MinVertexIndex+BaseVertexIndex)*stride);3057stop = This->state.vtxbuf[i].buffer_offset+(MinVertexIndex+NumVertices+BaseVertexIndex)*stride;3058stop = MIN2(stop, full_size);3059NineTrackSystemmemDynamic(&This->state.stream[i]->base,3060start, stop-start);3061}3062}30633064NineBeforeDraw(This);3065nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex,3066MinVertexIndex, NumVertices, StartIndex,3067PrimitiveCount);3068NineAfterDraw(This);30693070return D3D_OK;3071}30723073static void3074NineDevice9_SetStreamSourceNULL( struct NineDevice9 *This );30753076HRESULT NINE_WINAPI3077NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,3078D3DPRIMITIVETYPE PrimitiveType,3079UINT PrimitiveCount,3080const void *pVertexStreamZeroData,3081UINT VertexStreamZeroStride )3082{3083struct pipe_resource *resource = NULL;3084unsigned buffer_offset;3085unsigned StartVertex = 0;30863087DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",3088This, PrimitiveType, PrimitiveCount,3089pVertexStreamZeroData, VertexStreamZeroStride);30903091user_assert(pVertexStreamZeroData && VertexStreamZeroStride,3092D3DERR_INVALIDCALL);3093user_assert(PrimitiveCount, D3D_OK);30943095u_upload_data(This->vertex_uploader,30960,3097(prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride,30981,3099pVertexStreamZeroData,3100&buffer_offset,3101&resource);3102u_upload_unmap(This->vertex_uploader);31033104/* Optimization to skip changing the bound vertex buffer data3105* for consecutive DrawPrimitiveUp with identical VertexStreamZeroStride */3106if (VertexStreamZeroStride > 0) {3107StartVertex = buffer_offset / VertexStreamZeroStride;3108buffer_offset -= StartVertex * VertexStreamZeroStride;3109}31103111nine_context_set_stream_source_apply(This, 0, resource,3112buffer_offset, VertexStreamZeroStride);3113pipe_resource_reference(&resource, NULL);31143115NineBeforeDraw(This);3116nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount);3117NineAfterDraw(This);31183119NineDevice9_PauseRecording(This);3120NineDevice9_SetStreamSourceNULL(This);3121NineDevice9_ResumeRecording(This);31223123return D3D_OK;3124}31253126HRESULT NINE_WINAPI3127NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,3128D3DPRIMITIVETYPE PrimitiveType,3129UINT MinVertexIndex,3130UINT NumVertices,3131UINT PrimitiveCount,3132const void *pIndexData,3133D3DFORMAT IndexDataFormat,3134const void *pVertexStreamZeroData,3135UINT VertexStreamZeroStride )3136{3137struct pipe_vertex_buffer vbuf;3138unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;3139struct pipe_resource *ibuf = NULL;3140unsigned base;31413142DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "3143"PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "3144"pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",3145This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,3146pIndexData, IndexDataFormat,3147pVertexStreamZeroData, VertexStreamZeroStride);31483149user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL);3150user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL);3151user_assert(IndexDataFormat == D3DFMT_INDEX16 ||3152IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);3153user_assert(PrimitiveCount, D3D_OK);31543155base = MinVertexIndex * VertexStreamZeroStride;3156vbuf.is_user_buffer = false;3157vbuf.buffer.resource = NULL;3158vbuf.stride = VertexStreamZeroStride;3159u_upload_data(This->vertex_uploader,3160base,3161NumVertices * VertexStreamZeroStride, /* XXX */316264,3163(const uint8_t *)pVertexStreamZeroData + base,3164&vbuf.buffer_offset,3165&vbuf.buffer.resource);3166u_upload_unmap(This->vertex_uploader);3167/* Won't be used: */3168vbuf.buffer_offset -= base;31693170unsigned index_offset = 0;3171u_upload_data(This->pipe_secondary->stream_uploader,31720,3173(prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size,317464,3175pIndexData,3176&index_offset,3177&ibuf);3178u_upload_unmap(This->pipe_secondary->stream_uploader);31793180NineBeforeDraw(This);3181nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType,3182MinVertexIndex,3183NumVertices,3184PrimitiveCount,3185&vbuf,3186ibuf,3187ibuf ? NULL : (void*)pIndexData,3188index_offset,3189index_size);3190NineAfterDraw(This);31913192pipe_vertex_buffer_unreference(&vbuf);3193pipe_resource_reference(&ibuf, NULL);31943195NineDevice9_PauseRecording(This);3196NineDevice9_SetIndices(This, NULL);3197NineDevice9_SetStreamSourceNULL(This);3198NineDevice9_ResumeRecording(This);31993200return D3D_OK;3201}32023203HRESULT NINE_WINAPI3204NineDevice9_ProcessVertices( struct NineDevice9 *This,3205UINT SrcStartIndex,3206UINT DestIndex,3207UINT VertexCount,3208IDirect3DVertexBuffer9 *pDestBuffer,3209IDirect3DVertexDeclaration9 *pVertexDecl,3210DWORD Flags )3211{3212struct pipe_screen *screen_sw = This->screen_sw;3213struct pipe_context *pipe_sw = This->pipe_sw;3214struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl);3215struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);3216struct NineVertexShader9 *vs;3217struct pipe_resource *resource;3218struct pipe_transfer *transfer = NULL;3219struct pipe_stream_output_info so;3220struct pipe_stream_output_target *target;3221struct pipe_draw_info draw;3222struct pipe_draw_start_count_bias sc;3223struct pipe_box box;3224bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t);3225unsigned offsets[1] = {0};3226HRESULT hr;3227unsigned buffer_size;3228void *map;32293230DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "3231"pDestBuffer=%p pVertexDecl=%p Flags=%d\n",3232This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer,3233pVertexDecl, Flags);32343235user_assert(pDestBuffer && pVertexDecl, D3DERR_INVALIDCALL);32363237if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) {3238DBG("ProcessVertices not supported\n");3239return D3DERR_INVALIDCALL;3240}324132423243vs = programmable_vs ? This->state.vs : This->ff.vs;3244/* Note: version is 0 for ff */3245user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF),3246D3DERR_INVALIDCALL);3247if (!vdecl) {3248DWORD FVF = dst->desc.FVF;3249vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);3250if (!vdecl) {3251hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);3252if (FAILED(hr))3253return hr;3254vdecl->fvf = FVF;3255_mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl);3256NineUnknown_ConvertRefToBind(NineUnknown(vdecl));3257}3258}32593260/* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags3261* D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular3262* if not set, everything from src will be used, and dst3263* must match exactly the ff vs outputs.3264* TODO: Handle all the checks, etc for ff */3265user_assert(vdecl->position_t || programmable_vs,3266D3DERR_INVALIDCALL);32673268/* TODO: Support vs < 3 and ff */3269user_assert(vs->byte_code.version == 0x30,3270D3DERR_INVALIDCALL);3271/* TODO: Not hardcode the constant buffers for swvp */3272user_assert(This->may_swvp,3273D3DERR_INVALIDCALL);32743275nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so);32763277buffer_size = VertexCount * so.stride[0] * 4;3278{3279struct pipe_resource templ;32803281memset(&templ, 0, sizeof(templ));3282templ.target = PIPE_BUFFER;3283templ.format = PIPE_FORMAT_R8_UNORM;3284templ.width0 = buffer_size;3285templ.flags = 0;3286templ.bind = PIPE_BIND_STREAM_OUTPUT;3287templ.usage = PIPE_USAGE_STREAM;3288templ.height0 = templ.depth0 = templ.array_size = 1;3289templ.last_level = templ.nr_samples = templ.nr_storage_samples = 0;32903291resource = screen_sw->resource_create(screen_sw, &templ);3292if (!resource)3293return E_OUTOFMEMORY;3294}3295target = pipe_sw->create_stream_output_target(pipe_sw, resource,32960, buffer_size);3297if (!target) {3298pipe_resource_reference(&resource, NULL);3299return D3DERR_DRIVERINTERNALERROR;3300}33013302draw.mode = PIPE_PRIM_POINTS;3303sc.count = VertexCount;3304draw.start_instance = 0;3305draw.primitive_restart = FALSE;3306draw.restart_index = 0;3307draw.instance_count = 1;3308draw.index_size = 0;3309sc.start = 0;3310sc.index_bias = 0;3311draw.min_index = 0;3312draw.max_index = VertexCount - 1;331333143315pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets);33163317pipe_sw->draw_vbo(pipe_sw, &draw, 0, NULL, &sc, 1);33183319pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0);3320pipe_sw->stream_output_target_destroy(pipe_sw, target);33213322u_box_1d(0, VertexCount * so.stride[0] * 4, &box);3323map = pipe_sw->buffer_map(pipe_sw, resource, 0, PIPE_MAP_READ, &box,3324&transfer);3325if (!map) {3326hr = D3DERR_DRIVERINTERNALERROR;3327goto out;3328}33293330hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,3331dst, DestIndex, VertexCount,3332map, &so);3333if (transfer)3334pipe_sw->buffer_unmap(pipe_sw, transfer);33353336out:3337nine_state_after_draw_sw(This);3338pipe_resource_reference(&resource, NULL);3339return hr;3340}33413342HRESULT NINE_WINAPI3343NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,3344const D3DVERTEXELEMENT9 *pVertexElements,3345IDirect3DVertexDeclaration9 **ppDecl )3346{3347struct NineVertexDeclaration9 *vdecl;33483349DBG("This=%p pVertexElements=%p ppDecl=%p\n",3350This, pVertexElements, ppDecl);33513352user_assert(pVertexElements && ppDecl, D3DERR_INVALIDCALL);33533354HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl);3355if (SUCCEEDED(hr))3356*ppDecl = (IDirect3DVertexDeclaration9 *)vdecl;33573358return hr;3359}33603361HRESULT NINE_WINAPI3362NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,3363IDirect3DVertexDeclaration9 *pDecl )3364{3365struct nine_state *state = This->update;3366struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl);33673368DBG("This=%p pDecl=%p\n", This, pDecl);33693370if (unlikely(This->is_recording)) {3371nine_bind(&state->vdecl, vdecl);3372state->changed.group |= NINE_STATE_VDECL;3373return D3D_OK;3374}33753376if (state->vdecl == vdecl)3377return D3D_OK;33783379nine_bind(&state->vdecl, vdecl);33803381nine_context_set_vertex_declaration(This, vdecl);33823383return D3D_OK;3384}33853386HRESULT NINE_WINAPI3387NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,3388IDirect3DVertexDeclaration9 **ppDecl )3389{3390user_assert(ppDecl, D3DERR_INVALIDCALL);33913392*ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl;3393if (*ppDecl)3394NineUnknown_AddRef(NineUnknown(*ppDecl));3395return D3D_OK;3396}33973398HRESULT NINE_WINAPI3399NineDevice9_SetFVF( struct NineDevice9 *This,3400DWORD FVF )3401{3402struct NineVertexDeclaration9 *vdecl;3403HRESULT hr;34043405DBG("FVF = %08x\n", FVF);3406if (!FVF)3407return D3D_OK; /* like wine */34083409vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);3410if (!vdecl) {3411hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);3412if (FAILED(hr))3413return hr;3414vdecl->fvf = FVF;3415_mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl);3416NineUnknown_ConvertRefToBind(NineUnknown(vdecl));3417}3418return NineDevice9_SetVertexDeclaration(3419This, (IDirect3DVertexDeclaration9 *)vdecl);3420}34213422HRESULT NINE_WINAPI3423NineDevice9_GetFVF( struct NineDevice9 *This,3424DWORD *pFVF )3425{3426user_assert(pFVF != NULL, D3DERR_INVALIDCALL);3427*pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0;3428return D3D_OK;3429}34303431HRESULT NINE_WINAPI3432NineDevice9_CreateVertexShader( struct NineDevice9 *This,3433const DWORD *pFunction,3434IDirect3DVertexShader9 **ppShader )3435{3436struct NineVertexShader9 *vs;3437HRESULT hr;34383439DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);34403441user_assert(pFunction && ppShader, D3DERR_INVALIDCALL);34423443hr = NineVertexShader9_new(This, &vs, pFunction, NULL);3444if (FAILED(hr))3445return hr;3446*ppShader = (IDirect3DVertexShader9 *)vs;3447return D3D_OK;3448}34493450HRESULT NINE_WINAPI3451NineDevice9_SetVertexShader( struct NineDevice9 *This,3452IDirect3DVertexShader9 *pShader )3453{3454struct nine_state *state = This->update;3455struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader;34563457DBG("This=%p pShader=%p\n", This, pShader);34583459if (unlikely(This->is_recording)) {3460nine_bind(&state->vs, vs_shader);3461state->changed.group |= NINE_STATE_VS;3462return D3D_OK;3463}34643465if (state->vs == vs_shader)3466return D3D_OK;34673468nine_bind(&state->vs, vs_shader);34693470nine_context_set_vertex_shader(This, vs_shader);34713472return D3D_OK;3473}34743475HRESULT NINE_WINAPI3476NineDevice9_GetVertexShader( struct NineDevice9 *This,3477IDirect3DVertexShader9 **ppShader )3478{3479user_assert(ppShader, D3DERR_INVALIDCALL);3480nine_reference_set(ppShader, This->state.vs);3481return D3D_OK;3482}34833484HRESULT NINE_WINAPI3485NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,3486UINT StartRegister,3487const float *pConstantData,3488UINT Vector4fCount )3489{3490struct nine_state *state = This->update;3491float *vs_const_f = state->vs_const_f;34923493DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",3494This, StartRegister, pConstantData, Vector4fCount);34953496user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);3497user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);34983499if (!Vector4fCount)3500return D3D_OK;3501user_assert(pConstantData, D3DERR_INVALIDCALL);35023503if (unlikely(This->is_recording)) {3504memcpy(&vs_const_f[StartRegister * 4],3505pConstantData,3506Vector4fCount * 4 * sizeof(state->vs_const_f[0]));35073508nine_ranges_insert(&state->changed.vs_const_f,3509StartRegister, StartRegister + Vector4fCount,3510&This->range_pool);35113512state->changed.group |= NINE_STATE_VS_CONST;35133514return D3D_OK;3515}35163517if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData,3518Vector4fCount * 4 * sizeof(state->vs_const_f[0])))3519return D3D_OK;35203521memcpy(&vs_const_f[StartRegister * 4],3522pConstantData,3523Vector4fCount * 4 * sizeof(state->vs_const_f[0]));35243525nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData,3526Vector4fCount * 4 * sizeof(state->vs_const_f[0]),3527Vector4fCount);35283529return D3D_OK;3530}35313532HRESULT NINE_WINAPI3533NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,3534UINT StartRegister,3535float *pConstantData,3536UINT Vector4fCount )3537{3538const struct nine_state *state = &This->state;35393540user_assert(!This->pure, D3DERR_INVALIDCALL);3541user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);3542user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);3543user_assert(pConstantData, D3DERR_INVALIDCALL);35443545memcpy(pConstantData,3546&state->vs_const_f[StartRegister * 4],3547Vector4fCount * 4 * sizeof(state->vs_const_f[0]));35483549return D3D_OK;3550}35513552HRESULT NINE_WINAPI3553NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,3554UINT StartRegister,3555const int *pConstantData,3556UINT Vector4iCount )3557{3558struct nine_state *state = This->update;3559int i;35603561DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",3562This, StartRegister, pConstantData, Vector4iCount);35633564user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),3565D3DERR_INVALIDCALL);3566user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),3567D3DERR_INVALIDCALL);3568user_assert(pConstantData, D3DERR_INVALIDCALL);35693570if (This->driver_caps.vs_integer) {3571if (!This->is_recording) {3572if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData,3573Vector4iCount * sizeof(int[4])))3574return D3D_OK;3575}3576memcpy(&state->vs_const_i[4 * StartRegister],3577pConstantData,3578Vector4iCount * sizeof(int[4]));3579} else {3580for (i = 0; i < Vector4iCount; i++) {3581state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i]));3582state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1]));3583state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2]));3584state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3]));3585}3586}35873588if (unlikely(This->is_recording)) {3589nine_ranges_insert(&state->changed.vs_const_i,3590StartRegister, StartRegister + Vector4iCount,3591&This->range_pool);3592state->changed.group |= NINE_STATE_VS_CONST;3593} else3594nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData,3595Vector4iCount * sizeof(int[4]), Vector4iCount);35963597return D3D_OK;3598}35993600HRESULT NINE_WINAPI3601NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,3602UINT StartRegister,3603int *pConstantData,3604UINT Vector4iCount )3605{3606const struct nine_state *state = &This->state;3607int i;36083609user_assert(!This->pure, D3DERR_INVALIDCALL);3610user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),3611D3DERR_INVALIDCALL);3612user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),3613D3DERR_INVALIDCALL);3614user_assert(pConstantData, D3DERR_INVALIDCALL);36153616if (This->driver_caps.vs_integer) {3617memcpy(pConstantData,3618&state->vs_const_i[4 * StartRegister],3619Vector4iCount * sizeof(int[4]));3620} else {3621for (i = 0; i < Vector4iCount; i++) {3622pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]);3623pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]);3624pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]);3625pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]);3626}3627}36283629return D3D_OK;3630}36313632HRESULT NINE_WINAPI3633NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,3634UINT StartRegister,3635const BOOL *pConstantData,3636UINT BoolCount )3637{3638struct nine_state *state = This->update;3639int i;3640uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f);36413642DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",3643This, StartRegister, pConstantData, BoolCount);36443645user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),3646D3DERR_INVALIDCALL);3647user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),3648D3DERR_INVALIDCALL);3649user_assert(pConstantData, D3DERR_INVALIDCALL);36503651if (!This->is_recording) {3652bool noChange = true;3653for (i = 0; i < BoolCount; i++) {3654if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i])3655noChange = false;3656}3657if (noChange)3658return D3D_OK;3659}36603661for (i = 0; i < BoolCount; i++)3662state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;36633664if (unlikely(This->is_recording)) {3665nine_ranges_insert(&state->changed.vs_const_b,3666StartRegister, StartRegister + BoolCount,3667&This->range_pool);3668state->changed.group |= NINE_STATE_VS_CONST;3669} else3670nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData,3671sizeof(BOOL) * BoolCount, BoolCount);36723673return D3D_OK;3674}36753676HRESULT NINE_WINAPI3677NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,3678UINT StartRegister,3679BOOL *pConstantData,3680UINT BoolCount )3681{3682const struct nine_state *state = &This->state;3683int i;36843685user_assert(!This->pure, D3DERR_INVALIDCALL);3686user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),3687D3DERR_INVALIDCALL);3688user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),3689D3DERR_INVALIDCALL);3690user_assert(pConstantData, D3DERR_INVALIDCALL);36913692for (i = 0; i < BoolCount; i++)3693pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE;36943695return D3D_OK;3696}36973698HRESULT NINE_WINAPI3699NineDevice9_SetStreamSource( struct NineDevice9 *This,3700UINT StreamNumber,3701IDirect3DVertexBuffer9 *pStreamData,3702UINT OffsetInBytes,3703UINT Stride )3704{3705struct nine_state *state = This->update;3706struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData);3707const unsigned i = StreamNumber;37083709DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",3710This, StreamNumber, pStreamData, OffsetInBytes, Stride);37113712user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);3713user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL);37143715if (unlikely(This->is_recording)) {3716nine_bind(&state->stream[i], pStreamData);3717state->changed.vtxbuf |= 1 << StreamNumber;3718state->vtxbuf[i].stride = Stride;3719state->vtxbuf[i].buffer_offset = OffsetInBytes;3720return D3D_OK;3721}37223723if (state->stream[i] == NineVertexBuffer9(pStreamData) &&3724state->vtxbuf[i].stride == Stride &&3725state->vtxbuf[i].buffer_offset == OffsetInBytes)3726return D3D_OK;37273728state->vtxbuf[i].stride = Stride;3729state->vtxbuf[i].buffer_offset = OffsetInBytes;37303731NineBindBufferToDevice(This,3732(struct NineBuffer9 **)&state->stream[i],3733(struct NineBuffer9 *)pVBuf9);37343735nine_context_set_stream_source(This,3736StreamNumber,3737pVBuf9,3738OffsetInBytes,3739Stride);37403741return D3D_OK;3742}37433744static void3745NineDevice9_SetStreamSourceNULL( struct NineDevice9 *This )3746{3747struct nine_state *state = This->update;37483749DBG("This=%p\n", This);37503751state->vtxbuf[0].stride = 0;3752state->vtxbuf[0].buffer_offset = 0;37533754if (!state->stream[0])3755return;37563757NineBindBufferToDevice(This,3758(struct NineBuffer9 **)&state->stream[0],3759NULL);3760}37613762HRESULT NINE_WINAPI3763NineDevice9_GetStreamSource( struct NineDevice9 *This,3764UINT StreamNumber,3765IDirect3DVertexBuffer9 **ppStreamData,3766UINT *pOffsetInBytes,3767UINT *pStride )3768{3769const struct nine_state *state = &This->state;3770const unsigned i = StreamNumber;37713772user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);3773user_assert(ppStreamData && pOffsetInBytes && pStride, D3DERR_INVALIDCALL);37743775nine_reference_set(ppStreamData, state->stream[i]);3776*pStride = state->vtxbuf[i].stride;3777*pOffsetInBytes = state->vtxbuf[i].buffer_offset;37783779return D3D_OK;3780}37813782HRESULT NINE_WINAPI3783NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,3784UINT StreamNumber,3785UINT Setting )3786{3787struct nine_state *state = This->update;3788/* const UINT freq = Setting & 0x7FFFFF; */37893790DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This,3791StreamNumber, Setting);37923793user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);3794user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA),3795D3DERR_INVALIDCALL);3796user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) &&3797(Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL);3798user_assert(Setting, D3DERR_INVALIDCALL);37993800if (unlikely(This->is_recording)) {3801state->stream_freq[StreamNumber] = Setting;3802state->changed.stream_freq |= 1 << StreamNumber;3803return D3D_OK;3804}38053806if (state->stream_freq[StreamNumber] == Setting)3807return D3D_OK;38083809state->stream_freq[StreamNumber] = Setting;38103811nine_context_set_stream_source_freq(This, StreamNumber, Setting);3812return D3D_OK;3813}38143815HRESULT NINE_WINAPI3816NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,3817UINT StreamNumber,3818UINT *pSetting )3819{3820user_assert(pSetting != NULL, D3DERR_INVALIDCALL);3821user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);3822*pSetting = This->state.stream_freq[StreamNumber];3823return D3D_OK;3824}38253826HRESULT NINE_WINAPI3827NineDevice9_SetIndices( struct NineDevice9 *This,3828IDirect3DIndexBuffer9 *pIndexData )3829{3830struct nine_state *state = This->update;3831struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData);38323833DBG("This=%p pIndexData=%p\n", This, pIndexData);38343835if (unlikely(This->is_recording)) {3836nine_bind(&state->idxbuf, idxbuf);3837state->changed.group |= NINE_STATE_IDXBUF;3838return D3D_OK;3839}38403841if (state->idxbuf == idxbuf)3842return D3D_OK;38433844NineBindBufferToDevice(This,3845(struct NineBuffer9 **)&state->idxbuf,3846(struct NineBuffer9 *)idxbuf);38473848nine_context_set_indices(This, idxbuf);38493850return D3D_OK;3851}38523853/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense3854* here because it's an argument passed to the Draw calls.3855*/3856HRESULT NINE_WINAPI3857NineDevice9_GetIndices( struct NineDevice9 *This,3858IDirect3DIndexBuffer9 **ppIndexData)3859{3860user_assert(ppIndexData, D3DERR_INVALIDCALL);3861nine_reference_set(ppIndexData, This->state.idxbuf);3862return D3D_OK;3863}38643865HRESULT NINE_WINAPI3866NineDevice9_CreatePixelShader( struct NineDevice9 *This,3867const DWORD *pFunction,3868IDirect3DPixelShader9 **ppShader )3869{3870struct NinePixelShader9 *ps;3871HRESULT hr;38723873DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);38743875user_assert(pFunction && ppShader, D3DERR_INVALIDCALL);38763877hr = NinePixelShader9_new(This, &ps, pFunction, NULL);3878if (FAILED(hr))3879return hr;3880*ppShader = (IDirect3DPixelShader9 *)ps;3881return D3D_OK;3882}38833884HRESULT NINE_WINAPI3885NineDevice9_SetPixelShader( struct NineDevice9 *This,3886IDirect3DPixelShader9 *pShader )3887{3888struct nine_state *state = This->update;3889struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader;38903891DBG("This=%p pShader=%p\n", This, pShader);38923893if (unlikely(This->is_recording)) {3894nine_bind(&state->ps, pShader);3895state->changed.group |= NINE_STATE_PS;3896return D3D_OK;3897}38983899if (state->ps == ps)3900return D3D_OK;39013902nine_bind(&state->ps, ps);39033904nine_context_set_pixel_shader(This, ps);39053906return D3D_OK;3907}39083909HRESULT NINE_WINAPI3910NineDevice9_GetPixelShader( struct NineDevice9 *This,3911IDirect3DPixelShader9 **ppShader )3912{3913user_assert(ppShader, D3DERR_INVALIDCALL);3914nine_reference_set(ppShader, This->state.ps);3915return D3D_OK;3916}39173918HRESULT NINE_WINAPI3919NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,3920UINT StartRegister,3921const float *pConstantData,3922UINT Vector4fCount )3923{3924struct nine_state *state = This->update;39253926DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",3927This, StartRegister, pConstantData, Vector4fCount);39283929user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);3930user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);39313932if (!Vector4fCount)3933return D3D_OK;3934user_assert(pConstantData, D3DERR_INVALIDCALL);39353936if (unlikely(This->is_recording)) {3937memcpy(&state->ps_const_f[StartRegister * 4],3938pConstantData,3939Vector4fCount * 4 * sizeof(state->ps_const_f[0]));39403941nine_ranges_insert(&state->changed.ps_const_f,3942StartRegister, StartRegister + Vector4fCount,3943&This->range_pool);39443945state->changed.group |= NINE_STATE_PS_CONST;3946return D3D_OK;3947}39483949if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData,3950Vector4fCount * 4 * sizeof(state->ps_const_f[0])))3951return D3D_OK;39523953memcpy(&state->ps_const_f[StartRegister * 4],3954pConstantData,3955Vector4fCount * 4 * sizeof(state->ps_const_f[0]));39563957nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData,3958Vector4fCount * 4 * sizeof(state->ps_const_f[0]),3959Vector4fCount);39603961return D3D_OK;3962}39633964HRESULT NINE_WINAPI3965NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,3966UINT StartRegister,3967float *pConstantData,3968UINT Vector4fCount )3969{3970const struct nine_state *state = &This->state;39713972user_assert(!This->pure, D3DERR_INVALIDCALL);3973user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);3974user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);3975user_assert(pConstantData, D3DERR_INVALIDCALL);39763977memcpy(pConstantData,3978&state->ps_const_f[StartRegister * 4],3979Vector4fCount * 4 * sizeof(state->ps_const_f[0]));39803981return D3D_OK;3982}39833984HRESULT NINE_WINAPI3985NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,3986UINT StartRegister,3987const int *pConstantData,3988UINT Vector4iCount )3989{3990struct nine_state *state = This->update;3991int i;39923993DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",3994This, StartRegister, pConstantData, Vector4iCount);39953996user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);3997user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);3998user_assert(pConstantData, D3DERR_INVALIDCALL);39994000if (This->driver_caps.ps_integer) {4001if (!This->is_recording) {4002if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData,4003Vector4iCount * sizeof(state->ps_const_i[0])))4004return D3D_OK;4005}4006memcpy(&state->ps_const_i[StartRegister][0],4007pConstantData,4008Vector4iCount * sizeof(state->ps_const_i[0]));4009} else {4010for (i = 0; i < Vector4iCount; i++) {4011state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i]));4012state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1]));4013state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2]));4014state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3]));4015}4016}40174018if (unlikely(This->is_recording)) {4019state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;4020state->changed.group |= NINE_STATE_PS_CONST;4021} else4022nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData,4023sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount);40244025return D3D_OK;4026}40274028HRESULT NINE_WINAPI4029NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,4030UINT StartRegister,4031int *pConstantData,4032UINT Vector4iCount )4033{4034const struct nine_state *state = &This->state;4035int i;40364037user_assert(!This->pure, D3DERR_INVALIDCALL);4038user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);4039user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);4040user_assert(pConstantData, D3DERR_INVALIDCALL);40414042if (This->driver_caps.ps_integer) {4043memcpy(pConstantData,4044&state->ps_const_i[StartRegister][0],4045Vector4iCount * sizeof(state->ps_const_i[0]));4046} else {4047for (i = 0; i < Vector4iCount; i++) {4048pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]);4049pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]);4050pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]);4051pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]);4052}4053}40544055return D3D_OK;4056}40574058HRESULT NINE_WINAPI4059NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,4060UINT StartRegister,4061const BOOL *pConstantData,4062UINT BoolCount )4063{4064struct nine_state *state = This->update;4065int i;4066uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f);40674068DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",4069This, StartRegister, pConstantData, BoolCount);40704071user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);4072user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);4073user_assert(pConstantData, D3DERR_INVALIDCALL);40744075if (!This->is_recording) {4076bool noChange = true;4077for (i = 0; i < BoolCount; i++) {4078if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i])4079noChange = false;4080}4081if (noChange)4082return D3D_OK;4083}40844085for (i = 0; i < BoolCount; i++)4086state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;40874088if (unlikely(This->is_recording)) {4089state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;4090state->changed.group |= NINE_STATE_PS_CONST;4091} else4092nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData,4093sizeof(BOOL) * BoolCount, BoolCount);40944095return D3D_OK;4096}40974098HRESULT NINE_WINAPI4099NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,4100UINT StartRegister,4101BOOL *pConstantData,4102UINT BoolCount )4103{4104const struct nine_state *state = &This->state;4105int i;41064107user_assert(!This->pure, D3DERR_INVALIDCALL);4108user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);4109user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);4110user_assert(pConstantData, D3DERR_INVALIDCALL);41114112for (i = 0; i < BoolCount; i++)4113pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE;41144115return D3D_OK;4116}41174118HRESULT NINE_WINAPI4119NineDevice9_DrawRectPatch( struct NineDevice9 *This,4120UINT Handle,4121const float *pNumSegs,4122const D3DRECTPATCH_INFO *pRectPatchInfo )4123{4124STUB(D3DERR_INVALIDCALL);4125}41264127HRESULT NINE_WINAPI4128NineDevice9_DrawTriPatch( struct NineDevice9 *This,4129UINT Handle,4130const float *pNumSegs,4131const D3DTRIPATCH_INFO *pTriPatchInfo )4132{4133STUB(D3DERR_INVALIDCALL);4134}41354136HRESULT NINE_WINAPI4137NineDevice9_DeletePatch( struct NineDevice9 *This,4138UINT Handle )4139{4140STUB(D3DERR_INVALIDCALL);4141}41424143HRESULT NINE_WINAPI4144NineDevice9_CreateQuery( struct NineDevice9 *This,4145D3DQUERYTYPE Type,4146IDirect3DQuery9 **ppQuery )4147{4148struct NineQuery9 *query;4149HRESULT hr;41504151DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery);41524153hr = nine_is_query_supported(This->screen, Type);4154if (!ppQuery || hr != D3D_OK)4155return hr;41564157hr = NineQuery9_new(This, &query, Type);4158if (FAILED(hr))4159return hr;4160*ppQuery = (IDirect3DQuery9 *)query;4161return D3D_OK;4162}41634164IDirect3DDevice9Vtbl NineDevice9_vtable = {4165(void *)NineUnknown_QueryInterface,4166(void *)NineUnknown_AddRef,4167(void *)NineUnknown_Release,4168(void *)NineDevice9_TestCooperativeLevel,4169(void *)NineDevice9_GetAvailableTextureMem,4170(void *)NineDevice9_EvictManagedResources,4171(void *)NineDevice9_GetDirect3D,4172(void *)NineDevice9_GetDeviceCaps,4173(void *)NineDevice9_GetDisplayMode,4174(void *)NineDevice9_GetCreationParameters,4175(void *)NineDevice9_SetCursorProperties,4176(void *)NineDevice9_SetCursorPosition,4177(void *)NineDevice9_ShowCursor,4178(void *)NineDevice9_CreateAdditionalSwapChain,4179(void *)NineDevice9_GetSwapChain,4180(void *)NineDevice9_GetNumberOfSwapChains,4181(void *)NineDevice9_Reset,4182(void *)NineDevice9_Present,4183(void *)NineDevice9_GetBackBuffer,4184(void *)NineDevice9_GetRasterStatus,4185(void *)NineDevice9_SetDialogBoxMode,4186(void *)NineDevice9_SetGammaRamp,4187(void *)NineDevice9_GetGammaRamp,4188(void *)NineDevice9_CreateTexture,4189(void *)NineDevice9_CreateVolumeTexture,4190(void *)NineDevice9_CreateCubeTexture,4191(void *)NineDevice9_CreateVertexBuffer,4192(void *)NineDevice9_CreateIndexBuffer,4193(void *)NineDevice9_CreateRenderTarget,4194(void *)NineDevice9_CreateDepthStencilSurface,4195(void *)NineDevice9_UpdateSurface,4196(void *)NineDevice9_UpdateTexture,4197(void *)NineDevice9_GetRenderTargetData,4198(void *)NineDevice9_GetFrontBufferData,4199(void *)NineDevice9_StretchRect,4200(void *)NineDevice9_ColorFill,4201(void *)NineDevice9_CreateOffscreenPlainSurface,4202(void *)NineDevice9_SetRenderTarget,4203(void *)NineDevice9_GetRenderTarget,4204(void *)NineDevice9_SetDepthStencilSurface,4205(void *)NineDevice9_GetDepthStencilSurface,4206(void *)NineDevice9_BeginScene,4207(void *)NineDevice9_EndScene,4208(void *)NineDevice9_Clear,4209(void *)NineDevice9_SetTransform,4210(void *)NineDevice9_GetTransform,4211(void *)NineDevice9_MultiplyTransform,4212(void *)NineDevice9_SetViewport,4213(void *)NineDevice9_GetViewport,4214(void *)NineDevice9_SetMaterial,4215(void *)NineDevice9_GetMaterial,4216(void *)NineDevice9_SetLight,4217(void *)NineDevice9_GetLight,4218(void *)NineDevice9_LightEnable,4219(void *)NineDevice9_GetLightEnable,4220(void *)NineDevice9_SetClipPlane,4221(void *)NineDevice9_GetClipPlane,4222(void *)NineDevice9_SetRenderState,4223(void *)NineDevice9_GetRenderState,4224(void *)NineDevice9_CreateStateBlock,4225(void *)NineDevice9_BeginStateBlock,4226(void *)NineDevice9_EndStateBlock,4227(void *)NineDevice9_SetClipStatus,4228(void *)NineDevice9_GetClipStatus,4229(void *)NineDevice9_GetTexture,4230(void *)NineDevice9_SetTexture,4231(void *)NineDevice9_GetTextureStageState,4232(void *)NineDevice9_SetTextureStageState,4233(void *)NineDevice9_GetSamplerState,4234(void *)NineDevice9_SetSamplerState,4235(void *)NineDevice9_ValidateDevice,4236(void *)NineDevice9_SetPaletteEntries,4237(void *)NineDevice9_GetPaletteEntries,4238(void *)NineDevice9_SetCurrentTexturePalette,4239(void *)NineDevice9_GetCurrentTexturePalette,4240(void *)NineDevice9_SetScissorRect,4241(void *)NineDevice9_GetScissorRect,4242(void *)NineDevice9_SetSoftwareVertexProcessing,4243(void *)NineDevice9_GetSoftwareVertexProcessing,4244(void *)NineDevice9_SetNPatchMode,4245(void *)NineDevice9_GetNPatchMode,4246(void *)NineDevice9_DrawPrimitive,4247(void *)NineDevice9_DrawIndexedPrimitive,4248(void *)NineDevice9_DrawPrimitiveUP,4249(void *)NineDevice9_DrawIndexedPrimitiveUP,4250(void *)NineDevice9_ProcessVertices,4251(void *)NineDevice9_CreateVertexDeclaration,4252(void *)NineDevice9_SetVertexDeclaration,4253(void *)NineDevice9_GetVertexDeclaration,4254(void *)NineDevice9_SetFVF,4255(void *)NineDevice9_GetFVF,4256(void *)NineDevice9_CreateVertexShader,4257(void *)NineDevice9_SetVertexShader,4258(void *)NineDevice9_GetVertexShader,4259(void *)NineDevice9_SetVertexShaderConstantF,4260(void *)NineDevice9_GetVertexShaderConstantF,4261(void *)NineDevice9_SetVertexShaderConstantI,4262(void *)NineDevice9_GetVertexShaderConstantI,4263(void *)NineDevice9_SetVertexShaderConstantB,4264(void *)NineDevice9_GetVertexShaderConstantB,4265(void *)NineDevice9_SetStreamSource,4266(void *)NineDevice9_GetStreamSource,4267(void *)NineDevice9_SetStreamSourceFreq,4268(void *)NineDevice9_GetStreamSourceFreq,4269(void *)NineDevice9_SetIndices,4270(void *)NineDevice9_GetIndices,4271(void *)NineDevice9_CreatePixelShader,4272(void *)NineDevice9_SetPixelShader,4273(void *)NineDevice9_GetPixelShader,4274(void *)NineDevice9_SetPixelShaderConstantF,4275(void *)NineDevice9_GetPixelShaderConstantF,4276(void *)NineDevice9_SetPixelShaderConstantI,4277(void *)NineDevice9_GetPixelShaderConstantI,4278(void *)NineDevice9_SetPixelShaderConstantB,4279(void *)NineDevice9_GetPixelShaderConstantB,4280(void *)NineDevice9_DrawRectPatch,4281(void *)NineDevice9_DrawTriPatch,4282(void *)NineDevice9_DeletePatch,4283(void *)NineDevice9_CreateQuery4284};42854286static const GUID *NineDevice9_IIDs[] = {4287&IID_IDirect3DDevice9,4288&IID_IUnknown,4289NULL4290};42914292HRESULT4293NineDevice9_new( struct pipe_screen *pScreen,4294D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,4295D3DCAPS9 *pCaps,4296D3DPRESENT_PARAMETERS *pPresentationParameters,4297IDirect3D9 *pD3D9,4298ID3DPresentGroup *pPresentationGroup,4299struct d3dadapter9_context *pCTX,4300boolean ex,4301D3DDISPLAYMODEEX *pFullscreenDisplayMode,4302struct NineDevice9 **ppOut,4303int minorVersionNum )4304{4305BOOL lock;4306lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);43074308NINE_NEW(Device9, ppOut, lock, /* args */4309pScreen, pCreationParameters, pCaps,4310pPresentationParameters, pD3D9, pPresentationGroup, pCTX,4311ex, pFullscreenDisplayMode, minorVersionNum );4312}431343144315