17ec681f3Smrg/* 27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom 97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 227ec681f3Smrg 237ec681f3Smrg#include "device9.h" 247ec681f3Smrg#include "stateblock9.h" 257ec681f3Smrg#include "surface9.h" 267ec681f3Smrg#include "swapchain9.h" 277ec681f3Smrg#include "swapchain9ex.h" 287ec681f3Smrg#include "indexbuffer9.h" 297ec681f3Smrg#include "vertexbuffer9.h" 307ec681f3Smrg#include "vertexdeclaration9.h" 317ec681f3Smrg#include "vertexshader9.h" 327ec681f3Smrg#include "pixelshader9.h" 337ec681f3Smrg#include "query9.h" 347ec681f3Smrg#include "texture9.h" 357ec681f3Smrg#include "cubetexture9.h" 367ec681f3Smrg#include "volumetexture9.h" 377ec681f3Smrg#include "nine_buffer_upload.h" 387ec681f3Smrg#include "nine_helpers.h" 397ec681f3Smrg#include "nine_memory_helper.h" 407ec681f3Smrg#include "nine_pipe.h" 417ec681f3Smrg#include "nine_ff.h" 427ec681f3Smrg#include "nine_dump.h" 437ec681f3Smrg#include "nine_limits.h" 447ec681f3Smrg 457ec681f3Smrg#include "pipe/p_screen.h" 467ec681f3Smrg#include "pipe/p_context.h" 477ec681f3Smrg#include "pipe/p_config.h" 487ec681f3Smrg#include "util/macros.h" 497ec681f3Smrg#include "util/u_math.h" 507ec681f3Smrg#include "util/u_inlines.h" 517ec681f3Smrg#include "util/u_hash_table.h" 527ec681f3Smrg#include "util/format/u_format.h" 537ec681f3Smrg#include "util/u_surface.h" 547ec681f3Smrg#include "util/u_upload_mgr.h" 557ec681f3Smrg#include "hud/hud_context.h" 567ec681f3Smrg#include "compiler/glsl_types.h" 577ec681f3Smrg 587ec681f3Smrg#include "cso_cache/cso_context.h" 597ec681f3Smrg 607ec681f3Smrg#define DBG_CHANNEL DBG_DEVICE 617ec681f3Smrg 627ec681f3Smrg#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) 637ec681f3Smrg 647ec681f3Smrgstatic void nine_setup_fpu() 657ec681f3Smrg{ 667ec681f3Smrg uint16_t c; 677ec681f3Smrg 687ec681f3Smrg __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c)); 697ec681f3Smrg 707ec681f3Smrg /* clear the control word */ 717ec681f3Smrg c &= 0xF0C0; 727ec681f3Smrg /* d3d9 doc/wine tests: mask all exceptions, use single-precision 737ec681f3Smrg * and round to nearest */ 747ec681f3Smrg c |= 0x003F; 757ec681f3Smrg 767ec681f3Smrg __asm__ __volatile__ ("fldcw %0" : : "m" (*&c)); 777ec681f3Smrg} 787ec681f3Smrg 797ec681f3Smrgstatic void nine_setup_set_fpu(uint16_t val) 807ec681f3Smrg{ 817ec681f3Smrg __asm__ __volatile__ ("fldcw %0" : : "m" (*&val)); 827ec681f3Smrg} 837ec681f3Smrg 847ec681f3Smrgstatic uint16_t nine_setup_get_fpu() 857ec681f3Smrg{ 867ec681f3Smrg uint16_t c; 877ec681f3Smrg 887ec681f3Smrg __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c)); 897ec681f3Smrg return c; 907ec681f3Smrg} 917ec681f3Smrg 927ec681f3Smrg#else 937ec681f3Smrg 947ec681f3Smrgstatic void nine_setup_fpu(void) 957ec681f3Smrg{ 967ec681f3Smrg WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); 977ec681f3Smrg} 987ec681f3Smrg 997ec681f3Smrgstatic void nine_setup_set_fpu(UNUSED uint16_t val) 1007ec681f3Smrg{ 1017ec681f3Smrg WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); 1027ec681f3Smrg} 1037ec681f3Smrg 1047ec681f3Smrgstatic uint16_t nine_setup_get_fpu() 1057ec681f3Smrg{ 1067ec681f3Smrg WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); 1077ec681f3Smrg return 0; 1087ec681f3Smrg} 1097ec681f3Smrg 1107ec681f3Smrg#endif 1117ec681f3Smrg 1127ec681f3Smrgstruct pipe_resource * 1137ec681f3Smrgnine_resource_create_with_retry( struct NineDevice9 *This, 1147ec681f3Smrg struct pipe_screen *screen, 1157ec681f3Smrg const struct pipe_resource *templat ) 1167ec681f3Smrg{ 1177ec681f3Smrg struct pipe_resource *res; 1187ec681f3Smrg res = screen->resource_create(screen, templat); 1197ec681f3Smrg if (res) 1207ec681f3Smrg return res; 1217ec681f3Smrg /* Allocation failed, retry after freeing some resources 1227ec681f3Smrg * Note: Shouldn't be called from the worker thread */ 1237ec681f3Smrg if (!This) 1247ec681f3Smrg return NULL; 1257ec681f3Smrg /* Evict resources we can evict */ 1267ec681f3Smrg NineDevice9_EvictManagedResourcesInternal(This); 1277ec681f3Smrg /* Execute anything pending, such that some 1287ec681f3Smrg * deleted resources can be actually freed */ 1297ec681f3Smrg nine_csmt_process(This); 1307ec681f3Smrg /* We could also finish the context, if needed */ 1317ec681f3Smrg return screen->resource_create(screen, templat); 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrgvoid 1357ec681f3SmrgNineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ) 1367ec681f3Smrg{ 1377ec681f3Smrg struct NineSurface9 *refSurf = NULL; 1387ec681f3Smrg 1397ec681f3Smrg DBG("This=%p is_reset=%d\n", This, (int) is_reset); 1407ec681f3Smrg 1417ec681f3Smrg assert(!This->is_recording); 1427ec681f3Smrg 1437ec681f3Smrg nine_state_set_defaults(This, &This->caps, is_reset); 1447ec681f3Smrg 1457ec681f3Smrg refSurf = This->swapchains[0]->buffers[0]; 1467ec681f3Smrg assert(refSurf); 1477ec681f3Smrg 1487ec681f3Smrg This->state.viewport.X = 0; 1497ec681f3Smrg This->state.viewport.Y = 0; 1507ec681f3Smrg This->state.viewport.Width = refSurf->desc.Width; 1517ec681f3Smrg This->state.viewport.Height = refSurf->desc.Height; 1527ec681f3Smrg 1537ec681f3Smrg nine_context_set_viewport(This, &This->state.viewport); 1547ec681f3Smrg 1557ec681f3Smrg This->state.scissor.minx = 0; 1567ec681f3Smrg This->state.scissor.miny = 0; 1577ec681f3Smrg This->state.scissor.maxx = refSurf->desc.Width; 1587ec681f3Smrg This->state.scissor.maxy = refSurf->desc.Height; 1597ec681f3Smrg 1607ec681f3Smrg nine_context_set_scissor(This, &This->state.scissor); 1617ec681f3Smrg 1627ec681f3Smrg if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) { 1637ec681f3Smrg nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE); 1647ec681f3Smrg This->state.rs_advertised[D3DRS_ZENABLE] = TRUE; 1657ec681f3Smrg } 1667ec681f3Smrg if (This->state.rs_advertised[D3DRS_ZENABLE]) 1677ec681f3Smrg NineDevice9_SetDepthStencilSurface( 1687ec681f3Smrg This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf); 1697ec681f3Smrg} 1707ec681f3Smrg 1717ec681f3Smrg#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n) 1727ec681f3SmrgHRESULT 1737ec681f3SmrgNineDevice9_ctor( struct NineDevice9 *This, 1747ec681f3Smrg struct NineUnknownParams *pParams, 1757ec681f3Smrg struct pipe_screen *pScreen, 1767ec681f3Smrg D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 1777ec681f3Smrg D3DCAPS9 *pCaps, 1787ec681f3Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 1797ec681f3Smrg IDirect3D9 *pD3D9, 1807ec681f3Smrg ID3DPresentGroup *pPresentationGroup, 1817ec681f3Smrg struct d3dadapter9_context *pCTX, 1827ec681f3Smrg boolean ex, 1837ec681f3Smrg D3DDISPLAYMODEEX *pFullscreenDisplayMode, 1847ec681f3Smrg int minorVersionNum ) 1857ec681f3Smrg{ 1867ec681f3Smrg unsigned i; 1877ec681f3Smrg uint16_t fpu_cw = 0; 1887ec681f3Smrg HRESULT hr = NineUnknown_ctor(&This->base, pParams); 1897ec681f3Smrg 1907ec681f3Smrg DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p " 1917ec681f3Smrg "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n", 1927ec681f3Smrg This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9, 1937ec681f3Smrg pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode); 1947ec681f3Smrg 1957ec681f3Smrg if (FAILED(hr)) { return hr; } 1967ec681f3Smrg 1977ec681f3Smrg /* NIR shaders need to use GLSL types so let's initialize them here */ 1987ec681f3Smrg glsl_type_singleton_init_or_ref(); 1997ec681f3Smrg 2007ec681f3Smrg list_inithead(&This->update_buffers); 2017ec681f3Smrg list_inithead(&This->update_textures); 2027ec681f3Smrg list_inithead(&This->managed_buffers); 2037ec681f3Smrg list_inithead(&This->managed_textures); 2047ec681f3Smrg 2057ec681f3Smrg This->screen = pScreen; 2067ec681f3Smrg This->screen_sw = pCTX->ref; 2077ec681f3Smrg This->caps = *pCaps; 2087ec681f3Smrg This->d3d9 = pD3D9; 2097ec681f3Smrg This->params = *pCreationParameters; 2107ec681f3Smrg This->ex = ex; 2117ec681f3Smrg This->present = pPresentationGroup; 2127ec681f3Smrg This->minor_version_num = minorVersionNum; 2137ec681f3Smrg 2147ec681f3Smrg /* Ex */ 2157ec681f3Smrg This->gpu_priority = 0; 2167ec681f3Smrg This->max_frame_latency = 3; 2177ec681f3Smrg 2187ec681f3Smrg IDirect3D9_AddRef(This->d3d9); 2197ec681f3Smrg ID3DPresentGroup_AddRef(This->present); 2207ec681f3Smrg 2217ec681f3Smrg if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)) { 2227ec681f3Smrg nine_setup_fpu(); 2237ec681f3Smrg } else { 2247ec681f3Smrg /* Software renderer initialization needs exceptions masked */ 2257ec681f3Smrg fpu_cw = nine_setup_get_fpu(); 2267ec681f3Smrg nine_setup_set_fpu(fpu_cw | 0x007f); 2277ec681f3Smrg } 2287ec681f3Smrg 2297ec681f3Smrg if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) { 2307ec681f3Smrg DBG("Application asked full Software Vertex Processing.\n"); 2317ec681f3Smrg This->swvp = true; 2327ec681f3Smrg This->may_swvp = true; 2337ec681f3Smrg } else 2347ec681f3Smrg This->swvp = false; 2357ec681f3Smrg if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { 2367ec681f3Smrg DBG("Application asked mixed Software Vertex Processing.\n"); 2377ec681f3Smrg This->may_swvp = true; 2387ec681f3Smrg } 2397ec681f3Smrg This->context.swvp = This->swvp; 2407ec681f3Smrg /* TODO: check if swvp is resetted by device Resets */ 2417ec681f3Smrg 2427ec681f3Smrg if (This->may_swvp && 2437ec681f3Smrg (This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, 2447ec681f3Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) 2457ec681f3Smrg < (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) || 2467ec681f3Smrg This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, 2477ec681f3Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) { 2487ec681f3Smrg /* Note: We just go on, some apps never use the abilities of 2497ec681f3Smrg * swvp, and just set more constants than allowed at init. 2507ec681f3Smrg * Only cards we support that are affected are the r500 */ 2517ec681f3Smrg WARN("Card unable to handle Software Vertex Processing. Game may fail\n"); 2527ec681f3Smrg } 2537ec681f3Smrg 2547ec681f3Smrg /* When may_swvp, SetConstant* limits are different */ 2557ec681f3Smrg if (This->may_swvp) 2567ec681f3Smrg This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP; 2577ec681f3Smrg 2587ec681f3Smrg This->pure = !!(This->params.BehaviorFlags & D3DCREATE_PUREDEVICE); 2597ec681f3Smrg 2607ec681f3Smrg This->context.pipe = This->screen->context_create(This->screen, NULL, PIPE_CONTEXT_PREFER_THREADED); 2617ec681f3Smrg This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0); 2627ec681f3Smrg if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */ 2637ec681f3Smrg This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, PIPE_CONTEXT_PREFER_THREADED); 2647ec681f3Smrg if (!This->pipe_sw) { return E_OUTOFMEMORY; } 2657ec681f3Smrg 2667ec681f3Smrg This->context.cso = cso_create_context(This->context.pipe, CSO_NO_USER_VERTEX_BUFFERS); 2677ec681f3Smrg if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */ 2687ec681f3Smrg This->cso_sw = cso_create_context(This->pipe_sw, 0); 2697ec681f3Smrg if (!This->cso_sw) { return E_OUTOFMEMORY; } 2707ec681f3Smrg 2717ec681f3Smrg /* Create first, it messes up our state. */ 2727ec681f3Smrg This->hud = hud_create(This->context.cso, NULL, NULL); /* NULL result is fine */ 2737ec681f3Smrg 2747ec681f3Smrg This->allocator = nine_allocator_create(This, pCTX->memfd_virtualsizelimit); 2757ec681f3Smrg 2767ec681f3Smrg /* Available memory counter. Updated only for allocations with this device 2777ec681f3Smrg * instance. This is the Win 7 behavior. 2787ec681f3Smrg * Win XP shares this counter across multiple devices. */ 2797ec681f3Smrg This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY); 2807ec681f3Smrg This->available_texture_mem = (pCTX->override_vram_size >= 0) ? 2817ec681f3Smrg (long long)pCTX->override_vram_size : This->available_texture_mem; 2827ec681f3Smrg This->available_texture_mem <<= 20; 2837ec681f3Smrg 2847ec681f3Smrg /* We cap texture memory usage to 95% of what is reported free initially 2857ec681f3Smrg * This helps get closer Win behaviour. For example VertexBuffer allocation 2867ec681f3Smrg * still succeeds when texture allocation fails. */ 2877ec681f3Smrg This->available_texture_limit = This->available_texture_mem * 5LL / 100LL; 2887ec681f3Smrg 2897ec681f3Smrg This->frame_count = 0; /* Used to check if events occur the same frame */ 2907ec681f3Smrg 2917ec681f3Smrg /* create implicit swapchains */ 2927ec681f3Smrg This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present); 2937ec681f3Smrg This->swapchains = CALLOC(This->nswapchains, 2947ec681f3Smrg sizeof(struct NineSwapChain9 *)); 2957ec681f3Smrg if (!This->swapchains) { return E_OUTOFMEMORY; } 2967ec681f3Smrg 2977ec681f3Smrg for (i = 0; i < This->nswapchains; ++i) { 2987ec681f3Smrg ID3DPresent *present; 2997ec681f3Smrg 3007ec681f3Smrg hr = ID3DPresentGroup_GetPresent(This->present, i, &present); 3017ec681f3Smrg if (FAILED(hr)) 3027ec681f3Smrg return hr; 3037ec681f3Smrg 3047ec681f3Smrg if (ex) { 3057ec681f3Smrg D3DDISPLAYMODEEX *mode = NULL; 3067ec681f3Smrg struct NineSwapChain9Ex **ret = 3077ec681f3Smrg (struct NineSwapChain9Ex **)&This->swapchains[i]; 3087ec681f3Smrg 3097ec681f3Smrg if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); 3107ec681f3Smrg /* when this is a Device9Ex, it should create SwapChain9Exs */ 3117ec681f3Smrg hr = NineSwapChain9Ex_new(This, TRUE, present, 3127ec681f3Smrg &pPresentationParameters[i], pCTX, 3137ec681f3Smrg This->params.hFocusWindow, mode, ret); 3147ec681f3Smrg } else { 3157ec681f3Smrg hr = NineSwapChain9_new(This, TRUE, present, 3167ec681f3Smrg &pPresentationParameters[i], pCTX, 3177ec681f3Smrg This->params.hFocusWindow, 3187ec681f3Smrg &This->swapchains[i]); 3197ec681f3Smrg } 3207ec681f3Smrg 3217ec681f3Smrg ID3DPresent_Release(present); 3227ec681f3Smrg if (FAILED(hr)) 3237ec681f3Smrg return hr; 3247ec681f3Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i])); 3257ec681f3Smrg 3267ec681f3Smrg hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0, 3277ec681f3Smrg D3DBACKBUFFER_TYPE_MONO, 3287ec681f3Smrg (IDirect3DSurface9 **) 3297ec681f3Smrg &This->state.rt[i]); 3307ec681f3Smrg if (FAILED(hr)) 3317ec681f3Smrg return hr; 3327ec681f3Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i])); 3337ec681f3Smrg nine_bind(&This->context.rt[i], This->state.rt[i]); 3347ec681f3Smrg } 3357ec681f3Smrg 3367ec681f3Smrg /* Initialize CSMT */ 3377ec681f3Smrg /* r600, radeonsi and iris are thread safe. */ 3387ec681f3Smrg if (pCTX->csmt_force == 1) 3397ec681f3Smrg This->csmt_active = true; 3407ec681f3Smrg else if (pCTX->csmt_force == 0) 3417ec681f3Smrg This->csmt_active = false; 3427ec681f3Smrg else if (strstr(pScreen->get_name(pScreen), "AMD") != NULL) 3437ec681f3Smrg This->csmt_active = true; 3447ec681f3Smrg else if (strstr(pScreen->get_name(pScreen), "Intel") != NULL) 3457ec681f3Smrg This->csmt_active = true; 3467ec681f3Smrg 3477ec681f3Smrg /* We rely on u_upload_mgr using persistent coherent buffers (which don't 3487ec681f3Smrg * require flush to work in multi-pipe_context scenario) for vertex and 3497ec681f3Smrg * index buffers */ 3507ec681f3Smrg if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT)) 3517ec681f3Smrg This->csmt_active = false; 3527ec681f3Smrg 3537ec681f3Smrg if (This->csmt_active) { 3547ec681f3Smrg This->csmt_ctx = nine_csmt_create(This); 3557ec681f3Smrg if (!This->csmt_ctx) 3567ec681f3Smrg return E_OUTOFMEMORY; 3577ec681f3Smrg } 3587ec681f3Smrg 3597ec681f3Smrg if (This->csmt_active) 3607ec681f3Smrg DBG("\033[1;32mCSMT is active\033[0m\n"); 3617ec681f3Smrg 3627ec681f3Smrg This->workarounds.dynamic_texture_workaround = pCTX->dynamic_texture_workaround; 3637ec681f3Smrg 3647ec681f3Smrg /* Due to the pb_cache, in some cases the buffer_upload path can increase GTT usage/virtual memory. 3657ec681f3Smrg * As the performance gain is negligible when csmt is off, disable it in this case. 3667ec681f3Smrg * That way csmt_force=0 can be used as a workaround to reduce GTT usage/virtual memory. */ 3677ec681f3Smrg This->buffer_upload = This->csmt_active ? nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4) : NULL; 3687ec681f3Smrg 3697ec681f3Smrg /* Initialize a dummy VBO to be used when a vertex declaration does not 3707ec681f3Smrg * specify all the inputs needed by vertex shader, on win default behavior 3717ec681f3Smrg * is to pass 0,0,0,0 to the shader */ 3727ec681f3Smrg { 3737ec681f3Smrg struct pipe_transfer *transfer; 3747ec681f3Smrg struct pipe_resource tmpl; 3757ec681f3Smrg struct pipe_box box; 3767ec681f3Smrg unsigned char *data; 3777ec681f3Smrg 3787ec681f3Smrg memset(&tmpl, 0, sizeof(tmpl)); 3797ec681f3Smrg tmpl.target = PIPE_BUFFER; 3807ec681f3Smrg tmpl.format = PIPE_FORMAT_R8_UNORM; 3817ec681f3Smrg tmpl.width0 = 16; /* 4 floats */ 3827ec681f3Smrg tmpl.height0 = 1; 3837ec681f3Smrg tmpl.depth0 = 1; 3847ec681f3Smrg tmpl.array_size = 1; 3857ec681f3Smrg tmpl.last_level = 0; 3867ec681f3Smrg tmpl.nr_samples = 0; 3877ec681f3Smrg tmpl.usage = PIPE_USAGE_DEFAULT; 3887ec681f3Smrg tmpl.bind = PIPE_BIND_VERTEX_BUFFER; 3897ec681f3Smrg tmpl.flags = 0; 3907ec681f3Smrg This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl); 3917ec681f3Smrg 3927ec681f3Smrg if (!This->dummy_vbo) 3937ec681f3Smrg return D3DERR_OUTOFVIDEOMEMORY; 3947ec681f3Smrg 3957ec681f3Smrg u_box_1d(0, 16, &box); 3967ec681f3Smrg data = This->context.pipe->buffer_map(This->context.pipe, This->dummy_vbo, 0, 3977ec681f3Smrg PIPE_MAP_WRITE | 3987ec681f3Smrg PIPE_MAP_DISCARD_WHOLE_RESOURCE, 3997ec681f3Smrg &box, &transfer); 4007ec681f3Smrg assert(data); 4017ec681f3Smrg assert(transfer); 4027ec681f3Smrg memset(data, 0, 16); 4037ec681f3Smrg This->context.pipe->buffer_unmap(This->context.pipe, transfer); 4047ec681f3Smrg } 4057ec681f3Smrg 4067ec681f3Smrg This->cursor.software = FALSE; 4077ec681f3Smrg This->cursor.hotspot.x = -1; 4087ec681f3Smrg This->cursor.hotspot.y = -1; 4097ec681f3Smrg This->cursor.w = This->cursor.h = 0; 4107ec681f3Smrg This->cursor.visible = FALSE; 4117ec681f3Smrg if (ID3DPresent_GetCursorPos(This->swapchains[0]->present, &This->cursor.pos) != S_OK) { 4127ec681f3Smrg This->cursor.pos.x = 0; 4137ec681f3Smrg This->cursor.pos.y = 0; 4147ec681f3Smrg } 4157ec681f3Smrg 4167ec681f3Smrg { 4177ec681f3Smrg struct pipe_resource tmpl; 4187ec681f3Smrg memset(&tmpl, 0, sizeof(tmpl)); 4197ec681f3Smrg tmpl.target = PIPE_TEXTURE_2D; 4207ec681f3Smrg tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; 4217ec681f3Smrg tmpl.width0 = 64; 4227ec681f3Smrg tmpl.height0 = 64; 4237ec681f3Smrg tmpl.depth0 = 1; 4247ec681f3Smrg tmpl.array_size = 1; 4257ec681f3Smrg tmpl.last_level = 0; 4267ec681f3Smrg tmpl.nr_samples = 0; 4277ec681f3Smrg tmpl.usage = PIPE_USAGE_DEFAULT; 4287ec681f3Smrg tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW; 4297ec681f3Smrg tmpl.flags = 0; 4307ec681f3Smrg 4317ec681f3Smrg This->cursor.image = pScreen->resource_create(pScreen, &tmpl); 4327ec681f3Smrg if (!This->cursor.image) 4337ec681f3Smrg return D3DERR_OUTOFVIDEOMEMORY; 4347ec681f3Smrg 4357ec681f3Smrg /* For uploading 32x32 (argb) cursor */ 4367ec681f3Smrg This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32); 4377ec681f3Smrg if (!This->cursor.hw_upload_temp) 4387ec681f3Smrg return D3DERR_OUTOFVIDEOMEMORY; 4397ec681f3Smrg } 4407ec681f3Smrg 4417ec681f3Smrg /* Create constant buffers. */ 4427ec681f3Smrg { 4437ec681f3Smrg unsigned max_const_vs, max_const_ps; 4447ec681f3Smrg 4457ec681f3Smrg /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots, 4467ec681f3Smrg * we have to take in some more slots for int and bool*/ 4477ec681f3Smrg max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, 4487ec681f3Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / 4497ec681f3Smrg sizeof(float[4]), 4507ec681f3Smrg NINE_MAX_CONST_ALL); 4517ec681f3Smrg /* ps 3.0: 224 float constants. All cards supported support at least 4527ec681f3Smrg * 256 constants for ps */ 4537ec681f3Smrg max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 4547ec681f3Smrg 4557ec681f3Smrg This->max_vs_const_f = max_const_vs - 4567ec681f3Smrg (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 4577ec681f3Smrg This->max_ps_const_f = max_const_ps - 4587ec681f3Smrg (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 4597ec681f3Smrg 4607ec681f3Smrg This->vs_const_size = max_const_vs * sizeof(float[4]); 4617ec681f3Smrg This->ps_const_size = max_const_ps * sizeof(float[4]); 4627ec681f3Smrg /* Include space for I,B constants for user constbuf. */ 4637ec681f3Smrg if (This->may_swvp) { 4647ec681f3Smrg This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 4657ec681f3Smrg This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 4667ec681f3Smrg if (!This->context.vs_const_f_swvp) 4677ec681f3Smrg return E_OUTOFMEMORY; 4687ec681f3Smrg This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 4697ec681f3Smrg This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 4707ec681f3Smrg This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); 4717ec681f3Smrg This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); 4727ec681f3Smrg This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); 4737ec681f3Smrg This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); 4747ec681f3Smrg } else { 4757ec681f3Smrg This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1); 4767ec681f3Smrg This->context.vs_const_f_swvp = NULL; 4777ec681f3Smrg This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1); 4787ec681f3Smrg This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1); 4797ec681f3Smrg This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); 4807ec681f3Smrg This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); 4817ec681f3Smrg This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); 4827ec681f3Smrg This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); 4837ec681f3Smrg } 4847ec681f3Smrg This->context.vs_const_f = CALLOC(This->vs_const_size, 1); 4857ec681f3Smrg This->state.ps_const_f = CALLOC(This->ps_const_size, 1); 4867ec681f3Smrg This->context.ps_const_f = CALLOC(This->ps_const_size, 1); 4877ec681f3Smrg This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1); 4887ec681f3Smrg if (!This->state.vs_const_f || !This->context.vs_const_f || 4897ec681f3Smrg !This->state.ps_const_f || !This->context.ps_const_f || 4907ec681f3Smrg !This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp || 4917ec681f3Smrg !This->context.ps_lconstf_temp || 4927ec681f3Smrg !This->state.vs_const_i || !This->context.vs_const_i || 4937ec681f3Smrg !This->state.vs_const_b || !This->context.vs_const_b) 4947ec681f3Smrg return E_OUTOFMEMORY; 4957ec681f3Smrg 4967ec681f3Smrg if (strstr(pScreen->get_name(pScreen), "AMD") || 4977ec681f3Smrg strstr(pScreen->get_name(pScreen), "ATI")) { 4987ec681f3Smrg This->driver_bugs.buggy_barycentrics = TRUE; 4997ec681f3Smrg } 5007ec681f3Smrg } 5017ec681f3Smrg 5027ec681f3Smrg /* allocate dummy texture/sampler for when there are missing ones bound */ 5037ec681f3Smrg { 5047ec681f3Smrg struct pipe_resource tmplt; 5057ec681f3Smrg struct pipe_sampler_view templ; 5067ec681f3Smrg struct pipe_sampler_state samp; 5077ec681f3Smrg memset(&tmplt, 0, sizeof(tmplt)); 5087ec681f3Smrg memset(&samp, 0, sizeof(samp)); 5097ec681f3Smrg 5107ec681f3Smrg tmplt.target = PIPE_TEXTURE_2D; 5117ec681f3Smrg tmplt.width0 = 1; 5127ec681f3Smrg tmplt.height0 = 1; 5137ec681f3Smrg tmplt.depth0 = 1; 5147ec681f3Smrg tmplt.last_level = 0; 5157ec681f3Smrg tmplt.array_size = 1; 5167ec681f3Smrg tmplt.usage = PIPE_USAGE_DEFAULT; 5177ec681f3Smrg tmplt.flags = 0; 5187ec681f3Smrg tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; 5197ec681f3Smrg tmplt.bind = PIPE_BIND_SAMPLER_VIEW; 5207ec681f3Smrg tmplt.nr_samples = 0; 5217ec681f3Smrg 5227ec681f3Smrg This->dummy_texture = This->screen->resource_create(This->screen, &tmplt); 5237ec681f3Smrg if (!This->dummy_texture) 5247ec681f3Smrg return D3DERR_DRIVERINTERNALERROR; 5257ec681f3Smrg 5267ec681f3Smrg templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; 5277ec681f3Smrg templ.u.tex.first_layer = 0; 5287ec681f3Smrg templ.u.tex.last_layer = 0; 5297ec681f3Smrg templ.u.tex.first_level = 0; 5307ec681f3Smrg templ.u.tex.last_level = 0; 5317ec681f3Smrg templ.swizzle_r = PIPE_SWIZZLE_0; 5327ec681f3Smrg templ.swizzle_g = PIPE_SWIZZLE_0; 5337ec681f3Smrg templ.swizzle_b = PIPE_SWIZZLE_0; 5347ec681f3Smrg templ.swizzle_a = PIPE_SWIZZLE_1; 5357ec681f3Smrg templ.target = This->dummy_texture->target; 5367ec681f3Smrg 5377ec681f3Smrg This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ); 5387ec681f3Smrg if (!This->dummy_sampler_view) 5397ec681f3Smrg return D3DERR_DRIVERINTERNALERROR; 5407ec681f3Smrg 5417ec681f3Smrg samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 5427ec681f3Smrg samp.max_lod = 15.0f; 5437ec681f3Smrg samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 5447ec681f3Smrg samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 5457ec681f3Smrg samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 5467ec681f3Smrg samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; 5477ec681f3Smrg samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 5487ec681f3Smrg samp.compare_mode = PIPE_TEX_COMPARE_NONE; 5497ec681f3Smrg samp.compare_func = PIPE_FUNC_LEQUAL; 5507ec681f3Smrg samp.normalized_coords = 1; 5517ec681f3Smrg samp.seamless_cube_map = 0; 5527ec681f3Smrg This->dummy_sampler_state = samp; 5537ec681f3Smrg } 5547ec681f3Smrg 5557ec681f3Smrg /* Allocate upload helper for drivers that suck (from st pov ;). */ 5567ec681f3Smrg 5577ec681f3Smrg This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS); 5587ec681f3Smrg This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader; 5597ec681f3Smrg This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION); 5607ec681f3Smrg This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); 5617ec681f3Smrg This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); 5627ec681f3Smrg This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED); 5637ec681f3Smrg 5647ec681f3Smrg This->context.inline_constants = pCTX->shader_inline_constants; 5657ec681f3Smrg /* Code would be needed when integers are not available to correctly 5667ec681f3Smrg * handle the conversion of integer constants */ 5677ec681f3Smrg This->context.inline_constants &= This->driver_caps.vs_integer && This->driver_caps.ps_integer; 5687ec681f3Smrg 5697ec681f3Smrg nine_ff_init(This); /* initialize fixed function code */ 5707ec681f3Smrg 5717ec681f3Smrg NineDevice9_SetDefaultState(This, FALSE); 5727ec681f3Smrg 5737ec681f3Smrg { 5747ec681f3Smrg struct pipe_poly_stipple stipple; 5757ec681f3Smrg memset(&stipple, ~0, sizeof(stipple)); 5767ec681f3Smrg This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple); 5777ec681f3Smrg } 5787ec681f3Smrg 5797ec681f3Smrg This->update = &This->state; 5807ec681f3Smrg 5817ec681f3Smrg nine_state_init_sw(This); 5827ec681f3Smrg 5837ec681f3Smrg ID3DPresentGroup_Release(This->present); 5847ec681f3Smrg nine_context_update_state(This); /* Some drivers needs states to be initialized */ 5857ec681f3Smrg nine_csmt_process(This); 5867ec681f3Smrg 5877ec681f3Smrg if (This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE) 5887ec681f3Smrg nine_setup_set_fpu(fpu_cw); 5897ec681f3Smrg 5907ec681f3Smrg return D3D_OK; 5917ec681f3Smrg} 5927ec681f3Smrg#undef GET_PCAP 5937ec681f3Smrg 5947ec681f3Smrgvoid 5957ec681f3SmrgNineDevice9_dtor( struct NineDevice9 *This ) 5967ec681f3Smrg{ 5977ec681f3Smrg unsigned i; 5987ec681f3Smrg 5997ec681f3Smrg DBG("This=%p\n", This); 6007ec681f3Smrg 6017ec681f3Smrg /* Flush all pending commands to get refcount right, 6027ec681f3Smrg * and properly release bound objects. It is ok to still 6037ec681f3Smrg * execute commands while we are in device dtor, because 6047ec681f3Smrg * we haven't released anything yet. Note that no pending 6057ec681f3Smrg * command can increase the device refcount. */ 6067ec681f3Smrg if (This->csmt_active && This->csmt_ctx) { 6077ec681f3Smrg nine_csmt_process(This); 6087ec681f3Smrg nine_csmt_destroy(This, This->csmt_ctx); 6097ec681f3Smrg This->csmt_active = FALSE; 6107ec681f3Smrg This->csmt_ctx = NULL; 6117ec681f3Smrg } 6127ec681f3Smrg 6137ec681f3Smrg nine_ff_fini(This); 6147ec681f3Smrg nine_state_destroy_sw(This); 6157ec681f3Smrg nine_device_state_clear(This); 6167ec681f3Smrg nine_context_clear(This); 6177ec681f3Smrg 6187ec681f3Smrg nine_bind(&This->record, NULL); 6197ec681f3Smrg 6207ec681f3Smrg pipe_sampler_view_reference(&This->dummy_sampler_view, NULL); 6217ec681f3Smrg pipe_resource_reference(&This->dummy_texture, NULL); 6227ec681f3Smrg pipe_resource_reference(&This->dummy_vbo, NULL); 6237ec681f3Smrg FREE(This->state.vs_const_f); 6247ec681f3Smrg FREE(This->context.vs_const_f); 6257ec681f3Smrg FREE(This->state.ps_const_f); 6267ec681f3Smrg FREE(This->context.ps_const_f); 6277ec681f3Smrg FREE(This->state.vs_lconstf_temp); 6287ec681f3Smrg FREE(This->context.vs_lconstf_temp); 6297ec681f3Smrg FREE(This->context.ps_lconstf_temp); 6307ec681f3Smrg FREE(This->state.vs_const_i); 6317ec681f3Smrg FREE(This->context.vs_const_i); 6327ec681f3Smrg FREE(This->state.vs_const_b); 6337ec681f3Smrg FREE(This->context.vs_const_b); 6347ec681f3Smrg FREE(This->context.vs_const_f_swvp); 6357ec681f3Smrg 6367ec681f3Smrg pipe_resource_reference(&This->cursor.image, NULL); 6377ec681f3Smrg FREE(This->cursor.hw_upload_temp); 6387ec681f3Smrg 6397ec681f3Smrg if (This->swapchains) { 6407ec681f3Smrg for (i = 0; i < This->nswapchains; ++i) 6417ec681f3Smrg if (This->swapchains[i]) 6427ec681f3Smrg NineUnknown_Unbind(NineUnknown(This->swapchains[i])); 6437ec681f3Smrg FREE(This->swapchains); 6447ec681f3Smrg } 6457ec681f3Smrg 6467ec681f3Smrg if (This->buffer_upload) 6477ec681f3Smrg nine_upload_destroy(This->buffer_upload); 6487ec681f3Smrg 6497ec681f3Smrg if (This->allocator) 6507ec681f3Smrg nine_allocator_destroy(This->allocator); 6517ec681f3Smrg 6527ec681f3Smrg /* Destroy cso first */ 6537ec681f3Smrg if (This->context.cso) { cso_destroy_context(This->context.cso); } 6547ec681f3Smrg if (This->cso_sw) { cso_destroy_context(This->cso_sw); } 6557ec681f3Smrg if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); } 6567ec681f3Smrg if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); } 6577ec681f3Smrg if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); } 6587ec681f3Smrg 6597ec681f3Smrg if (This->present) { ID3DPresentGroup_Release(This->present); } 6607ec681f3Smrg if (This->d3d9) { IDirect3D9_Release(This->d3d9); } 6617ec681f3Smrg 6627ec681f3Smrg NineUnknown_dtor(&This->base); 6637ec681f3Smrg glsl_type_singleton_decref(); 6647ec681f3Smrg} 6657ec681f3Smrg 6667ec681f3Smrgstruct pipe_screen * 6677ec681f3SmrgNineDevice9_GetScreen( struct NineDevice9 *This ) 6687ec681f3Smrg{ 6697ec681f3Smrg return This->screen; 6707ec681f3Smrg} 6717ec681f3Smrg 6727ec681f3Smrgstruct pipe_context * 6737ec681f3SmrgNineDevice9_GetPipe( struct NineDevice9 *This ) 6747ec681f3Smrg{ 6757ec681f3Smrg return nine_context_get_pipe(This); 6767ec681f3Smrg} 6777ec681f3Smrg 6787ec681f3Smrgconst D3DCAPS9 * 6797ec681f3SmrgNineDevice9_GetCaps( struct NineDevice9 *This ) 6807ec681f3Smrg{ 6817ec681f3Smrg return &This->caps; 6827ec681f3Smrg} 6837ec681f3Smrg 6847ec681f3Smrgstatic inline void 6857ec681f3SmrgNineDevice9_PauseRecording( struct NineDevice9 *This ) 6867ec681f3Smrg{ 6877ec681f3Smrg if (This->record) { 6887ec681f3Smrg This->update = &This->state; 6897ec681f3Smrg This->is_recording = FALSE; 6907ec681f3Smrg } 6917ec681f3Smrg} 6927ec681f3Smrg 6937ec681f3Smrgstatic inline void 6947ec681f3SmrgNineDevice9_ResumeRecording( struct NineDevice9 *This ) 6957ec681f3Smrg{ 6967ec681f3Smrg if (This->record) { 6977ec681f3Smrg This->update = &This->record->state; 6987ec681f3Smrg This->is_recording = TRUE; 6997ec681f3Smrg } 7007ec681f3Smrg} 7017ec681f3Smrg 7027ec681f3SmrgHRESULT NINE_WINAPI 7037ec681f3SmrgNineDevice9_TestCooperativeLevel( struct NineDevice9 *This ) 7047ec681f3Smrg{ 7057ec681f3Smrg if (NineSwapChain9_GetOccluded(This->swapchains[0])) { 7067ec681f3Smrg This->device_needs_reset = TRUE; 7077ec681f3Smrg return D3DERR_DEVICELOST; 7087ec681f3Smrg } else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) { 7097ec681f3Smrg This->device_needs_reset = TRUE; 7107ec681f3Smrg return D3DERR_DEVICENOTRESET; 7117ec681f3Smrg } else if (This->device_needs_reset) { 7127ec681f3Smrg return D3DERR_DEVICENOTRESET; 7137ec681f3Smrg } 7147ec681f3Smrg 7157ec681f3Smrg return D3D_OK; 7167ec681f3Smrg} 7177ec681f3Smrg 7187ec681f3SmrgUINT NINE_WINAPI 7197ec681f3SmrgNineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) 7207ec681f3Smrg{ 7217ec681f3Smrg /* To prevent overflows - Not sure how this should be handled */ 7227ec681f3Smrg return (UINT)MIN2(This->available_texture_mem, (long long)(UINT_MAX - (64 << 20))); /* 64 MB margin */ 7237ec681f3Smrg} 7247ec681f3Smrg 7257ec681f3Smrgvoid 7267ec681f3SmrgNineDevice9_EvictManagedResourcesInternal( struct NineDevice9 *This ) 7277ec681f3Smrg{ 7287ec681f3Smrg struct NineBaseTexture9 *tex; 7297ec681f3Smrg 7307ec681f3Smrg DBG("This=%p\n", This); 7317ec681f3Smrg 7327ec681f3Smrg /* This function is called internally when an allocation fails. 7337ec681f3Smrg * We are supposed to release old unused managed textures/buffers, 7347ec681f3Smrg * until we have enough space for the allocation. 7357ec681f3Smrg * For now just release everything, except the bound textures, 7367ec681f3Smrg * as this function can be called when uploading bound textures. 7377ec681f3Smrg */ 7387ec681f3Smrg LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) { 7397ec681f3Smrg if (!tex->bind_count) 7407ec681f3Smrg NineBaseTexture9_UnLoad(tex); 7417ec681f3Smrg } 7427ec681f3Smrg} 7437ec681f3Smrg 7447ec681f3SmrgHRESULT NINE_WINAPI 7457ec681f3SmrgNineDevice9_EvictManagedResources( struct NineDevice9 *This ) 7467ec681f3Smrg{ 7477ec681f3Smrg struct NineBaseTexture9 *tex; 7487ec681f3Smrg struct NineBuffer9 *buf; 7497ec681f3Smrg 7507ec681f3Smrg DBG("This=%p\n", This); 7517ec681f3Smrg LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) { 7527ec681f3Smrg NineBaseTexture9_UnLoad(tex); 7537ec681f3Smrg } 7547ec681f3Smrg /* Vertex/index buffers don't take a lot of space and aren't accounted 7557ec681f3Smrg * for d3d memory usage. Instead of actually freeing from memory, 7567ec681f3Smrg * just mark the buffer dirty to trigger a re-upload later. We 7577ec681f3Smrg * could just ignore, but some bad behaving apps could rely on it (if 7587ec681f3Smrg * they write outside the locked regions typically). */ 7597ec681f3Smrg LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) { 7607ec681f3Smrg NineBuffer9_SetDirty(buf); 7617ec681f3Smrg } 7627ec681f3Smrg 7637ec681f3Smrg return D3D_OK; 7647ec681f3Smrg} 7657ec681f3Smrg 7667ec681f3SmrgHRESULT NINE_WINAPI 7677ec681f3SmrgNineDevice9_GetDirect3D( struct NineDevice9 *This, 7687ec681f3Smrg IDirect3D9 **ppD3D9 ) 7697ec681f3Smrg{ 7707ec681f3Smrg user_assert(ppD3D9 != NULL, E_POINTER); 7717ec681f3Smrg IDirect3D9_AddRef(This->d3d9); 7727ec681f3Smrg *ppD3D9 = This->d3d9; 7737ec681f3Smrg return D3D_OK; 7747ec681f3Smrg} 7757ec681f3Smrg 7767ec681f3SmrgHRESULT NINE_WINAPI 7777ec681f3SmrgNineDevice9_GetDeviceCaps( struct NineDevice9 *This, 7787ec681f3Smrg D3DCAPS9 *pCaps ) 7797ec681f3Smrg{ 7807ec681f3Smrg user_assert(pCaps != NULL, D3DERR_INVALIDCALL); 7817ec681f3Smrg *pCaps = This->caps; 7827ec681f3Smrg return D3D_OK; 7837ec681f3Smrg} 7847ec681f3Smrg 7857ec681f3SmrgHRESULT NINE_WINAPI 7867ec681f3SmrgNineDevice9_GetDisplayMode( struct NineDevice9 *This, 7877ec681f3Smrg UINT iSwapChain, 7887ec681f3Smrg D3DDISPLAYMODE *pMode ) 7897ec681f3Smrg{ 7907ec681f3Smrg DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode); 7917ec681f3Smrg 7927ec681f3Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 7937ec681f3Smrg 7947ec681f3Smrg return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode); 7957ec681f3Smrg} 7967ec681f3Smrg 7977ec681f3SmrgHRESULT NINE_WINAPI 7987ec681f3SmrgNineDevice9_GetCreationParameters( struct NineDevice9 *This, 7997ec681f3Smrg D3DDEVICE_CREATION_PARAMETERS *pParameters ) 8007ec681f3Smrg{ 8017ec681f3Smrg user_assert(pParameters != NULL, D3DERR_INVALIDCALL); 8027ec681f3Smrg *pParameters = This->params; 8037ec681f3Smrg return D3D_OK; 8047ec681f3Smrg} 8057ec681f3Smrg 8067ec681f3SmrgHRESULT NINE_WINAPI 8077ec681f3SmrgNineDevice9_SetCursorProperties( struct NineDevice9 *This, 8087ec681f3Smrg UINT XHotSpot, 8097ec681f3Smrg UINT YHotSpot, 8107ec681f3Smrg IDirect3DSurface9 *pCursorBitmap ) 8117ec681f3Smrg{ 8127ec681f3Smrg struct NineSurface9 *surf = NineSurface9(pCursorBitmap); 8137ec681f3Smrg struct pipe_context *pipe = NineDevice9_GetPipe(This); 8147ec681f3Smrg struct pipe_box box; 8157ec681f3Smrg struct pipe_transfer *transfer; 8167ec681f3Smrg BOOL hw_cursor; 8177ec681f3Smrg void *ptr; 8187ec681f3Smrg 8197ec681f3Smrg DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u " 8207ec681f3Smrg "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap); 8217ec681f3Smrg 8227ec681f3Smrg user_assert(pCursorBitmap, D3DERR_INVALIDCALL); 8237ec681f3Smrg user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL); 8247ec681f3Smrg 8257ec681f3Smrg if (This->swapchains[0]->params.Windowed) { 8267ec681f3Smrg This->cursor.w = MIN2(surf->desc.Width, 32); 8277ec681f3Smrg This->cursor.h = MIN2(surf->desc.Height, 32); 8287ec681f3Smrg hw_cursor = 1; /* always use hw cursor for windowed mode */ 8297ec681f3Smrg } else { 8307ec681f3Smrg This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0); 8317ec681f3Smrg This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0); 8327ec681f3Smrg hw_cursor = This->cursor.w == 32 && This->cursor.h == 32; 8337ec681f3Smrg } 8347ec681f3Smrg 8357ec681f3Smrg u_box_origin_2d(This->cursor.w, This->cursor.h, &box); 8367ec681f3Smrg 8377ec681f3Smrg ptr = pipe->texture_map(pipe, This->cursor.image, 0, 8387ec681f3Smrg PIPE_MAP_WRITE | 8397ec681f3Smrg PIPE_MAP_DISCARD_WHOLE_RESOURCE, 8407ec681f3Smrg &box, &transfer); 8417ec681f3Smrg if (!ptr) 8427ec681f3Smrg ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR); 8437ec681f3Smrg 8447ec681f3Smrg This->cursor.hotspot.x = XHotSpot; 8457ec681f3Smrg This->cursor.hotspot.y = YHotSpot; 8467ec681f3Smrg 8477ec681f3Smrg /* Copy cursor image to internal storage. */ 8487ec681f3Smrg { 8497ec681f3Smrg D3DLOCKED_RECT lock; 8507ec681f3Smrg HRESULT hr; 8517ec681f3Smrg 8527ec681f3Smrg hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY); 8537ec681f3Smrg if (FAILED(hr)) 8547ec681f3Smrg ret_err("Failed to map cursor source image.\n", 8557ec681f3Smrg D3DERR_DRIVERINTERNALERROR); 8567ec681f3Smrg 8577ec681f3Smrg util_format_unpack_rgba_8unorm_rect(surf->base.info.format, ptr, transfer->stride, 8587ec681f3Smrg lock.pBits, lock.Pitch, 8597ec681f3Smrg This->cursor.w, This->cursor.h); 8607ec681f3Smrg 8617ec681f3Smrg if (hw_cursor) { 8627ec681f3Smrg void *data = lock.pBits; 8637ec681f3Smrg /* SetCursor assumes 32x32 argb with pitch 128 */ 8647ec681f3Smrg if (lock.Pitch != 128) { 8657ec681f3Smrg util_format_unpack_rgba_8unorm_rect(surf->base.info.format, 8667ec681f3Smrg This->cursor.hw_upload_temp, 128, 8677ec681f3Smrg lock.pBits, lock.Pitch, 8687ec681f3Smrg 32, 32); 8697ec681f3Smrg data = This->cursor.hw_upload_temp; 8707ec681f3Smrg } 8717ec681f3Smrg hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present, 8727ec681f3Smrg data, 8737ec681f3Smrg &This->cursor.hotspot, 8747ec681f3Smrg This->cursor.visible) == D3D_OK; 8757ec681f3Smrg } 8767ec681f3Smrg 8777ec681f3Smrg NineSurface9_UnlockRect(surf); 8787ec681f3Smrg } 8797ec681f3Smrg pipe->texture_unmap(pipe, transfer); 8807ec681f3Smrg 8817ec681f3Smrg /* hide cursor if we emulate it */ 8827ec681f3Smrg if (!hw_cursor) 8837ec681f3Smrg ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE); 8847ec681f3Smrg This->cursor.software = !hw_cursor; 8857ec681f3Smrg 8867ec681f3Smrg return D3D_OK; 8877ec681f3Smrg} 8887ec681f3Smrg 8897ec681f3Smrgvoid NINE_WINAPI 8907ec681f3SmrgNineDevice9_SetCursorPosition( struct NineDevice9 *This, 8917ec681f3Smrg int X, 8927ec681f3Smrg int Y, 8937ec681f3Smrg DWORD Flags ) 8947ec681f3Smrg{ 8957ec681f3Smrg struct NineSwapChain9 *swap = This->swapchains[0]; 8967ec681f3Smrg 8977ec681f3Smrg DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags); 8987ec681f3Smrg 8997ec681f3Smrg /* present >= v1.4 handles this itself */ 9007ec681f3Smrg if (This->minor_version_num < 4) { 9017ec681f3Smrg if (This->cursor.pos.x == X && This->cursor.pos.y == Y) 9027ec681f3Smrg return; 9037ec681f3Smrg } 9047ec681f3Smrg 9057ec681f3Smrg This->cursor.pos.x = X; 9067ec681f3Smrg This->cursor.pos.y = Y; 9077ec681f3Smrg 9087ec681f3Smrg if (!This->cursor.software) 9097ec681f3Smrg This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK; 9107ec681f3Smrg} 9117ec681f3Smrg 9127ec681f3SmrgBOOL NINE_WINAPI 9137ec681f3SmrgNineDevice9_ShowCursor( struct NineDevice9 *This, 9147ec681f3Smrg BOOL bShow ) 9157ec681f3Smrg{ 9167ec681f3Smrg BOOL old = This->cursor.visible; 9177ec681f3Smrg 9187ec681f3Smrg DBG("This=%p bShow=%d\n", This, (int) bShow); 9197ec681f3Smrg 9207ec681f3Smrg /* No-op until a cursor is set in d3d */ 9217ec681f3Smrg if (This->cursor.hotspot.x == -1) 9227ec681f3Smrg return old; 9237ec681f3Smrg 9247ec681f3Smrg This->cursor.visible = bShow; 9257ec681f3Smrg /* Note: Don't optimize by avoiding the call if This->cursor.visible 9267ec681f3Smrg * hasn't changed. One has to keep in mind the app may do SetCursor 9277ec681f3Smrg * calls outside d3d, thus such an optimization affects behaviour. */ 9287ec681f3Smrg if (!This->cursor.software) 9297ec681f3Smrg This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK; 9307ec681f3Smrg 9317ec681f3Smrg return old; 9327ec681f3Smrg} 9337ec681f3Smrg 9347ec681f3SmrgHRESULT NINE_WINAPI 9357ec681f3SmrgNineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, 9367ec681f3Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 9377ec681f3Smrg IDirect3DSwapChain9 **pSwapChain ) 9387ec681f3Smrg{ 9397ec681f3Smrg struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0]; 9407ec681f3Smrg ID3DPresent *present; 9417ec681f3Smrg HRESULT hr; 9427ec681f3Smrg 9437ec681f3Smrg DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n", 9447ec681f3Smrg This, pPresentationParameters, pSwapChain); 9457ec681f3Smrg 9467ec681f3Smrg user_assert(pPresentationParameters, D3DERR_INVALIDCALL); 9477ec681f3Smrg user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); 9487ec681f3Smrg user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL); 9497ec681f3Smrg 9507ec681f3Smrg /* TODO: this deserves more tests */ 9517ec681f3Smrg if (!pPresentationParameters->hDeviceWindow) 9527ec681f3Smrg pPresentationParameters->hDeviceWindow = This->params.hFocusWindow; 9537ec681f3Smrg 9547ec681f3Smrg hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present); 9557ec681f3Smrg 9567ec681f3Smrg if (FAILED(hr)) 9577ec681f3Smrg return hr; 9587ec681f3Smrg 9597ec681f3Smrg hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters, 9607ec681f3Smrg tmplt->actx, 9617ec681f3Smrg tmplt->params.hDeviceWindow, 9627ec681f3Smrg &swapchain); 9637ec681f3Smrg if (FAILED(hr)) 9647ec681f3Smrg return hr; 9657ec681f3Smrg 9667ec681f3Smrg *pSwapChain = (IDirect3DSwapChain9 *)swapchain; 9677ec681f3Smrg return D3D_OK; 9687ec681f3Smrg} 9697ec681f3Smrg 9707ec681f3SmrgHRESULT NINE_WINAPI 9717ec681f3SmrgNineDevice9_GetSwapChain( struct NineDevice9 *This, 9727ec681f3Smrg UINT iSwapChain, 9737ec681f3Smrg IDirect3DSwapChain9 **pSwapChain ) 9747ec681f3Smrg{ 9757ec681f3Smrg user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); 9767ec681f3Smrg 9777ec681f3Smrg *pSwapChain = NULL; 9787ec681f3Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 9797ec681f3Smrg 9807ec681f3Smrg NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain])); 9817ec681f3Smrg *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain]; 9827ec681f3Smrg 9837ec681f3Smrg return D3D_OK; 9847ec681f3Smrg} 9857ec681f3Smrg 9867ec681f3SmrgUINT NINE_WINAPI 9877ec681f3SmrgNineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) 9887ec681f3Smrg{ 9897ec681f3Smrg return This->nswapchains; 9907ec681f3Smrg} 9917ec681f3Smrg 9927ec681f3SmrgHRESULT NINE_WINAPI 9937ec681f3SmrgNineDevice9_Reset( struct NineDevice9 *This, 9947ec681f3Smrg D3DPRESENT_PARAMETERS *pPresentationParameters ) 9957ec681f3Smrg{ 9967ec681f3Smrg HRESULT hr = D3D_OK; 9977ec681f3Smrg unsigned i; 9987ec681f3Smrg 9997ec681f3Smrg DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); 10007ec681f3Smrg 10017ec681f3Smrg user_assert(pPresentationParameters != NULL, D3DERR_INVALIDCALL); 10027ec681f3Smrg 10037ec681f3Smrg if (NineSwapChain9_GetOccluded(This->swapchains[0])) { 10047ec681f3Smrg This->device_needs_reset = TRUE; 10057ec681f3Smrg return D3DERR_DEVICELOST; 10067ec681f3Smrg } 10077ec681f3Smrg 10087ec681f3Smrg for (i = 0; i < This->nswapchains; ++i) { 10097ec681f3Smrg D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; 10107ec681f3Smrg hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL); 10117ec681f3Smrg if (hr != D3D_OK) 10127ec681f3Smrg break; 10137ec681f3Smrg } 10147ec681f3Smrg 10157ec681f3Smrg nine_csmt_process(This); 10167ec681f3Smrg nine_device_state_clear(This); 10177ec681f3Smrg nine_context_clear(This); 10187ec681f3Smrg 10197ec681f3Smrg NineDevice9_SetDefaultState(This, TRUE); 10207ec681f3Smrg NineDevice9_SetRenderTarget( 10217ec681f3Smrg This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]); 10227ec681f3Smrg /* XXX: better use GetBackBuffer here ? */ 10237ec681f3Smrg 10247ec681f3Smrg This->device_needs_reset = (hr != D3D_OK); 10257ec681f3Smrg return hr; 10267ec681f3Smrg} 10277ec681f3Smrg 10287ec681f3SmrgHRESULT NINE_WINAPI 10297ec681f3SmrgNineDevice9_Present( struct NineDevice9 *This, 10307ec681f3Smrg const RECT *pSourceRect, 10317ec681f3Smrg const RECT *pDestRect, 10327ec681f3Smrg HWND hDestWindowOverride, 10337ec681f3Smrg const RGNDATA *pDirtyRegion ) 10347ec681f3Smrg{ 10357ec681f3Smrg unsigned i; 10367ec681f3Smrg HRESULT hr; 10377ec681f3Smrg 10387ec681f3Smrg DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n", 10397ec681f3Smrg This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); 10407ec681f3Smrg 10417ec681f3Smrg /* XXX is this right? */ 10427ec681f3Smrg for (i = 0; i < This->nswapchains; ++i) { 10437ec681f3Smrg hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect, 10447ec681f3Smrg hDestWindowOverride, pDirtyRegion, 0); 10457ec681f3Smrg if (FAILED(hr)) { return hr; } 10467ec681f3Smrg } 10477ec681f3Smrg 10487ec681f3Smrg return D3D_OK; 10497ec681f3Smrg} 10507ec681f3Smrg 10517ec681f3SmrgHRESULT NINE_WINAPI 10527ec681f3SmrgNineDevice9_GetBackBuffer( struct NineDevice9 *This, 10537ec681f3Smrg UINT iSwapChain, 10547ec681f3Smrg UINT iBackBuffer, 10557ec681f3Smrg D3DBACKBUFFER_TYPE Type, 10567ec681f3Smrg IDirect3DSurface9 **ppBackBuffer ) 10577ec681f3Smrg{ 10587ec681f3Smrg user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); 10597ec681f3Smrg /* return NULL on error */ 10607ec681f3Smrg *ppBackBuffer = NULL; 10617ec681f3Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 10627ec681f3Smrg 10637ec681f3Smrg return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain], 10647ec681f3Smrg iBackBuffer, Type, ppBackBuffer); 10657ec681f3Smrg} 10667ec681f3Smrg 10677ec681f3SmrgHRESULT NINE_WINAPI 10687ec681f3SmrgNineDevice9_GetRasterStatus( struct NineDevice9 *This, 10697ec681f3Smrg UINT iSwapChain, 10707ec681f3Smrg D3DRASTER_STATUS *pRasterStatus ) 10717ec681f3Smrg{ 10727ec681f3Smrg user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL); 10737ec681f3Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 10747ec681f3Smrg 10757ec681f3Smrg return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain], 10767ec681f3Smrg pRasterStatus); 10777ec681f3Smrg} 10787ec681f3Smrg 10797ec681f3SmrgHRESULT NINE_WINAPI 10807ec681f3SmrgNineDevice9_SetDialogBoxMode( struct NineDevice9 *This, 10817ec681f3Smrg BOOL bEnableDialogs ) 10827ec681f3Smrg{ 10837ec681f3Smrg STUB(D3DERR_INVALIDCALL); 10847ec681f3Smrg} 10857ec681f3Smrg 10867ec681f3Smrgvoid NINE_WINAPI 10877ec681f3SmrgNineDevice9_SetGammaRamp( struct NineDevice9 *This, 10887ec681f3Smrg UINT iSwapChain, 10897ec681f3Smrg DWORD Flags, 10907ec681f3Smrg const D3DGAMMARAMP *pRamp ) 10917ec681f3Smrg{ 10927ec681f3Smrg DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This, 10937ec681f3Smrg iSwapChain, Flags, pRamp); 10947ec681f3Smrg 10957ec681f3Smrg user_warn(iSwapChain >= This->nswapchains); 10967ec681f3Smrg user_warn(!pRamp); 10977ec681f3Smrg 10987ec681f3Smrg if (pRamp && (iSwapChain < This->nswapchains)) { 10997ec681f3Smrg struct NineSwapChain9 *swap = This->swapchains[iSwapChain]; 11007ec681f3Smrg swap->gamma = *pRamp; 11017ec681f3Smrg ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow); 11027ec681f3Smrg } 11037ec681f3Smrg} 11047ec681f3Smrg 11057ec681f3Smrgvoid NINE_WINAPI 11067ec681f3SmrgNineDevice9_GetGammaRamp( struct NineDevice9 *This, 11077ec681f3Smrg UINT iSwapChain, 11087ec681f3Smrg D3DGAMMARAMP *pRamp ) 11097ec681f3Smrg{ 11107ec681f3Smrg DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp); 11117ec681f3Smrg 11127ec681f3Smrg user_warn(iSwapChain >= This->nswapchains); 11137ec681f3Smrg user_warn(!pRamp); 11147ec681f3Smrg 11157ec681f3Smrg if (pRamp && (iSwapChain < This->nswapchains)) 11167ec681f3Smrg *pRamp = This->swapchains[iSwapChain]->gamma; 11177ec681f3Smrg} 11187ec681f3Smrg 11197ec681f3SmrgHRESULT NINE_WINAPI 11207ec681f3SmrgNineDevice9_CreateTexture( struct NineDevice9 *This, 11217ec681f3Smrg UINT Width, 11227ec681f3Smrg UINT Height, 11237ec681f3Smrg UINT Levels, 11247ec681f3Smrg DWORD Usage, 11257ec681f3Smrg D3DFORMAT Format, 11267ec681f3Smrg D3DPOOL Pool, 11277ec681f3Smrg IDirect3DTexture9 **ppTexture, 11287ec681f3Smrg HANDLE *pSharedHandle ) 11297ec681f3Smrg{ 11307ec681f3Smrg struct NineTexture9 *tex; 11317ec681f3Smrg HRESULT hr; 11327ec681f3Smrg 11337ec681f3Smrg DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " 11347ec681f3Smrg "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels, 11357ec681f3Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 11367ec681f3Smrg nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle); 11377ec681f3Smrg 11387ec681f3Smrg user_assert(ppTexture != NULL, D3DERR_INVALIDCALL); 11397ec681f3Smrg 11407ec681f3Smrg Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP | 11417ec681f3Smrg D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 11427ec681f3Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI; 11437ec681f3Smrg 11447ec681f3Smrg *ppTexture = NULL; 11457ec681f3Smrg 11467ec681f3Smrg hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool, 11477ec681f3Smrg &tex, pSharedHandle); 11487ec681f3Smrg if (SUCCEEDED(hr)) 11497ec681f3Smrg *ppTexture = (IDirect3DTexture9 *)tex; 11507ec681f3Smrg 11517ec681f3Smrg return hr; 11527ec681f3Smrg} 11537ec681f3Smrg 11547ec681f3SmrgHRESULT NINE_WINAPI 11557ec681f3SmrgNineDevice9_CreateVolumeTexture( struct NineDevice9 *This, 11567ec681f3Smrg UINT Width, 11577ec681f3Smrg UINT Height, 11587ec681f3Smrg UINT Depth, 11597ec681f3Smrg UINT Levels, 11607ec681f3Smrg DWORD Usage, 11617ec681f3Smrg D3DFORMAT Format, 11627ec681f3Smrg D3DPOOL Pool, 11637ec681f3Smrg IDirect3DVolumeTexture9 **ppVolumeTexture, 11647ec681f3Smrg HANDLE *pSharedHandle ) 11657ec681f3Smrg{ 11667ec681f3Smrg struct NineVolumeTexture9 *tex; 11677ec681f3Smrg HRESULT hr; 11687ec681f3Smrg 11697ec681f3Smrg DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s " 11707ec681f3Smrg "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels, 11717ec681f3Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 11727ec681f3Smrg nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle); 11737ec681f3Smrg 11747ec681f3Smrg user_assert(ppVolumeTexture != NULL, D3DERR_INVALIDCALL); 11757ec681f3Smrg 11767ec681f3Smrg Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 11777ec681f3Smrg D3DUSAGE_SOFTWAREPROCESSING; 11787ec681f3Smrg 11797ec681f3Smrg *ppVolumeTexture = NULL; 11807ec681f3Smrg 11817ec681f3Smrg hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels, 11827ec681f3Smrg Usage, Format, Pool, &tex, pSharedHandle); 11837ec681f3Smrg if (SUCCEEDED(hr)) 11847ec681f3Smrg *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex; 11857ec681f3Smrg 11867ec681f3Smrg return hr; 11877ec681f3Smrg} 11887ec681f3Smrg 11897ec681f3SmrgHRESULT NINE_WINAPI 11907ec681f3SmrgNineDevice9_CreateCubeTexture( struct NineDevice9 *This, 11917ec681f3Smrg UINT EdgeLength, 11927ec681f3Smrg UINT Levels, 11937ec681f3Smrg DWORD Usage, 11947ec681f3Smrg D3DFORMAT Format, 11957ec681f3Smrg D3DPOOL Pool, 11967ec681f3Smrg IDirect3DCubeTexture9 **ppCubeTexture, 11977ec681f3Smrg HANDLE *pSharedHandle ) 11987ec681f3Smrg{ 11997ec681f3Smrg struct NineCubeTexture9 *tex; 12007ec681f3Smrg HRESULT hr; 12017ec681f3Smrg 12027ec681f3Smrg DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p " 12037ec681f3Smrg "pSharedHandle=%p\n", This, EdgeLength, Levels, 12047ec681f3Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 12057ec681f3Smrg nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle); 12067ec681f3Smrg 12077ec681f3Smrg user_assert(ppCubeTexture != NULL, D3DERR_INVALIDCALL); 12087ec681f3Smrg 12097ec681f3Smrg Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | 12107ec681f3Smrg D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 12117ec681f3Smrg D3DUSAGE_SOFTWAREPROCESSING; 12127ec681f3Smrg 12137ec681f3Smrg *ppCubeTexture = NULL; 12147ec681f3Smrg 12157ec681f3Smrg hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool, 12167ec681f3Smrg &tex, pSharedHandle); 12177ec681f3Smrg if (SUCCEEDED(hr)) 12187ec681f3Smrg *ppCubeTexture = (IDirect3DCubeTexture9 *)tex; 12197ec681f3Smrg 12207ec681f3Smrg return hr; 12217ec681f3Smrg} 12227ec681f3Smrg 12237ec681f3SmrgHRESULT NINE_WINAPI 12247ec681f3SmrgNineDevice9_CreateVertexBuffer( struct NineDevice9 *This, 12257ec681f3Smrg UINT Length, 12267ec681f3Smrg DWORD Usage, 12277ec681f3Smrg DWORD FVF, 12287ec681f3Smrg D3DPOOL Pool, 12297ec681f3Smrg IDirect3DVertexBuffer9 **ppVertexBuffer, 12307ec681f3Smrg HANDLE *pSharedHandle ) 12317ec681f3Smrg{ 12327ec681f3Smrg struct NineVertexBuffer9 *buf; 12337ec681f3Smrg HRESULT hr; 12347ec681f3Smrg D3DVERTEXBUFFER_DESC desc; 12357ec681f3Smrg 12367ec681f3Smrg DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n", 12377ec681f3Smrg This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); 12387ec681f3Smrg 12397ec681f3Smrg user_assert(ppVertexBuffer != NULL, D3DERR_INVALIDCALL); 12407ec681f3Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 12417ec681f3Smrg 12427ec681f3Smrg desc.Format = D3DFMT_VERTEXDATA; 12437ec681f3Smrg desc.Type = D3DRTYPE_VERTEXBUFFER; 12447ec681f3Smrg desc.Usage = Usage & 12457ec681f3Smrg (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 12467ec681f3Smrg D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 12477ec681f3Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI | 12487ec681f3Smrg D3DUSAGE_WRITEONLY); 12497ec681f3Smrg desc.Pool = Pool; 12507ec681f3Smrg desc.Size = Length; 12517ec681f3Smrg desc.FVF = FVF; 12527ec681f3Smrg 12537ec681f3Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 12547ec681f3Smrg user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 12557ec681f3Smrg 12567ec681f3Smrg hr = NineVertexBuffer9_new(This, &desc, &buf); 12577ec681f3Smrg if (SUCCEEDED(hr)) 12587ec681f3Smrg *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf; 12597ec681f3Smrg return hr; 12607ec681f3Smrg} 12617ec681f3Smrg 12627ec681f3SmrgHRESULT NINE_WINAPI 12637ec681f3SmrgNineDevice9_CreateIndexBuffer( struct NineDevice9 *This, 12647ec681f3Smrg UINT Length, 12657ec681f3Smrg DWORD Usage, 12667ec681f3Smrg D3DFORMAT Format, 12677ec681f3Smrg D3DPOOL Pool, 12687ec681f3Smrg IDirect3DIndexBuffer9 **ppIndexBuffer, 12697ec681f3Smrg HANDLE *pSharedHandle ) 12707ec681f3Smrg{ 12717ec681f3Smrg struct NineIndexBuffer9 *buf; 12727ec681f3Smrg HRESULT hr; 12737ec681f3Smrg D3DINDEXBUFFER_DESC desc; 12747ec681f3Smrg 12757ec681f3Smrg DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p " 12767ec681f3Smrg "pSharedHandle=%p\n", This, Length, Usage, 12777ec681f3Smrg d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle); 12787ec681f3Smrg 12797ec681f3Smrg user_assert(ppIndexBuffer != NULL, D3DERR_INVALIDCALL); 12807ec681f3Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 12817ec681f3Smrg 12827ec681f3Smrg desc.Format = Format; 12837ec681f3Smrg desc.Type = D3DRTYPE_INDEXBUFFER; 12847ec681f3Smrg desc.Usage = Usage & 12857ec681f3Smrg (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 12867ec681f3Smrg D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 12877ec681f3Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY); 12887ec681f3Smrg desc.Pool = Pool; 12897ec681f3Smrg desc.Size = Length; 12907ec681f3Smrg 12917ec681f3Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 12927ec681f3Smrg user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 12937ec681f3Smrg 12947ec681f3Smrg hr = NineIndexBuffer9_new(This, &desc, &buf); 12957ec681f3Smrg if (SUCCEEDED(hr)) 12967ec681f3Smrg *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf; 12977ec681f3Smrg return hr; 12987ec681f3Smrg} 12997ec681f3Smrg 13007ec681f3Smrgstatic HRESULT 13017ec681f3Smrgcreate_zs_or_rt_surface(struct NineDevice9 *This, 13027ec681f3Smrg unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */ 13037ec681f3Smrg D3DPOOL Pool, 13047ec681f3Smrg UINT Width, UINT Height, 13057ec681f3Smrg D3DFORMAT Format, 13067ec681f3Smrg D3DMULTISAMPLE_TYPE MultiSample, 13077ec681f3Smrg DWORD MultisampleQuality, 13087ec681f3Smrg BOOL Discard_or_Lockable, 13097ec681f3Smrg IDirect3DSurface9 **ppSurface, 13107ec681f3Smrg HANDLE *pSharedHandle) 13117ec681f3Smrg{ 13127ec681f3Smrg struct NineSurface9 *surface; 13137ec681f3Smrg HRESULT hr; 13147ec681f3Smrg D3DSURFACE_DESC desc; 13157ec681f3Smrg 13167ec681f3Smrg DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u " 13177ec681f3Smrg "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n", 13187ec681f3Smrg This, type, nine_D3DPOOL_to_str(Pool), Width, Height, 13197ec681f3Smrg d3dformat_to_string(Format), MultiSample, MultisampleQuality, 13207ec681f3Smrg Discard_or_Lockable, ppSurface, pSharedHandle); 13217ec681f3Smrg 13227ec681f3Smrg if (pSharedHandle) 13237ec681f3Smrg DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n"); 13247ec681f3Smrg 13257ec681f3Smrg user_assert(Width && Height, D3DERR_INVALIDCALL); 13267ec681f3Smrg user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 13277ec681f3Smrg 13287ec681f3Smrg desc.Format = Format; 13297ec681f3Smrg desc.Type = D3DRTYPE_SURFACE; 13307ec681f3Smrg desc.Usage = 0; 13317ec681f3Smrg desc.Pool = Pool; 13327ec681f3Smrg desc.MultiSampleType = MultiSample; 13337ec681f3Smrg desc.MultiSampleQuality = MultisampleQuality; 13347ec681f3Smrg desc.Width = Width; 13357ec681f3Smrg desc.Height = Height; 13367ec681f3Smrg switch (type) { 13377ec681f3Smrg case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break; 13387ec681f3Smrg case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break; 13397ec681f3Smrg default: assert(type == 2); break; 13407ec681f3Smrg } 13417ec681f3Smrg 13427ec681f3Smrg hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface); 13437ec681f3Smrg if (SUCCEEDED(hr)) { 13447ec681f3Smrg *ppSurface = (IDirect3DSurface9 *)surface; 13457ec681f3Smrg 13467ec681f3Smrg if (surface->base.resource && Discard_or_Lockable && (type != 1)) 13477ec681f3Smrg surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; 13487ec681f3Smrg } 13497ec681f3Smrg 13507ec681f3Smrg return hr; 13517ec681f3Smrg} 13527ec681f3Smrg 13537ec681f3SmrgHRESULT NINE_WINAPI 13547ec681f3SmrgNineDevice9_CreateRenderTarget( struct NineDevice9 *This, 13557ec681f3Smrg UINT Width, 13567ec681f3Smrg UINT Height, 13577ec681f3Smrg D3DFORMAT Format, 13587ec681f3Smrg D3DMULTISAMPLE_TYPE MultiSample, 13597ec681f3Smrg DWORD MultisampleQuality, 13607ec681f3Smrg BOOL Lockable, 13617ec681f3Smrg IDirect3DSurface9 **ppSurface, 13627ec681f3Smrg HANDLE *pSharedHandle ) 13637ec681f3Smrg{ 13647ec681f3Smrg user_assert(ppSurface != NULL, D3DERR_INVALIDCALL); 13657ec681f3Smrg *ppSurface = NULL; 13667ec681f3Smrg return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT, 13677ec681f3Smrg Width, Height, Format, 13687ec681f3Smrg MultiSample, MultisampleQuality, 13697ec681f3Smrg Lockable, ppSurface, pSharedHandle); 13707ec681f3Smrg} 13717ec681f3Smrg 13727ec681f3SmrgHRESULT NINE_WINAPI 13737ec681f3SmrgNineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, 13747ec681f3Smrg UINT Width, 13757ec681f3Smrg UINT Height, 13767ec681f3Smrg D3DFORMAT Format, 13777ec681f3Smrg D3DMULTISAMPLE_TYPE MultiSample, 13787ec681f3Smrg DWORD MultisampleQuality, 13797ec681f3Smrg BOOL Discard, 13807ec681f3Smrg IDirect3DSurface9 **ppSurface, 13817ec681f3Smrg HANDLE *pSharedHandle ) 13827ec681f3Smrg{ 13837ec681f3Smrg user_assert(ppSurface != NULL, D3DERR_INVALIDCALL); 13847ec681f3Smrg *ppSurface = NULL; 13857ec681f3Smrg if (!depth_stencil_format(Format)) 13867ec681f3Smrg return D3DERR_NOTAVAILABLE; 13877ec681f3Smrg return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT, 13887ec681f3Smrg Width, Height, Format, 13897ec681f3Smrg MultiSample, MultisampleQuality, 13907ec681f3Smrg Discard, ppSurface, pSharedHandle); 13917ec681f3Smrg} 13927ec681f3Smrg 13937ec681f3SmrgHRESULT NINE_WINAPI 13947ec681f3SmrgNineDevice9_UpdateSurface( struct NineDevice9 *This, 13957ec681f3Smrg IDirect3DSurface9 *pSourceSurface, 13967ec681f3Smrg const RECT *pSourceRect, 13977ec681f3Smrg IDirect3DSurface9 *pDestinationSurface, 13987ec681f3Smrg const POINT *pDestPoint ) 13997ec681f3Smrg{ 14007ec681f3Smrg struct NineSurface9 *dst = NineSurface9(pDestinationSurface); 14017ec681f3Smrg struct NineSurface9 *src = NineSurface9(pSourceSurface); 14027ec681f3Smrg int copy_width, copy_height; 14037ec681f3Smrg RECT destRect; 14047ec681f3Smrg 14057ec681f3Smrg DBG("This=%p pSourceSurface=%p pDestinationSurface=%p " 14067ec681f3Smrg "pSourceRect=%p pDestPoint=%p\n", This, 14077ec681f3Smrg pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint); 14087ec681f3Smrg if (pSourceRect) 14097ec681f3Smrg DBG("pSourceRect = (%u,%u)-(%u,%u)\n", 14107ec681f3Smrg pSourceRect->left, pSourceRect->top, 14117ec681f3Smrg pSourceRect->right, pSourceRect->bottom); 14127ec681f3Smrg if (pDestPoint) 14137ec681f3Smrg DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y); 14147ec681f3Smrg 14157ec681f3Smrg user_assert(dst && src, D3DERR_INVALIDCALL); 14167ec681f3Smrg 14177ec681f3Smrg user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 14187ec681f3Smrg user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 14197ec681f3Smrg 14207ec681f3Smrg user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 14217ec681f3Smrg user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 14227ec681f3Smrg 14237ec681f3Smrg user_assert(!src->lock_count, D3DERR_INVALIDCALL); 14247ec681f3Smrg user_assert(!dst->lock_count, D3DERR_INVALIDCALL); 14257ec681f3Smrg 14267ec681f3Smrg user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL); 14277ec681f3Smrg user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL); 14287ec681f3Smrg 14297ec681f3Smrg if (pSourceRect) { 14307ec681f3Smrg copy_width = pSourceRect->right - pSourceRect->left; 14317ec681f3Smrg copy_height = pSourceRect->bottom - pSourceRect->top; 14327ec681f3Smrg 14337ec681f3Smrg user_assert(pSourceRect->left >= 0 && 14347ec681f3Smrg copy_width > 0 && 14357ec681f3Smrg pSourceRect->right <= src->desc.Width && 14367ec681f3Smrg pSourceRect->top >= 0 && 14377ec681f3Smrg copy_height > 0 && 14387ec681f3Smrg pSourceRect->bottom <= src->desc.Height, 14397ec681f3Smrg D3DERR_INVALIDCALL); 14407ec681f3Smrg } else { 14417ec681f3Smrg copy_width = src->desc.Width; 14427ec681f3Smrg copy_height = src->desc.Height; 14437ec681f3Smrg } 14447ec681f3Smrg 14457ec681f3Smrg destRect.right = copy_width; 14467ec681f3Smrg destRect.bottom = copy_height; 14477ec681f3Smrg 14487ec681f3Smrg if (pDestPoint) { 14497ec681f3Smrg user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0, 14507ec681f3Smrg D3DERR_INVALIDCALL); 14517ec681f3Smrg destRect.right += pDestPoint->x; 14527ec681f3Smrg destRect.bottom += pDestPoint->y; 14537ec681f3Smrg } 14547ec681f3Smrg 14557ec681f3Smrg user_assert(destRect.right <= dst->desc.Width && 14567ec681f3Smrg destRect.bottom <= dst->desc.Height, 14577ec681f3Smrg D3DERR_INVALIDCALL); 14587ec681f3Smrg 14597ec681f3Smrg if (compressed_format(dst->desc.Format)) { 14607ec681f3Smrg const unsigned w = util_format_get_blockwidth(dst->base.info.format); 14617ec681f3Smrg const unsigned h = util_format_get_blockheight(dst->base.info.format); 14627ec681f3Smrg 14637ec681f3Smrg if (pDestPoint) { 14647ec681f3Smrg user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h), 14657ec681f3Smrg D3DERR_INVALIDCALL); 14667ec681f3Smrg } 14677ec681f3Smrg 14687ec681f3Smrg if (pSourceRect) { 14697ec681f3Smrg user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h), 14707ec681f3Smrg D3DERR_INVALIDCALL); 14717ec681f3Smrg } 14727ec681f3Smrg if (!(copy_width == src->desc.Width && 14737ec681f3Smrg copy_width == dst->desc.Width && 14747ec681f3Smrg copy_height == src->desc.Height && 14757ec681f3Smrg copy_height == dst->desc.Height)) { 14767ec681f3Smrg user_assert(!(copy_width % w) && !(copy_height % h), 14777ec681f3Smrg D3DERR_INVALIDCALL); 14787ec681f3Smrg } 14797ec681f3Smrg } 14807ec681f3Smrg 14817ec681f3Smrg NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect); 14827ec681f3Smrg 14837ec681f3Smrg return D3D_OK; 14847ec681f3Smrg} 14857ec681f3Smrg 14867ec681f3SmrgHRESULT NINE_WINAPI 14877ec681f3SmrgNineDevice9_UpdateTexture( struct NineDevice9 *This, 14887ec681f3Smrg IDirect3DBaseTexture9 *pSourceTexture, 14897ec681f3Smrg IDirect3DBaseTexture9 *pDestinationTexture ) 14907ec681f3Smrg{ 14917ec681f3Smrg struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture); 14927ec681f3Smrg struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture); 14937ec681f3Smrg unsigned l, m; 14947ec681f3Smrg unsigned last_src_level, last_dst_level; 14957ec681f3Smrg RECT rect; 14967ec681f3Smrg 14977ec681f3Smrg DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This, 14987ec681f3Smrg pSourceTexture, pDestinationTexture); 14997ec681f3Smrg 15007ec681f3Smrg user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL); 15017ec681f3Smrg user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL); 15027ec681f3Smrg 15037ec681f3Smrg user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 15047ec681f3Smrg user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 15057ec681f3Smrg user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL); 15067ec681f3Smrg user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) || 15077ec681f3Smrg dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL); 15087ec681f3Smrg 15097ec681f3Smrg /* Spec: Failure if 15107ec681f3Smrg * . Different formats 15117ec681f3Smrg * . Fewer src levels than dst levels (if the opposite, only matching levels 15127ec681f3Smrg * are supposed to be copied) 15137ec681f3Smrg * . Levels do not match 15147ec681f3Smrg * DDI: Actually the above should pass because of legacy applications 15157ec681f3Smrg * Do what you want about these, but you shouldn't crash. 15167ec681f3Smrg * However driver can expect that the top dimension is greater for src than dst. 15177ec681f3Smrg * Wine tests: Every combination that passes the initial checks should pass. 15187ec681f3Smrg * . Different formats => conversion driver and format dependent. 15197ec681f3Smrg * . 1 level, but size not matching => copy is done (and even crash if src bigger 15207ec681f3Smrg * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied 15217ec681f3Smrg * or if a subrect is copied). 15227ec681f3Smrg * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect 15237ec681f3Smrg * copied to 7x7. 15247ec681f3Smrg * 15257ec681f3Smrg * From these, the proposal is: 15267ec681f3Smrg * . Different formats -> use util_format_translate to translate if possible for surfaces. 15277ec681f3Smrg * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations 15287ec681f3Smrg * . First level copied -> the first level such that src is smaller or equal to dst first level 15297ec681f3Smrg * . number of levels copied -> as long as it fits and textures have levels 15307ec681f3Smrg * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK) 15317ec681f3Smrg */ 15327ec681f3Smrg 15337ec681f3Smrg last_src_level = srcb->level_count-1; 15347ec681f3Smrg last_dst_level = dstb->level_count-1; 15357ec681f3Smrg 15367ec681f3Smrg for (m = 0; m <= last_src_level; ++m) { 15377ec681f3Smrg unsigned w = u_minify(srcb->base.info.width0, m); 15387ec681f3Smrg unsigned h = u_minify(srcb->base.info.height0, m); 15397ec681f3Smrg unsigned d = u_minify(srcb->base.info.depth0, m); 15407ec681f3Smrg 15417ec681f3Smrg if (w <= dstb->base.info.width0 && 15427ec681f3Smrg h <= dstb->base.info.height0 && 15437ec681f3Smrg d <= dstb->base.info.depth0) 15447ec681f3Smrg break; 15457ec681f3Smrg } 15467ec681f3Smrg user_assert(m <= last_src_level, D3D_OK); 15477ec681f3Smrg 15487ec681f3Smrg last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level); 15497ec681f3Smrg 15507ec681f3Smrg if (dstb->base.type == D3DRTYPE_TEXTURE) { 15517ec681f3Smrg struct NineTexture9 *dst = NineTexture9(dstb); 15527ec681f3Smrg struct NineTexture9 *src = NineTexture9(srcb); 15537ec681f3Smrg 15547ec681f3Smrg if (src->dirty_rect.width == 0) 15557ec681f3Smrg return D3D_OK; 15567ec681f3Smrg 15577ec681f3Smrg pipe_box_to_rect(&rect, &src->dirty_rect); 15587ec681f3Smrg for (l = 0; l < m; ++l) 15597ec681f3Smrg rect_minify_inclusive(&rect); 15607ec681f3Smrg 15617ec681f3Smrg for (l = 0; l <= last_dst_level; ++l, ++m) { 15627ec681f3Smrg fit_rect_format_inclusive(dst->base.base.info.format, 15637ec681f3Smrg &rect, 15647ec681f3Smrg dst->surfaces[l]->desc.Width, 15657ec681f3Smrg dst->surfaces[l]->desc.Height); 15667ec681f3Smrg NineSurface9_CopyMemToDefault(dst->surfaces[l], 15677ec681f3Smrg src->surfaces[m], 15687ec681f3Smrg (POINT *)&rect, 15697ec681f3Smrg &rect); 15707ec681f3Smrg rect_minify_inclusive(&rect); 15717ec681f3Smrg } 15727ec681f3Smrg u_box_origin_2d(0, 0, &src->dirty_rect); 15737ec681f3Smrg } else 15747ec681f3Smrg if (dstb->base.type == D3DRTYPE_CUBETEXTURE) { 15757ec681f3Smrg struct NineCubeTexture9 *dst = NineCubeTexture9(dstb); 15767ec681f3Smrg struct NineCubeTexture9 *src = NineCubeTexture9(srcb); 15777ec681f3Smrg unsigned z; 15787ec681f3Smrg 15797ec681f3Smrg /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */ 15807ec681f3Smrg for (z = 0; z < 6; ++z) { 15817ec681f3Smrg if (src->dirty_rect[z].width == 0) 15827ec681f3Smrg continue; 15837ec681f3Smrg 15847ec681f3Smrg pipe_box_to_rect(&rect, &src->dirty_rect[z]); 15857ec681f3Smrg for (l = 0; l < m; ++l) 15867ec681f3Smrg rect_minify_inclusive(&rect); 15877ec681f3Smrg 15887ec681f3Smrg for (l = 0; l <= last_dst_level; ++l, ++m) { 15897ec681f3Smrg fit_rect_format_inclusive(dst->base.base.info.format, 15907ec681f3Smrg &rect, 15917ec681f3Smrg dst->surfaces[l * 6 + z]->desc.Width, 15927ec681f3Smrg dst->surfaces[l * 6 + z]->desc.Height); 15937ec681f3Smrg NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z], 15947ec681f3Smrg src->surfaces[m * 6 + z], 15957ec681f3Smrg (POINT *)&rect, 15967ec681f3Smrg &rect); 15977ec681f3Smrg rect_minify_inclusive(&rect); 15987ec681f3Smrg } 15997ec681f3Smrg u_box_origin_2d(0, 0, &src->dirty_rect[z]); 16007ec681f3Smrg m -= l; 16017ec681f3Smrg } 16027ec681f3Smrg } else 16037ec681f3Smrg if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) { 16047ec681f3Smrg struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb); 16057ec681f3Smrg struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb); 16067ec681f3Smrg 16077ec681f3Smrg if (src->dirty_box.width == 0) 16087ec681f3Smrg return D3D_OK; 16097ec681f3Smrg for (l = 0; l <= last_dst_level; ++l, ++m) 16107ec681f3Smrg NineVolume9_CopyMemToDefault(dst->volumes[l], 16117ec681f3Smrg src->volumes[m], 0, 0, 0, NULL); 16127ec681f3Smrg u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box); 16137ec681f3Smrg } else{ 16147ec681f3Smrg assert(!"invalid texture type"); 16157ec681f3Smrg } 16167ec681f3Smrg 16177ec681f3Smrg if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) { 16187ec681f3Smrg dstb->dirty_mip = TRUE; 16197ec681f3Smrg NineBaseTexture9_GenerateMipSubLevels(dstb); 16207ec681f3Smrg } 16217ec681f3Smrg 16227ec681f3Smrg return D3D_OK; 16237ec681f3Smrg} 16247ec681f3Smrg 16257ec681f3SmrgHRESULT NINE_WINAPI 16267ec681f3SmrgNineDevice9_GetRenderTargetData( struct NineDevice9 *This, 16277ec681f3Smrg IDirect3DSurface9 *pRenderTarget, 16287ec681f3Smrg IDirect3DSurface9 *pDestSurface ) 16297ec681f3Smrg{ 16307ec681f3Smrg struct NineSurface9 *dst = NineSurface9(pDestSurface); 16317ec681f3Smrg struct NineSurface9 *src = NineSurface9(pRenderTarget); 16327ec681f3Smrg 16337ec681f3Smrg DBG("This=%p pRenderTarget=%p pDestSurface=%p\n", 16347ec681f3Smrg This, pRenderTarget, pDestSurface); 16357ec681f3Smrg 16367ec681f3Smrg user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL); 16377ec681f3Smrg 16387ec681f3Smrg user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 16397ec681f3Smrg user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 16407ec681f3Smrg 16417ec681f3Smrg user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 16427ec681f3Smrg user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 16437ec681f3Smrg 16447ec681f3Smrg user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL); 16457ec681f3Smrg user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL); 16467ec681f3Smrg 16477ec681f3Smrg user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL); 16487ec681f3Smrg 16497ec681f3Smrg NineSurface9_CopyDefaultToMem(dst, src); 16507ec681f3Smrg 16517ec681f3Smrg return D3D_OK; 16527ec681f3Smrg} 16537ec681f3Smrg 16547ec681f3SmrgHRESULT NINE_WINAPI 16557ec681f3SmrgNineDevice9_GetFrontBufferData( struct NineDevice9 *This, 16567ec681f3Smrg UINT iSwapChain, 16577ec681f3Smrg IDirect3DSurface9 *pDestSurface ) 16587ec681f3Smrg{ 16597ec681f3Smrg DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This, 16607ec681f3Smrg iSwapChain, pDestSurface); 16617ec681f3Smrg 16627ec681f3Smrg user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL); 16637ec681f3Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 16647ec681f3Smrg 16657ec681f3Smrg return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain], 16667ec681f3Smrg pDestSurface); 16677ec681f3Smrg} 16687ec681f3Smrg 16697ec681f3SmrgHRESULT NINE_WINAPI 16707ec681f3SmrgNineDevice9_StretchRect( struct NineDevice9 *This, 16717ec681f3Smrg IDirect3DSurface9 *pSourceSurface, 16727ec681f3Smrg const RECT *pSourceRect, 16737ec681f3Smrg IDirect3DSurface9 *pDestSurface, 16747ec681f3Smrg const RECT *pDestRect, 16757ec681f3Smrg D3DTEXTUREFILTERTYPE Filter ) 16767ec681f3Smrg{ 16777ec681f3Smrg struct pipe_screen *screen = This->screen; 16787ec681f3Smrg struct NineSurface9 *dst = NineSurface9(pDestSurface); 16797ec681f3Smrg struct NineSurface9 *src = NineSurface9(pSourceSurface); 16807ec681f3Smrg struct pipe_resource *dst_res, *src_res; 16817ec681f3Smrg boolean zs; 16827ec681f3Smrg struct pipe_blit_info blit; 16837ec681f3Smrg boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE; 16847ec681f3Smrg 16857ec681f3Smrg DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p " 16867ec681f3Smrg "pDestRect=%p Filter=%u\n", 16877ec681f3Smrg This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); 16887ec681f3Smrg if (pSourceRect) 16897ec681f3Smrg DBG("pSourceRect=(%u,%u)-(%u,%u)\n", 16907ec681f3Smrg pSourceRect->left, pSourceRect->top, 16917ec681f3Smrg pSourceRect->right, pSourceRect->bottom); 16927ec681f3Smrg if (pDestRect) 16937ec681f3Smrg DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top, 16947ec681f3Smrg pDestRect->right, pDestRect->bottom); 16957ec681f3Smrg 16967ec681f3Smrg user_assert(pSourceSurface && pDestSurface, D3DERR_INVALIDCALL); 16977ec681f3Smrg user_assert(dst->base.pool == D3DPOOL_DEFAULT && 16987ec681f3Smrg src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 16997ec681f3Smrg 17007ec681f3Smrg dst_res = NineSurface9_GetResource(dst); 17017ec681f3Smrg src_res = NineSurface9_GetResource(src); 17027ec681f3Smrg zs = util_format_is_depth_or_stencil(dst_res->format); 17037ec681f3Smrg user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL); 17047ec681f3Smrg user_assert(!zs || !pSourceRect || 17057ec681f3Smrg (pSourceRect->left == 0 && 17067ec681f3Smrg pSourceRect->top == 0 && 17077ec681f3Smrg pSourceRect->right == src->desc.Width && 17087ec681f3Smrg pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL); 17097ec681f3Smrg user_assert(!zs || !pDestRect || 17107ec681f3Smrg (pDestRect->left == 0 && 17117ec681f3Smrg pDestRect->top == 0 && 17127ec681f3Smrg pDestRect->right == dst->desc.Width && 17137ec681f3Smrg pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL); 17147ec681f3Smrg user_assert(!zs || 17157ec681f3Smrg (dst->desc.Width == src->desc.Width && 17167ec681f3Smrg dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL); 17177ec681f3Smrg user_assert(zs || !util_format_is_depth_or_stencil(src_res->format), 17187ec681f3Smrg D3DERR_INVALIDCALL); 17197ec681f3Smrg user_assert(!zs || dst->desc.Format == src->desc.Format, 17207ec681f3Smrg D3DERR_INVALIDCALL); 17217ec681f3Smrg user_assert(screen->is_format_supported(screen, src_res->format, 17227ec681f3Smrg src_res->target, 17237ec681f3Smrg src_res->nr_samples, 17247ec681f3Smrg src_res->nr_storage_samples, 17257ec681f3Smrg PIPE_BIND_SAMPLER_VIEW), 17267ec681f3Smrg D3DERR_INVALIDCALL); 17277ec681f3Smrg 17287ec681f3Smrg /* We might want to permit these, but wine thinks we shouldn't. */ 17297ec681f3Smrg user_assert(!pDestRect || 17307ec681f3Smrg (pDestRect->left <= pDestRect->right && 17317ec681f3Smrg pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL); 17327ec681f3Smrg user_assert(!pSourceRect || 17337ec681f3Smrg (pSourceRect->left <= pSourceRect->right && 17347ec681f3Smrg pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL); 17357ec681f3Smrg 17367ec681f3Smrg memset(&blit, 0, sizeof(blit)); 17377ec681f3Smrg blit.dst.resource = dst_res; 17387ec681f3Smrg blit.dst.level = dst->level; 17397ec681f3Smrg blit.dst.box.z = dst->layer; 17407ec681f3Smrg blit.dst.box.depth = 1; 17417ec681f3Smrg blit.dst.format = dst_res->format; 17427ec681f3Smrg if (pDestRect) { 17437ec681f3Smrg flip_x = pDestRect->left > pDestRect->right; 17447ec681f3Smrg if (flip_x) { 17457ec681f3Smrg blit.dst.box.x = pDestRect->right; 17467ec681f3Smrg blit.dst.box.width = pDestRect->left - pDestRect->right; 17477ec681f3Smrg } else { 17487ec681f3Smrg blit.dst.box.x = pDestRect->left; 17497ec681f3Smrg blit.dst.box.width = pDestRect->right - pDestRect->left; 17507ec681f3Smrg } 17517ec681f3Smrg flip_y = pDestRect->top > pDestRect->bottom; 17527ec681f3Smrg if (flip_y) { 17537ec681f3Smrg blit.dst.box.y = pDestRect->bottom; 17547ec681f3Smrg blit.dst.box.height = pDestRect->top - pDestRect->bottom; 17557ec681f3Smrg } else { 17567ec681f3Smrg blit.dst.box.y = pDestRect->top; 17577ec681f3Smrg blit.dst.box.height = pDestRect->bottom - pDestRect->top; 17587ec681f3Smrg } 17597ec681f3Smrg } else { 17607ec681f3Smrg blit.dst.box.x = 0; 17617ec681f3Smrg blit.dst.box.y = 0; 17627ec681f3Smrg blit.dst.box.width = dst->desc.Width; 17637ec681f3Smrg blit.dst.box.height = dst->desc.Height; 17647ec681f3Smrg } 17657ec681f3Smrg blit.src.resource = src_res; 17667ec681f3Smrg blit.src.level = src->level; 17677ec681f3Smrg blit.src.box.z = src->layer; 17687ec681f3Smrg blit.src.box.depth = 1; 17697ec681f3Smrg blit.src.format = src_res->format; 17707ec681f3Smrg if (pSourceRect) { 17717ec681f3Smrg if (flip_x ^ (pSourceRect->left > pSourceRect->right)) { 17727ec681f3Smrg blit.src.box.x = pSourceRect->right; 17737ec681f3Smrg blit.src.box.width = pSourceRect->left - pSourceRect->right; 17747ec681f3Smrg } else { 17757ec681f3Smrg blit.src.box.x = pSourceRect->left; 17767ec681f3Smrg blit.src.box.width = pSourceRect->right - pSourceRect->left; 17777ec681f3Smrg } 17787ec681f3Smrg if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) { 17797ec681f3Smrg blit.src.box.y = pSourceRect->bottom; 17807ec681f3Smrg blit.src.box.height = pSourceRect->top - pSourceRect->bottom; 17817ec681f3Smrg } else { 17827ec681f3Smrg blit.src.box.y = pSourceRect->top; 17837ec681f3Smrg blit.src.box.height = pSourceRect->bottom - pSourceRect->top; 17847ec681f3Smrg } 17857ec681f3Smrg } else { 17867ec681f3Smrg blit.src.box.x = flip_x ? src->desc.Width : 0; 17877ec681f3Smrg blit.src.box.y = flip_y ? src->desc.Height : 0; 17887ec681f3Smrg blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width; 17897ec681f3Smrg blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height; 17907ec681f3Smrg } 17917ec681f3Smrg blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA; 17927ec681f3Smrg blit.filter = Filter == D3DTEXF_LINEAR ? 17937ec681f3Smrg PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST; 17947ec681f3Smrg blit.scissor_enable = FALSE; 17957ec681f3Smrg blit.alpha_blend = FALSE; 17967ec681f3Smrg 17977ec681f3Smrg /* If both of a src and dst dimension are negative, flip them. */ 17987ec681f3Smrg if (blit.dst.box.width < 0 && blit.src.box.width < 0) { 17997ec681f3Smrg blit.dst.box.width = -blit.dst.box.width; 18007ec681f3Smrg blit.src.box.width = -blit.src.box.width; 18017ec681f3Smrg } 18027ec681f3Smrg if (blit.dst.box.height < 0 && blit.src.box.height < 0) { 18037ec681f3Smrg blit.dst.box.height = -blit.dst.box.height; 18047ec681f3Smrg blit.src.box.height = -blit.src.box.height; 18057ec681f3Smrg } 18067ec681f3Smrg scaled = 18077ec681f3Smrg blit.dst.box.width != blit.src.box.width || 18087ec681f3Smrg blit.dst.box.height != blit.src.box.height; 18097ec681f3Smrg 18107ec681f3Smrg user_assert(!scaled || dst != src, D3DERR_INVALIDCALL); 18117ec681f3Smrg user_assert(!scaled || 18127ec681f3Smrg !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL); 18137ec681f3Smrg user_assert(!NineSurface9_IsOffscreenPlain(dst) || 18147ec681f3Smrg NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL); 18157ec681f3Smrg user_assert(NineSurface9_IsOffscreenPlain(dst) || 18167ec681f3Smrg dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL), 18177ec681f3Smrg D3DERR_INVALIDCALL); 18187ec681f3Smrg user_assert(!scaled || 18197ec681f3Smrg (!util_format_is_compressed(dst->base.info.format) && 18207ec681f3Smrg !util_format_is_compressed(src->base.info.format)), 18217ec681f3Smrg D3DERR_INVALIDCALL); 18227ec681f3Smrg 18237ec681f3Smrg user_warn(src == dst && 18247ec681f3Smrg u_box_test_intersection_2d(&blit.src.box, &blit.dst.box)); 18257ec681f3Smrg 18267ec681f3Smrg /* Check for clipping/clamping: */ 18277ec681f3Smrg { 18287ec681f3Smrg struct pipe_box box; 18297ec681f3Smrg int xy; 18307ec681f3Smrg 18317ec681f3Smrg xy = u_box_clip_2d(&box, &blit.dst.box, 18327ec681f3Smrg dst->desc.Width, dst->desc.Height); 18337ec681f3Smrg if (xy < 0) 18347ec681f3Smrg return D3D_OK; 18357ec681f3Smrg if (xy == 0) 18367ec681f3Smrg xy = u_box_clip_2d(&box, &blit.src.box, 18377ec681f3Smrg src->desc.Width, src->desc.Height); 18387ec681f3Smrg clamped = !!xy; 18397ec681f3Smrg } 18407ec681f3Smrg 18417ec681f3Smrg ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) || 18427ec681f3Smrg (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality); 18437ec681f3Smrg 18447ec681f3Smrg if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { 18457ec681f3Smrg DBG("using pipe->blit()\n"); 18467ec681f3Smrg /* TODO: software scaling */ 18477ec681f3Smrg user_assert(screen->is_format_supported(screen, dst_res->format, 18487ec681f3Smrg dst_res->target, 18497ec681f3Smrg dst_res->nr_samples, 18507ec681f3Smrg dst_res->nr_storage_samples, 18517ec681f3Smrg zs ? PIPE_BIND_DEPTH_STENCIL : 18527ec681f3Smrg PIPE_BIND_RENDER_TARGET), 18537ec681f3Smrg D3DERR_INVALIDCALL); 18547ec681f3Smrg 18557ec681f3Smrg nine_context_blit(This, (struct NineUnknown *)dst, 18567ec681f3Smrg (struct NineUnknown *)src, &blit); 18577ec681f3Smrg } else { 18587ec681f3Smrg assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 && 18597ec681f3Smrg blit.src.box.x >= 0 && blit.src.box.y >= 0 && 18607ec681f3Smrg blit.dst.box.x + blit.dst.box.width <= dst->desc.Width && 18617ec681f3Smrg blit.src.box.x + blit.src.box.width <= src->desc.Width && 18627ec681f3Smrg blit.dst.box.y + blit.dst.box.height <= dst->desc.Height && 18637ec681f3Smrg blit.src.box.y + blit.src.box.height <= src->desc.Height); 18647ec681f3Smrg /* Or drivers might crash ... */ 18657ec681f3Smrg DBG("Using resource_copy_region.\n"); 18667ec681f3Smrg nine_context_resource_copy_region(This, (struct NineUnknown *)dst, 18677ec681f3Smrg (struct NineUnknown *)src, 18687ec681f3Smrg blit.dst.resource, blit.dst.level, 18697ec681f3Smrg &blit.dst.box, 18707ec681f3Smrg blit.src.resource, blit.src.level, 18717ec681f3Smrg &blit.src.box); 18727ec681f3Smrg } 18737ec681f3Smrg 18747ec681f3Smrg /* Communicate the container it needs to update sublevels - if apply */ 18757ec681f3Smrg NineSurface9_MarkContainerDirty(dst); 18767ec681f3Smrg 18777ec681f3Smrg return D3D_OK; 18787ec681f3Smrg} 18797ec681f3Smrg 18807ec681f3SmrgHRESULT NINE_WINAPI 18817ec681f3SmrgNineDevice9_ColorFill( struct NineDevice9 *This, 18827ec681f3Smrg IDirect3DSurface9 *pSurface, 18837ec681f3Smrg const RECT *pRect, 18847ec681f3Smrg D3DCOLOR color ) 18857ec681f3Smrg{ 18867ec681f3Smrg struct NineSurface9 *surf = NineSurface9(pSurface); 18877ec681f3Smrg unsigned x, y, w, h; 18887ec681f3Smrg 18897ec681f3Smrg DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This, 18907ec681f3Smrg pSurface, pRect, color); 18917ec681f3Smrg if (pRect) 18927ec681f3Smrg DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top, 18937ec681f3Smrg pRect->right, pRect->bottom); 18947ec681f3Smrg 18957ec681f3Smrg user_assert(pSurface != NULL, D3DERR_INVALIDCALL); 18967ec681f3Smrg 18977ec681f3Smrg user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 18987ec681f3Smrg 18997ec681f3Smrg user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) || 19007ec681f3Smrg NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL); 19017ec681f3Smrg 19027ec681f3Smrg user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK); 19037ec681f3Smrg 19047ec681f3Smrg if (pRect) { 19057ec681f3Smrg x = pRect->left; 19067ec681f3Smrg y = pRect->top; 19077ec681f3Smrg w = pRect->right - pRect->left; 19087ec681f3Smrg h = pRect->bottom - pRect->top; 19097ec681f3Smrg /* Wine tests: */ 19107ec681f3Smrg if (compressed_format(surf->desc.Format)) { 19117ec681f3Smrg const unsigned bw = util_format_get_blockwidth(surf->base.info.format); 19127ec681f3Smrg const unsigned bh = util_format_get_blockheight(surf->base.info.format); 19137ec681f3Smrg 19147ec681f3Smrg user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh), 19157ec681f3Smrg D3DERR_INVALIDCALL); 19167ec681f3Smrg } 19177ec681f3Smrg } else{ 19187ec681f3Smrg x = 0; 19197ec681f3Smrg y = 0; 19207ec681f3Smrg w = surf->desc.Width; 19217ec681f3Smrg h = surf->desc.Height; 19227ec681f3Smrg } 19237ec681f3Smrg 19247ec681f3Smrg if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) { 19257ec681f3Smrg nine_context_clear_render_target(This, surf, color, x, y, w, h); 19267ec681f3Smrg } else { 19277ec681f3Smrg D3DLOCKED_RECT lock; 19287ec681f3Smrg union util_color uc; 19297ec681f3Smrg HRESULT hr; 19307ec681f3Smrg /* XXX: lock pRect and fix util_fill_rect */ 19317ec681f3Smrg hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD); 19327ec681f3Smrg if (FAILED(hr)) 19337ec681f3Smrg return hr; 19347ec681f3Smrg util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24, 19357ec681f3Smrg surf->base.info.format, &uc); 19367ec681f3Smrg util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch, 19377ec681f3Smrg x, y, w, h, &uc); 19387ec681f3Smrg NineSurface9_UnlockRect(surf); 19397ec681f3Smrg } 19407ec681f3Smrg 19417ec681f3Smrg return D3D_OK; 19427ec681f3Smrg} 19437ec681f3Smrg 19447ec681f3SmrgHRESULT NINE_WINAPI 19457ec681f3SmrgNineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, 19467ec681f3Smrg UINT Width, 19477ec681f3Smrg UINT Height, 19487ec681f3Smrg D3DFORMAT Format, 19497ec681f3Smrg D3DPOOL Pool, 19507ec681f3Smrg IDirect3DSurface9 **ppSurface, 19517ec681f3Smrg HANDLE *pSharedHandle ) 19527ec681f3Smrg{ 19537ec681f3Smrg HRESULT hr; 19547ec681f3Smrg 19557ec681f3Smrg DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u " 19567ec681f3Smrg "ppSurface=%p pSharedHandle=%p\n", This, 19577ec681f3Smrg Width, Height, d3dformat_to_string(Format), Format, Pool, 19587ec681f3Smrg ppSurface, pSharedHandle); 19597ec681f3Smrg 19607ec681f3Smrg user_assert(ppSurface != NULL, D3DERR_INVALIDCALL); 19617ec681f3Smrg *ppSurface = NULL; 19627ec681f3Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT 19637ec681f3Smrg || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 19647ec681f3Smrg user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 19657ec681f3Smrg 19667ec681f3Smrg /* Can be used with StretchRect and ColorFill. It's also always lockable. 19677ec681f3Smrg */ 19687ec681f3Smrg hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height, 19697ec681f3Smrg Format, 19707ec681f3Smrg D3DMULTISAMPLE_NONE, 0, 19717ec681f3Smrg TRUE, 19727ec681f3Smrg ppSurface, pSharedHandle); 19737ec681f3Smrg if (FAILED(hr)) 19747ec681f3Smrg DBG("Failed to create surface.\n"); 19757ec681f3Smrg return hr; 19767ec681f3Smrg} 19777ec681f3Smrg 19787ec681f3SmrgHRESULT NINE_WINAPI 19797ec681f3SmrgNineDevice9_SetRenderTarget( struct NineDevice9 *This, 19807ec681f3Smrg DWORD RenderTargetIndex, 19817ec681f3Smrg IDirect3DSurface9 *pRenderTarget ) 19827ec681f3Smrg{ 19837ec681f3Smrg struct NineSurface9 *rt = NineSurface9(pRenderTarget); 19847ec681f3Smrg const unsigned i = RenderTargetIndex; 19857ec681f3Smrg 19867ec681f3Smrg DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This, 19877ec681f3Smrg RenderTargetIndex, pRenderTarget); 19887ec681f3Smrg 19897ec681f3Smrg user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 19907ec681f3Smrg user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL); 19917ec681f3Smrg user_assert(!pRenderTarget || 19927ec681f3Smrg rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL); 19937ec681f3Smrg 19947ec681f3Smrg if (i == 0) { 19957ec681f3Smrg This->state.viewport.X = 0; 19967ec681f3Smrg This->state.viewport.Y = 0; 19977ec681f3Smrg This->state.viewport.Width = rt->desc.Width; 19987ec681f3Smrg This->state.viewport.Height = rt->desc.Height; 19997ec681f3Smrg This->state.viewport.MinZ = 0.0f; 20007ec681f3Smrg This->state.viewport.MaxZ = 1.0f; 20017ec681f3Smrg 20027ec681f3Smrg This->state.scissor.minx = 0; 20037ec681f3Smrg This->state.scissor.miny = 0; 20047ec681f3Smrg This->state.scissor.maxx = rt->desc.Width; 20057ec681f3Smrg This->state.scissor.maxy = rt->desc.Height; 20067ec681f3Smrg nine_context_set_viewport(This, &This->state.viewport); 20077ec681f3Smrg nine_context_set_scissor(This, &This->state.scissor); 20087ec681f3Smrg } 20097ec681f3Smrg 20107ec681f3Smrg if (This->state.rt[i] != NineSurface9(pRenderTarget)) 20117ec681f3Smrg nine_bind(&This->state.rt[i], pRenderTarget); 20127ec681f3Smrg 20137ec681f3Smrg nine_context_set_render_target(This, i, rt); 20147ec681f3Smrg return D3D_OK; 20157ec681f3Smrg} 20167ec681f3Smrg 20177ec681f3SmrgHRESULT NINE_WINAPI 20187ec681f3SmrgNineDevice9_GetRenderTarget( struct NineDevice9 *This, 20197ec681f3Smrg DWORD RenderTargetIndex, 20207ec681f3Smrg IDirect3DSurface9 **ppRenderTarget ) 20217ec681f3Smrg{ 20227ec681f3Smrg const unsigned i = RenderTargetIndex; 20237ec681f3Smrg 20247ec681f3Smrg user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 20257ec681f3Smrg user_assert(ppRenderTarget, D3DERR_INVALIDCALL); 20267ec681f3Smrg 20277ec681f3Smrg *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i]; 20287ec681f3Smrg if (!This->state.rt[i]) 20297ec681f3Smrg return D3DERR_NOTFOUND; 20307ec681f3Smrg 20317ec681f3Smrg NineUnknown_AddRef(NineUnknown(This->state.rt[i])); 20327ec681f3Smrg return D3D_OK; 20337ec681f3Smrg} 20347ec681f3Smrg 20357ec681f3SmrgHRESULT NINE_WINAPI 20367ec681f3SmrgNineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, 20377ec681f3Smrg IDirect3DSurface9 *pNewZStencil ) 20387ec681f3Smrg{ 20397ec681f3Smrg struct NineSurface9 *ds = NineSurface9(pNewZStencil); 20407ec681f3Smrg DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil); 20417ec681f3Smrg 20427ec681f3Smrg user_assert(!ds || util_format_is_depth_or_stencil(ds->base.info.format), 20437ec681f3Smrg D3DERR_INVALIDCALL); 20447ec681f3Smrg 20457ec681f3Smrg if (This->state.ds != ds) { 20467ec681f3Smrg nine_bind(&This->state.ds, ds); 20477ec681f3Smrg nine_context_set_depth_stencil(This, ds); 20487ec681f3Smrg } 20497ec681f3Smrg return D3D_OK; 20507ec681f3Smrg} 20517ec681f3Smrg 20527ec681f3SmrgHRESULT NINE_WINAPI 20537ec681f3SmrgNineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, 20547ec681f3Smrg IDirect3DSurface9 **ppZStencilSurface ) 20557ec681f3Smrg{ 20567ec681f3Smrg user_assert(ppZStencilSurface, D3DERR_INVALIDCALL); 20577ec681f3Smrg 20587ec681f3Smrg *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds; 20597ec681f3Smrg if (!This->state.ds) 20607ec681f3Smrg return D3DERR_NOTFOUND; 20617ec681f3Smrg 20627ec681f3Smrg NineUnknown_AddRef(NineUnknown(This->state.ds)); 20637ec681f3Smrg return D3D_OK; 20647ec681f3Smrg} 20657ec681f3Smrg 20667ec681f3SmrgHRESULT NINE_WINAPI 20677ec681f3SmrgNineDevice9_BeginScene( struct NineDevice9 *This ) 20687ec681f3Smrg{ 20697ec681f3Smrg DBG("This=%p\n", This); 20707ec681f3Smrg user_assert(!This->in_scene, D3DERR_INVALIDCALL); 20717ec681f3Smrg This->in_scene = TRUE; 20727ec681f3Smrg /* Do we want to do anything else here ? */ 20737ec681f3Smrg return D3D_OK; 20747ec681f3Smrg} 20757ec681f3Smrg 20767ec681f3SmrgHRESULT NINE_WINAPI 20777ec681f3SmrgNineDevice9_EndScene( struct NineDevice9 *This ) 20787ec681f3Smrg{ 20797ec681f3Smrg DBG("This=%p\n", This); 20807ec681f3Smrg user_assert(This->in_scene, D3DERR_INVALIDCALL); 20817ec681f3Smrg This->in_scene = FALSE; 20827ec681f3Smrg This->end_scene_since_present++; 20837ec681f3Smrg /* EndScene() is supposed to flush the GPU commands. 20847ec681f3Smrg * The idea is to flush ahead of the Present() call. 20857ec681f3Smrg * (Apps could take advantage of this by inserting CPU 20867ec681f3Smrg * work between EndScene() and Present()). 20877ec681f3Smrg * Most apps will have one EndScene per frame. 20887ec681f3Smrg * Some will have 2 or 3. 20897ec681f3Smrg * Some bad behaving apps do a lot of them. 20907ec681f3Smrg * As flushing has a cost, do it only once. */ 20917ec681f3Smrg if (This->end_scene_since_present <= 1) { 20927ec681f3Smrg nine_context_pipe_flush(This); 20937ec681f3Smrg nine_csmt_flush(This); 20947ec681f3Smrg } 20957ec681f3Smrg return D3D_OK; 20967ec681f3Smrg} 20977ec681f3Smrg 20987ec681f3SmrgHRESULT NINE_WINAPI 20997ec681f3SmrgNineDevice9_Clear( struct NineDevice9 *This, 21007ec681f3Smrg DWORD Count, 21017ec681f3Smrg const D3DRECT *pRects, 21027ec681f3Smrg DWORD Flags, 21037ec681f3Smrg D3DCOLOR Color, 21047ec681f3Smrg float Z, 21057ec681f3Smrg DWORD Stencil ) 21067ec681f3Smrg{ 21077ec681f3Smrg struct NineSurface9 *zsbuf_surf = This->state.ds; 21087ec681f3Smrg 21097ec681f3Smrg DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", 21107ec681f3Smrg This, Count, pRects, Flags, Color, Z, Stencil); 21117ec681f3Smrg 21127ec681f3Smrg user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL), 21137ec681f3Smrg D3DERR_INVALIDCALL); 21147ec681f3Smrg user_assert(!(Flags & D3DCLEAR_STENCIL) || 21157ec681f3Smrg (zsbuf_surf && 21167ec681f3Smrg util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)), 21177ec681f3Smrg D3DERR_INVALIDCALL); 21187ec681f3Smrg#ifdef NINE_STRICT 21197ec681f3Smrg user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL); 21207ec681f3Smrg#else 21217ec681f3Smrg user_warn((pRects && !Count) || (!pRects && Count)); 21227ec681f3Smrg if (pRects && !Count) 21237ec681f3Smrg return D3D_OK; 21247ec681f3Smrg if (!pRects) 21257ec681f3Smrg Count = 0; 21267ec681f3Smrg#endif 21277ec681f3Smrg 21287ec681f3Smrg nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil); 21297ec681f3Smrg return D3D_OK; 21307ec681f3Smrg} 21317ec681f3Smrg 21327ec681f3Smrgstatic void 21337ec681f3Smrgnine_D3DMATRIX_print(const D3DMATRIX *M) 21347ec681f3Smrg{ 21357ec681f3Smrg DBG("\n(%f %f %f %f)\n" 21367ec681f3Smrg "(%f %f %f %f)\n" 21377ec681f3Smrg "(%f %f %f %f)\n" 21387ec681f3Smrg "(%f %f %f %f)\n", 21397ec681f3Smrg M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], 21407ec681f3Smrg M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], 21417ec681f3Smrg M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], 21427ec681f3Smrg M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); 21437ec681f3Smrg} 21447ec681f3Smrg 21457ec681f3SmrgHRESULT NINE_WINAPI 21467ec681f3SmrgNineDevice9_SetTransform( struct NineDevice9 *This, 21477ec681f3Smrg D3DTRANSFORMSTATETYPE State, 21487ec681f3Smrg const D3DMATRIX *pMatrix ) 21497ec681f3Smrg{ 21507ec681f3Smrg struct nine_state *state = This->update; 21517ec681f3Smrg D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); 21527ec681f3Smrg 21537ec681f3Smrg DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 21547ec681f3Smrg 21557ec681f3Smrg user_assert(pMatrix, D3DERR_INVALIDCALL); 21567ec681f3Smrg user_assert(M, D3DERR_INVALIDCALL); 21577ec681f3Smrg nine_D3DMATRIX_print(pMatrix); 21587ec681f3Smrg 21597ec681f3Smrg *M = *pMatrix; 21607ec681f3Smrg if (unlikely(This->is_recording)) { 21617ec681f3Smrg state->ff.changed.transform[State / 32] |= 1 << (State % 32); 21627ec681f3Smrg state->changed.group |= NINE_STATE_FF_VSTRANSF; 21637ec681f3Smrg } else 21647ec681f3Smrg nine_context_set_transform(This, State, pMatrix); 21657ec681f3Smrg 21667ec681f3Smrg return D3D_OK; 21677ec681f3Smrg} 21687ec681f3Smrg 21697ec681f3SmrgHRESULT NINE_WINAPI 21707ec681f3SmrgNineDevice9_GetTransform( struct NineDevice9 *This, 21717ec681f3Smrg D3DTRANSFORMSTATETYPE State, 21727ec681f3Smrg D3DMATRIX *pMatrix ) 21737ec681f3Smrg{ 21747ec681f3Smrg D3DMATRIX *M; 21757ec681f3Smrg 21767ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 21777ec681f3Smrg M = nine_state_access_transform(&This->state.ff, State, FALSE); 21787ec681f3Smrg user_assert(pMatrix, D3DERR_INVALIDCALL); 21797ec681f3Smrg user_assert(M, D3DERR_INVALIDCALL); 21807ec681f3Smrg *pMatrix = *M; 21817ec681f3Smrg return D3D_OK; 21827ec681f3Smrg} 21837ec681f3Smrg 21847ec681f3SmrgHRESULT NINE_WINAPI 21857ec681f3SmrgNineDevice9_MultiplyTransform( struct NineDevice9 *This, 21867ec681f3Smrg D3DTRANSFORMSTATETYPE State, 21877ec681f3Smrg const D3DMATRIX *pMatrix ) 21887ec681f3Smrg{ 21897ec681f3Smrg struct nine_state *state = This->update; 21907ec681f3Smrg D3DMATRIX T; 21917ec681f3Smrg D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); 21927ec681f3Smrg 21937ec681f3Smrg DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 21947ec681f3Smrg 21957ec681f3Smrg user_assert(pMatrix, D3DERR_INVALIDCALL); 21967ec681f3Smrg user_assert(M, D3DERR_INVALIDCALL); 21977ec681f3Smrg 21987ec681f3Smrg nine_d3d_matrix_matrix_mul(&T, pMatrix, M); 21997ec681f3Smrg return NineDevice9_SetTransform(This, State, &T); 22007ec681f3Smrg} 22017ec681f3Smrg 22027ec681f3SmrgHRESULT NINE_WINAPI 22037ec681f3SmrgNineDevice9_SetViewport( struct NineDevice9 *This, 22047ec681f3Smrg const D3DVIEWPORT9 *pViewport ) 22057ec681f3Smrg{ 22067ec681f3Smrg struct nine_state *state = This->update; 22077ec681f3Smrg 22087ec681f3Smrg DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n", 22097ec681f3Smrg pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, 22107ec681f3Smrg pViewport->MinZ, pViewport->MaxZ); 22117ec681f3Smrg 22127ec681f3Smrg user_assert(pViewport != NULL, D3DERR_INVALIDCALL); 22137ec681f3Smrg state->viewport = *pViewport; 22147ec681f3Smrg nine_context_set_viewport(This, pViewport); 22157ec681f3Smrg 22167ec681f3Smrg return D3D_OK; 22177ec681f3Smrg} 22187ec681f3Smrg 22197ec681f3SmrgHRESULT NINE_WINAPI 22207ec681f3SmrgNineDevice9_GetViewport( struct NineDevice9 *This, 22217ec681f3Smrg D3DVIEWPORT9 *pViewport ) 22227ec681f3Smrg{ 22237ec681f3Smrg user_assert(pViewport != NULL, D3DERR_INVALIDCALL); 22247ec681f3Smrg *pViewport = This->state.viewport; 22257ec681f3Smrg return D3D_OK; 22267ec681f3Smrg} 22277ec681f3Smrg 22287ec681f3SmrgHRESULT NINE_WINAPI 22297ec681f3SmrgNineDevice9_SetMaterial( struct NineDevice9 *This, 22307ec681f3Smrg const D3DMATERIAL9 *pMaterial ) 22317ec681f3Smrg{ 22327ec681f3Smrg struct nine_state *state = This->update; 22337ec681f3Smrg 22347ec681f3Smrg DBG("This=%p pMaterial=%p\n", This, pMaterial); 22357ec681f3Smrg if (pMaterial) 22367ec681f3Smrg nine_dump_D3DMATERIAL9(DBG_FF, pMaterial); 22377ec681f3Smrg 22387ec681f3Smrg user_assert(pMaterial, E_POINTER); 22397ec681f3Smrg 22407ec681f3Smrg state->ff.material = *pMaterial; 22417ec681f3Smrg if (unlikely(This->is_recording)) 22427ec681f3Smrg state->changed.group |= NINE_STATE_FF_MATERIAL; 22437ec681f3Smrg else 22447ec681f3Smrg nine_context_set_material(This, pMaterial); 22457ec681f3Smrg 22467ec681f3Smrg return D3D_OK; 22477ec681f3Smrg} 22487ec681f3Smrg 22497ec681f3SmrgHRESULT NINE_WINAPI 22507ec681f3SmrgNineDevice9_GetMaterial( struct NineDevice9 *This, 22517ec681f3Smrg D3DMATERIAL9 *pMaterial ) 22527ec681f3Smrg{ 22537ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 22547ec681f3Smrg user_assert(pMaterial, E_POINTER); 22557ec681f3Smrg *pMaterial = This->state.ff.material; 22567ec681f3Smrg return D3D_OK; 22577ec681f3Smrg} 22587ec681f3Smrg 22597ec681f3SmrgHRESULT NINE_WINAPI 22607ec681f3SmrgNineDevice9_SetLight( struct NineDevice9 *This, 22617ec681f3Smrg DWORD Index, 22627ec681f3Smrg const D3DLIGHT9 *pLight ) 22637ec681f3Smrg{ 22647ec681f3Smrg struct nine_state *state = This->update; 22657ec681f3Smrg HRESULT hr; 22667ec681f3Smrg 22677ec681f3Smrg DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight); 22687ec681f3Smrg if (pLight) 22697ec681f3Smrg nine_dump_D3DLIGHT9(DBG_FF, pLight); 22707ec681f3Smrg 22717ec681f3Smrg user_assert(pLight, D3DERR_INVALIDCALL); 22727ec681f3Smrg user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL); 22737ec681f3Smrg 22747ec681f3Smrg user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */ 22757ec681f3Smrg 22767ec681f3Smrg hr = nine_state_set_light(&state->ff, Index, pLight); 22777ec681f3Smrg if (hr != D3D_OK) 22787ec681f3Smrg return hr; 22797ec681f3Smrg 22807ec681f3Smrg if (pLight->Type != D3DLIGHT_DIRECTIONAL && 22817ec681f3Smrg pLight->Attenuation0 == 0.0f && 22827ec681f3Smrg pLight->Attenuation1 == 0.0f && 22837ec681f3Smrg pLight->Attenuation2 == 0.0f) { 22847ec681f3Smrg DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n"); 22857ec681f3Smrg } 22867ec681f3Smrg 22877ec681f3Smrg if (unlikely(This->is_recording)) 22887ec681f3Smrg state->changed.group |= NINE_STATE_FF_LIGHTING; 22897ec681f3Smrg else 22907ec681f3Smrg nine_context_set_light(This, Index, pLight); 22917ec681f3Smrg 22927ec681f3Smrg return D3D_OK; 22937ec681f3Smrg} 22947ec681f3Smrg 22957ec681f3SmrgHRESULT NINE_WINAPI 22967ec681f3SmrgNineDevice9_GetLight( struct NineDevice9 *This, 22977ec681f3Smrg DWORD Index, 22987ec681f3Smrg D3DLIGHT9 *pLight ) 22997ec681f3Smrg{ 23007ec681f3Smrg const struct nine_state *state = &This->state; 23017ec681f3Smrg 23027ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 23037ec681f3Smrg user_assert(pLight, D3DERR_INVALIDCALL); 23047ec681f3Smrg user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 23057ec681f3Smrg user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 23067ec681f3Smrg D3DERR_INVALIDCALL); 23077ec681f3Smrg 23087ec681f3Smrg *pLight = state->ff.light[Index]; 23097ec681f3Smrg 23107ec681f3Smrg return D3D_OK; 23117ec681f3Smrg} 23127ec681f3Smrg 23137ec681f3SmrgHRESULT NINE_WINAPI 23147ec681f3SmrgNineDevice9_LightEnable( struct NineDevice9 *This, 23157ec681f3Smrg DWORD Index, 23167ec681f3Smrg BOOL Enable ) 23177ec681f3Smrg{ 23187ec681f3Smrg struct nine_state *state = This->update; 23197ec681f3Smrg 23207ec681f3Smrg DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable); 23217ec681f3Smrg 23227ec681f3Smrg if (Index >= state->ff.num_lights || 23237ec681f3Smrg state->ff.light[Index].Type == NINED3DLIGHT_INVALID) { 23247ec681f3Smrg /* This should create a default light. */ 23257ec681f3Smrg D3DLIGHT9 light; 23267ec681f3Smrg memset(&light, 0, sizeof(light)); 23277ec681f3Smrg light.Type = D3DLIGHT_DIRECTIONAL; 23287ec681f3Smrg light.Diffuse.r = 1.0f; 23297ec681f3Smrg light.Diffuse.g = 1.0f; 23307ec681f3Smrg light.Diffuse.b = 1.0f; 23317ec681f3Smrg light.Direction.z = 1.0f; 23327ec681f3Smrg NineDevice9_SetLight(This, Index, &light); 23337ec681f3Smrg } 23347ec681f3Smrg 23357ec681f3Smrg nine_state_light_enable(&state->ff, Index, Enable); 23367ec681f3Smrg if (likely(!This->is_recording)) 23377ec681f3Smrg nine_context_light_enable(This, Index, Enable); 23387ec681f3Smrg else 23397ec681f3Smrg state->changed.group |= NINE_STATE_FF_LIGHTING; 23407ec681f3Smrg 23417ec681f3Smrg return D3D_OK; 23427ec681f3Smrg} 23437ec681f3Smrg 23447ec681f3SmrgHRESULT NINE_WINAPI 23457ec681f3SmrgNineDevice9_GetLightEnable( struct NineDevice9 *This, 23467ec681f3Smrg DWORD Index, 23477ec681f3Smrg BOOL *pEnable ) 23487ec681f3Smrg{ 23497ec681f3Smrg const struct nine_state *state = &This->state; 23507ec681f3Smrg unsigned i; 23517ec681f3Smrg 23527ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 23537ec681f3Smrg user_assert(pEnable != NULL, D3DERR_INVALIDCALL); 23547ec681f3Smrg user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 23557ec681f3Smrg user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 23567ec681f3Smrg D3DERR_INVALIDCALL); 23577ec681f3Smrg 23587ec681f3Smrg for (i = 0; i < state->ff.num_lights_active; ++i) 23597ec681f3Smrg if (state->ff.active_light[i] == Index) 23607ec681f3Smrg break; 23617ec681f3Smrg 23627ec681f3Smrg *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine 23637ec681f3Smrg 23647ec681f3Smrg return D3D_OK; 23657ec681f3Smrg} 23667ec681f3Smrg 23677ec681f3SmrgHRESULT NINE_WINAPI 23687ec681f3SmrgNineDevice9_SetClipPlane( struct NineDevice9 *This, 23697ec681f3Smrg DWORD Index, 23707ec681f3Smrg const float *pPlane ) 23717ec681f3Smrg{ 23727ec681f3Smrg struct nine_state *state = This->update; 23737ec681f3Smrg 23747ec681f3Smrg user_assert(pPlane, D3DERR_INVALIDCALL); 23757ec681f3Smrg 23767ec681f3Smrg DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index, 23777ec681f3Smrg pPlane[0], pPlane[1], 23787ec681f3Smrg pPlane[2], pPlane[3]); 23797ec681f3Smrg 23807ec681f3Smrg user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 23817ec681f3Smrg 23827ec681f3Smrg memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0])); 23837ec681f3Smrg if (unlikely(This->is_recording)) 23847ec681f3Smrg state->changed.ucp |= 1 << Index; 23857ec681f3Smrg else 23867ec681f3Smrg nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane); 23877ec681f3Smrg 23887ec681f3Smrg return D3D_OK; 23897ec681f3Smrg} 23907ec681f3Smrg 23917ec681f3SmrgHRESULT NINE_WINAPI 23927ec681f3SmrgNineDevice9_GetClipPlane( struct NineDevice9 *This, 23937ec681f3Smrg DWORD Index, 23947ec681f3Smrg float *pPlane ) 23957ec681f3Smrg{ 23967ec681f3Smrg const struct nine_state *state = &This->state; 23977ec681f3Smrg 23987ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 23997ec681f3Smrg user_assert(pPlane != NULL, D3DERR_INVALIDCALL); 24007ec681f3Smrg user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 24017ec681f3Smrg 24027ec681f3Smrg memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0])); 24037ec681f3Smrg return D3D_OK; 24047ec681f3Smrg} 24057ec681f3Smrg 24067ec681f3SmrgHRESULT NINE_WINAPI 24077ec681f3SmrgNineDevice9_SetRenderState( struct NineDevice9 *This, 24087ec681f3Smrg D3DRENDERSTATETYPE State, 24097ec681f3Smrg DWORD Value ) 24107ec681f3Smrg{ 24117ec681f3Smrg struct nine_state *state = This->update; 24127ec681f3Smrg 24137ec681f3Smrg DBG("This=%p State=%u(%s) Value=%08x\n", This, 24147ec681f3Smrg State, nine_d3drs_to_string(State), Value); 24157ec681f3Smrg 24167ec681f3Smrg user_assert(State < D3DRS_COUNT, D3D_OK); 24177ec681f3Smrg 24187ec681f3Smrg if (unlikely(This->is_recording)) { 24197ec681f3Smrg state->rs_advertised[State] = Value; 24207ec681f3Smrg /* only need to record changed render states for stateblocks */ 24217ec681f3Smrg state->changed.rs[State / 32] |= 1 << (State % 32); 24227ec681f3Smrg return D3D_OK; 24237ec681f3Smrg } 24247ec681f3Smrg 24257ec681f3Smrg if (state->rs_advertised[State] == Value) 24267ec681f3Smrg return D3D_OK; 24277ec681f3Smrg 24287ec681f3Smrg state->rs_advertised[State] = Value; 24297ec681f3Smrg nine_context_set_render_state(This, State, Value); 24307ec681f3Smrg 24317ec681f3Smrg return D3D_OK; 24327ec681f3Smrg} 24337ec681f3Smrg 24347ec681f3SmrgHRESULT NINE_WINAPI 24357ec681f3SmrgNineDevice9_GetRenderState( struct NineDevice9 *This, 24367ec681f3Smrg D3DRENDERSTATETYPE State, 24377ec681f3Smrg DWORD *pValue ) 24387ec681f3Smrg{ 24397ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 24407ec681f3Smrg user_assert(pValue != NULL, D3DERR_INVALIDCALL); 24417ec681f3Smrg /* TODO: This needs tests */ 24427ec681f3Smrg if (State >= D3DRS_COUNT) { 24437ec681f3Smrg *pValue = 0; 24447ec681f3Smrg return D3D_OK; 24457ec681f3Smrg } 24467ec681f3Smrg 24477ec681f3Smrg *pValue = This->state.rs_advertised[State]; 24487ec681f3Smrg return D3D_OK; 24497ec681f3Smrg} 24507ec681f3Smrg 24517ec681f3SmrgHRESULT NINE_WINAPI 24527ec681f3SmrgNineDevice9_CreateStateBlock( struct NineDevice9 *This, 24537ec681f3Smrg D3DSTATEBLOCKTYPE Type, 24547ec681f3Smrg IDirect3DStateBlock9 **ppSB ) 24557ec681f3Smrg{ 24567ec681f3Smrg struct NineStateBlock9 *nsb; 24577ec681f3Smrg struct nine_state *dst; 24587ec681f3Smrg HRESULT hr; 24597ec681f3Smrg enum nine_stateblock_type type; 24607ec681f3Smrg unsigned s; 24617ec681f3Smrg 24627ec681f3Smrg DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB); 24637ec681f3Smrg 24647ec681f3Smrg user_assert(ppSB != NULL, D3DERR_INVALIDCALL); 24657ec681f3Smrg user_assert(Type == D3DSBT_ALL || 24667ec681f3Smrg Type == D3DSBT_VERTEXSTATE || 24677ec681f3Smrg Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL); 24687ec681f3Smrg 24697ec681f3Smrg switch (Type) { 24707ec681f3Smrg case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break; 24717ec681f3Smrg case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break; 24727ec681f3Smrg default: 24737ec681f3Smrg type = NINESBT_ALL; 24747ec681f3Smrg break; 24757ec681f3Smrg } 24767ec681f3Smrg 24777ec681f3Smrg hr = NineStateBlock9_new(This, &nsb, type); 24787ec681f3Smrg if (FAILED(hr)) 24797ec681f3Smrg return hr; 24807ec681f3Smrg *ppSB = (IDirect3DStateBlock9 *)nsb; 24817ec681f3Smrg dst = &nsb->state; 24827ec681f3Smrg 24837ec681f3Smrg dst->changed.group = NINE_STATE_SAMPLER; 24847ec681f3Smrg 24857ec681f3Smrg if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) { 24867ec681f3Smrg dst->changed.group |= 24877ec681f3Smrg NINE_STATE_FF_LIGHTING | 24887ec681f3Smrg NINE_STATE_VS | NINE_STATE_VS_CONST | 24897ec681f3Smrg NINE_STATE_VDECL; 24907ec681f3Smrg /* TODO: texture/sampler state */ 24917ec681f3Smrg memcpy(dst->changed.rs, 24927ec681f3Smrg nine_render_states_vertex, sizeof(dst->changed.rs)); 24937ec681f3Smrg nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f, 24947ec681f3Smrg &This->range_pool); 24957ec681f3Smrg nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I, 24967ec681f3Smrg &This->range_pool); 24977ec681f3Smrg nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B, 24987ec681f3Smrg &This->range_pool); 24997ec681f3Smrg for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 25007ec681f3Smrg dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET; 25017ec681f3Smrg if (This->state.ff.num_lights) { 25027ec681f3Smrg dst->ff.num_lights = This->state.ff.num_lights; 25037ec681f3Smrg /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so 25047ec681f3Smrg * all currently existing lights will be captured 25057ec681f3Smrg */ 25067ec681f3Smrg dst->ff.light = CALLOC(This->state.ff.num_lights, 25077ec681f3Smrg sizeof(D3DLIGHT9)); 25087ec681f3Smrg if (!dst->ff.light) { 25097ec681f3Smrg nine_bind(ppSB, NULL); 25107ec681f3Smrg return E_OUTOFMEMORY; 25117ec681f3Smrg } 25127ec681f3Smrg } 25137ec681f3Smrg } 25147ec681f3Smrg if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) { 25157ec681f3Smrg dst->changed.group |= 25167ec681f3Smrg NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_FF_PS_CONSTS; 25177ec681f3Smrg memcpy(dst->changed.rs, 25187ec681f3Smrg nine_render_states_pixel, sizeof(dst->changed.rs)); 25197ec681f3Smrg nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f, 25207ec681f3Smrg &This->range_pool); 25217ec681f3Smrg dst->changed.ps_const_i = 0xffff; 25227ec681f3Smrg dst->changed.ps_const_b = 0xffff; 25237ec681f3Smrg for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 25247ec681f3Smrg dst->changed.sampler[s] |= 0x1ffe; 25257ec681f3Smrg for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { 25267ec681f3Smrg dst->ff.changed.tex_stage[s][0] |= 0xffffffff; 25277ec681f3Smrg dst->ff.changed.tex_stage[s][1] |= 0xffffffff; 25287ec681f3Smrg } 25297ec681f3Smrg } 25307ec681f3Smrg if (Type == D3DSBT_ALL) { 25317ec681f3Smrg dst->changed.group |= 25327ec681f3Smrg NINE_STATE_VIEWPORT | 25337ec681f3Smrg NINE_STATE_SCISSOR | 25347ec681f3Smrg NINE_STATE_IDXBUF | 25357ec681f3Smrg NINE_STATE_FF_MATERIAL | 25367ec681f3Smrg NINE_STATE_FF_VSTRANSF; 25377ec681f3Smrg memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t)); 25387ec681f3Smrg dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1; 25397ec681f3Smrg dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; 25407ec681f3Smrg dst->changed.stream_freq = dst->changed.vtxbuf; 25417ec681f3Smrg dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; 25427ec681f3Smrg dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1; 25437ec681f3Smrg /* The doc says the projection, world, view and texture matrices 25447ec681f3Smrg * are saved, which would translate to: 25457ec681f3Smrg * dst->ff.changed.transform[0] = 0x00FF000C; 25467ec681f3Smrg * dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); 25477ec681f3Smrg * However we assume they meant save everything (which is basically just the 25487ec681f3Smrg * above plus the other world matrices). 25497ec681f3Smrg */ 25507ec681f3Smrg dst->ff.changed.transform[0] = 0x00FF000C; 25517ec681f3Smrg for (s = 0; s < 8; s++) 25527ec681f3Smrg dst->ff.changed.transform[8+s] = ~0; 25537ec681f3Smrg } 25547ec681f3Smrg NineStateBlock9_Capture(NineStateBlock9(*ppSB)); 25557ec681f3Smrg 25567ec681f3Smrg /* TODO: fixed function state */ 25577ec681f3Smrg 25587ec681f3Smrg return D3D_OK; 25597ec681f3Smrg} 25607ec681f3Smrg 25617ec681f3SmrgHRESULT NINE_WINAPI 25627ec681f3SmrgNineDevice9_BeginStateBlock( struct NineDevice9 *This ) 25637ec681f3Smrg{ 25647ec681f3Smrg HRESULT hr; 25657ec681f3Smrg 25667ec681f3Smrg DBG("This=%p\n", This); 25677ec681f3Smrg 25687ec681f3Smrg user_assert(!This->record, D3DERR_INVALIDCALL); 25697ec681f3Smrg 25707ec681f3Smrg hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM); 25717ec681f3Smrg if (FAILED(hr)) 25727ec681f3Smrg return hr; 25737ec681f3Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->record)); 25747ec681f3Smrg 25757ec681f3Smrg This->update = &This->record->state; 25767ec681f3Smrg This->is_recording = TRUE; 25777ec681f3Smrg 25787ec681f3Smrg return D3D_OK; 25797ec681f3Smrg} 25807ec681f3Smrg 25817ec681f3SmrgHRESULT NINE_WINAPI 25827ec681f3SmrgNineDevice9_EndStateBlock( struct NineDevice9 *This, 25837ec681f3Smrg IDirect3DStateBlock9 **ppSB ) 25847ec681f3Smrg{ 25857ec681f3Smrg DBG("This=%p ppSB=%p\n", This, ppSB); 25867ec681f3Smrg 25877ec681f3Smrg user_assert(This->record, D3DERR_INVALIDCALL); 25887ec681f3Smrg user_assert(ppSB != NULL, D3DERR_INVALIDCALL); 25897ec681f3Smrg 25907ec681f3Smrg This->update = &This->state; 25917ec681f3Smrg This->is_recording = FALSE; 25927ec681f3Smrg 25937ec681f3Smrg NineUnknown_AddRef(NineUnknown(This->record)); 25947ec681f3Smrg *ppSB = (IDirect3DStateBlock9 *)This->record; 25957ec681f3Smrg NineUnknown_Unbind(NineUnknown(This->record)); 25967ec681f3Smrg This->record = NULL; 25977ec681f3Smrg 25987ec681f3Smrg return D3D_OK; 25997ec681f3Smrg} 26007ec681f3Smrg 26017ec681f3SmrgHRESULT NINE_WINAPI 26027ec681f3SmrgNineDevice9_SetClipStatus( struct NineDevice9 *This, 26037ec681f3Smrg const D3DCLIPSTATUS9 *pClipStatus ) 26047ec681f3Smrg{ 26057ec681f3Smrg user_assert(pClipStatus, D3DERR_INVALIDCALL); 26067ec681f3Smrg return D3D_OK; 26077ec681f3Smrg} 26087ec681f3Smrg 26097ec681f3SmrgHRESULT NINE_WINAPI 26107ec681f3SmrgNineDevice9_GetClipStatus( struct NineDevice9 *This, 26117ec681f3Smrg D3DCLIPSTATUS9 *pClipStatus ) 26127ec681f3Smrg{ 26137ec681f3Smrg user_assert(pClipStatus, D3DERR_INVALIDCALL); 26147ec681f3Smrg /* Set/GetClipStatus is supposed to get the app some infos 26157ec681f3Smrg * about vertices being clipped if it is using the software 26167ec681f3Smrg * vertex rendering. It would be too complicated to implement. 26177ec681f3Smrg * Probably the info is for developpers when working on their 26187ec681f3Smrg * applications. Else it could be for apps to know if it is worth 26197ec681f3Smrg * drawing some elements. In that case it makes sense to send 26207ec681f3Smrg * 0 for ClipUnion and 0xFFFFFFFF for ClipIntersection (basically 26217ec681f3Smrg * means not all vertices are clipped). Those values are known to 26227ec681f3Smrg * be the default if SetClipStatus is not set. Else we could return 26237ec681f3Smrg * what was set with SetClipStatus unchanged. */ 26247ec681f3Smrg pClipStatus->ClipUnion = 0; 26257ec681f3Smrg pClipStatus->ClipIntersection = 0xFFFFFFFF; 26267ec681f3Smrg return D3D_OK; 26277ec681f3Smrg} 26287ec681f3Smrg 26297ec681f3SmrgHRESULT NINE_WINAPI 26307ec681f3SmrgNineDevice9_GetTexture( struct NineDevice9 *This, 26317ec681f3Smrg DWORD Stage, 26327ec681f3Smrg IDirect3DBaseTexture9 **ppTexture ) 26337ec681f3Smrg{ 26347ec681f3Smrg user_assert(Stage < NINE_MAX_SAMPLERS_PS || 26357ec681f3Smrg Stage == D3DDMAPSAMPLER || 26367ec681f3Smrg (Stage >= D3DVERTEXTEXTURESAMPLER0 && 26377ec681f3Smrg Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 26387ec681f3Smrg user_assert(ppTexture, D3DERR_INVALIDCALL); 26397ec681f3Smrg 26407ec681f3Smrg if (Stage >= D3DDMAPSAMPLER) 26417ec681f3Smrg Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 26427ec681f3Smrg 26437ec681f3Smrg *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage]; 26447ec681f3Smrg 26457ec681f3Smrg if (This->state.texture[Stage]) 26467ec681f3Smrg NineUnknown_AddRef(NineUnknown(This->state.texture[Stage])); 26477ec681f3Smrg return D3D_OK; 26487ec681f3Smrg} 26497ec681f3Smrg 26507ec681f3SmrgHRESULT NINE_WINAPI 26517ec681f3SmrgNineDevice9_SetTexture( struct NineDevice9 *This, 26527ec681f3Smrg DWORD Stage, 26537ec681f3Smrg IDirect3DBaseTexture9 *pTexture ) 26547ec681f3Smrg{ 26557ec681f3Smrg struct nine_state *state = This->update; 26567ec681f3Smrg struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture); 26577ec681f3Smrg struct NineBaseTexture9 *old; 26587ec681f3Smrg 26597ec681f3Smrg DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture); 26607ec681f3Smrg 26617ec681f3Smrg user_assert(Stage < NINE_MAX_SAMPLERS_PS || 26627ec681f3Smrg Stage == D3DDMAPSAMPLER || 26637ec681f3Smrg (Stage >= D3DVERTEXTEXTURESAMPLER0 && 26647ec681f3Smrg Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 26657ec681f3Smrg user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH && 26667ec681f3Smrg tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL); 26677ec681f3Smrg 26687ec681f3Smrg if (Stage >= D3DDMAPSAMPLER) 26697ec681f3Smrg Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 26707ec681f3Smrg 26717ec681f3Smrg if (This->is_recording) { 26727ec681f3Smrg state->changed.texture |= 1 << Stage; 26737ec681f3Smrg nine_bind(&state->texture[Stage], pTexture); 26747ec681f3Smrg return D3D_OK; 26757ec681f3Smrg } 26767ec681f3Smrg 26777ec681f3Smrg old = state->texture[Stage]; 26787ec681f3Smrg if (old == tex) 26797ec681f3Smrg return D3D_OK; 26807ec681f3Smrg 26817ec681f3Smrg NineBindTextureToDevice(This, &state->texture[Stage], tex); 26827ec681f3Smrg 26837ec681f3Smrg nine_context_set_texture(This, Stage, tex); 26847ec681f3Smrg 26857ec681f3Smrg return D3D_OK; 26867ec681f3Smrg} 26877ec681f3Smrg 26887ec681f3SmrgHRESULT NINE_WINAPI 26897ec681f3SmrgNineDevice9_GetTextureStageState( struct NineDevice9 *This, 26907ec681f3Smrg DWORD Stage, 26917ec681f3Smrg D3DTEXTURESTAGESTATETYPE Type, 26927ec681f3Smrg DWORD *pValue ) 26937ec681f3Smrg{ 26947ec681f3Smrg const struct nine_state *state = &This->state; 26957ec681f3Smrg 26967ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 26977ec681f3Smrg user_assert(pValue != NULL, D3DERR_INVALIDCALL); 26987ec681f3Smrg user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); 26997ec681f3Smrg user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 27007ec681f3Smrg 27017ec681f3Smrg *pValue = state->ff.tex_stage[Stage][Type]; 27027ec681f3Smrg 27037ec681f3Smrg return D3D_OK; 27047ec681f3Smrg} 27057ec681f3Smrg 27067ec681f3SmrgHRESULT NINE_WINAPI 27077ec681f3SmrgNineDevice9_SetTextureStageState( struct NineDevice9 *This, 27087ec681f3Smrg DWORD Stage, 27097ec681f3Smrg D3DTEXTURESTAGESTATETYPE Type, 27107ec681f3Smrg DWORD Value ) 27117ec681f3Smrg{ 27127ec681f3Smrg struct nine_state *state = This->update; 27137ec681f3Smrg 27147ec681f3Smrg DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value); 27157ec681f3Smrg nine_dump_D3DTSS_value(DBG_FF, Type, Value); 27167ec681f3Smrg 27177ec681f3Smrg user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); 27187ec681f3Smrg user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 27197ec681f3Smrg 27207ec681f3Smrg state->ff.tex_stage[Stage][Type] = Value; 27217ec681f3Smrg 27227ec681f3Smrg if (unlikely(This->is_recording)) { 27237ec681f3Smrg state->changed.group |= NINE_STATE_FF_PS_CONSTS; 27247ec681f3Smrg state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); 27257ec681f3Smrg } else 27267ec681f3Smrg nine_context_set_texture_stage_state(This, Stage, Type, Value); 27277ec681f3Smrg 27287ec681f3Smrg return D3D_OK; 27297ec681f3Smrg} 27307ec681f3Smrg 27317ec681f3SmrgHRESULT NINE_WINAPI 27327ec681f3SmrgNineDevice9_GetSamplerState( struct NineDevice9 *This, 27337ec681f3Smrg DWORD Sampler, 27347ec681f3Smrg D3DSAMPLERSTATETYPE Type, 27357ec681f3Smrg DWORD *pValue ) 27367ec681f3Smrg{ 27377ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 27387ec681f3Smrg user_assert(pValue != NULL, D3DERR_INVALIDCALL); 27397ec681f3Smrg user_assert(Sampler < NINE_MAX_SAMPLERS_PS || 27407ec681f3Smrg Sampler == D3DDMAPSAMPLER || 27417ec681f3Smrg (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 27427ec681f3Smrg Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 27437ec681f3Smrg 27447ec681f3Smrg if (Sampler >= D3DDMAPSAMPLER) 27457ec681f3Smrg Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 27467ec681f3Smrg 27477ec681f3Smrg *pValue = This->state.samp_advertised[Sampler][Type]; 27487ec681f3Smrg return D3D_OK; 27497ec681f3Smrg} 27507ec681f3Smrg 27517ec681f3SmrgHRESULT NINE_WINAPI 27527ec681f3SmrgNineDevice9_SetSamplerState( struct NineDevice9 *This, 27537ec681f3Smrg DWORD Sampler, 27547ec681f3Smrg D3DSAMPLERSTATETYPE Type, 27557ec681f3Smrg DWORD Value ) 27567ec681f3Smrg{ 27577ec681f3Smrg struct nine_state *state = This->update; 27587ec681f3Smrg 27597ec681f3Smrg DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This, 27607ec681f3Smrg Sampler, nine_D3DSAMP_to_str(Type), Value); 27617ec681f3Smrg 27627ec681f3Smrg user_assert(Sampler < NINE_MAX_SAMPLERS_PS || 27637ec681f3Smrg Sampler == D3DDMAPSAMPLER || 27647ec681f3Smrg (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 27657ec681f3Smrg Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 27667ec681f3Smrg 27677ec681f3Smrg if (Sampler >= D3DDMAPSAMPLER) 27687ec681f3Smrg Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 27697ec681f3Smrg 27707ec681f3Smrg if (unlikely(This->is_recording)) { 27717ec681f3Smrg state->samp_advertised[Sampler][Type] = Value; 27727ec681f3Smrg state->changed.group |= NINE_STATE_SAMPLER; 27737ec681f3Smrg state->changed.sampler[Sampler] |= 1 << Type; 27747ec681f3Smrg return D3D_OK; 27757ec681f3Smrg } 27767ec681f3Smrg 27777ec681f3Smrg if (state->samp_advertised[Sampler][Type] == Value) 27787ec681f3Smrg return D3D_OK; 27797ec681f3Smrg 27807ec681f3Smrg state->samp_advertised[Sampler][Type] = Value; 27817ec681f3Smrg nine_context_set_sampler_state(This, Sampler, Type, Value); 27827ec681f3Smrg 27837ec681f3Smrg return D3D_OK; 27847ec681f3Smrg} 27857ec681f3Smrg 27867ec681f3SmrgHRESULT NINE_WINAPI 27877ec681f3SmrgNineDevice9_ValidateDevice( struct NineDevice9 *This, 27887ec681f3Smrg DWORD *pNumPasses ) 27897ec681f3Smrg{ 27907ec681f3Smrg const struct nine_state *state = &This->state; 27917ec681f3Smrg unsigned i; 27927ec681f3Smrg unsigned w = 0, h = 0; 27937ec681f3Smrg 27947ec681f3Smrg DBG("This=%p pNumPasses=%p\n", This, pNumPasses); 27957ec681f3Smrg 27967ec681f3Smrg for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) { 27977ec681f3Smrg if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE || 27987ec681f3Smrg state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE) 27997ec681f3Smrg return D3DERR_UNSUPPORTEDTEXTUREFILTER; 28007ec681f3Smrg } 28017ec681f3Smrg 28027ec681f3Smrg for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { 28037ec681f3Smrg if (!state->rt[i]) 28047ec681f3Smrg continue; 28057ec681f3Smrg if (w == 0) { 28067ec681f3Smrg w = state->rt[i]->desc.Width; 28077ec681f3Smrg h = state->rt[i]->desc.Height; 28087ec681f3Smrg } else 28097ec681f3Smrg if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) { 28107ec681f3Smrg return D3DERR_CONFLICTINGRENDERSTATE; 28117ec681f3Smrg } 28127ec681f3Smrg } 28137ec681f3Smrg if (state->ds && 28147ec681f3Smrg (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) { 28157ec681f3Smrg if (w != 0 && 28167ec681f3Smrg (state->ds->desc.Width != w || state->ds->desc.Height != h)) 28177ec681f3Smrg return D3DERR_CONFLICTINGRENDERSTATE; 28187ec681f3Smrg } 28197ec681f3Smrg 28207ec681f3Smrg if (pNumPasses) 28217ec681f3Smrg *pNumPasses = 1; 28227ec681f3Smrg 28237ec681f3Smrg return D3D_OK; 28247ec681f3Smrg} 28257ec681f3Smrg 28267ec681f3SmrgHRESULT NINE_WINAPI 28277ec681f3SmrgNineDevice9_SetPaletteEntries( struct NineDevice9 *This, 28287ec681f3Smrg UINT PaletteNumber, 28297ec681f3Smrg const PALETTEENTRY *pEntries ) 28307ec681f3Smrg{ 28317ec681f3Smrg STUB(D3D_OK); /* like wine */ 28327ec681f3Smrg} 28337ec681f3Smrg 28347ec681f3SmrgHRESULT NINE_WINAPI 28357ec681f3SmrgNineDevice9_GetPaletteEntries( struct NineDevice9 *This, 28367ec681f3Smrg UINT PaletteNumber, 28377ec681f3Smrg PALETTEENTRY *pEntries ) 28387ec681f3Smrg{ 28397ec681f3Smrg STUB(D3DERR_INVALIDCALL); 28407ec681f3Smrg} 28417ec681f3Smrg 28427ec681f3SmrgHRESULT NINE_WINAPI 28437ec681f3SmrgNineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, 28447ec681f3Smrg UINT PaletteNumber ) 28457ec681f3Smrg{ 28467ec681f3Smrg STUB(D3D_OK); /* like wine */ 28477ec681f3Smrg} 28487ec681f3Smrg 28497ec681f3SmrgHRESULT NINE_WINAPI 28507ec681f3SmrgNineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, 28517ec681f3Smrg UINT *PaletteNumber ) 28527ec681f3Smrg{ 28537ec681f3Smrg STUB(D3DERR_INVALIDCALL); 28547ec681f3Smrg} 28557ec681f3Smrg 28567ec681f3SmrgHRESULT NINE_WINAPI 28577ec681f3SmrgNineDevice9_SetScissorRect( struct NineDevice9 *This, 28587ec681f3Smrg const RECT *pRect ) 28597ec681f3Smrg{ 28607ec681f3Smrg struct nine_state *state = This->update; 28617ec681f3Smrg 28627ec681f3Smrg user_assert(pRect != NULL, D3DERR_INVALIDCALL); 28637ec681f3Smrg 28647ec681f3Smrg DBG("x=(%u..%u) y=(%u..%u)\n", 28657ec681f3Smrg pRect->left, pRect->top, pRect->right, pRect->bottom); 28667ec681f3Smrg 28677ec681f3Smrg state->scissor.minx = pRect->left; 28687ec681f3Smrg state->scissor.miny = pRect->top; 28697ec681f3Smrg state->scissor.maxx = pRect->right; 28707ec681f3Smrg state->scissor.maxy = pRect->bottom; 28717ec681f3Smrg 28727ec681f3Smrg if (unlikely(This->is_recording)) 28737ec681f3Smrg state->changed.group |= NINE_STATE_SCISSOR; 28747ec681f3Smrg else 28757ec681f3Smrg nine_context_set_scissor(This, &state->scissor); 28767ec681f3Smrg 28777ec681f3Smrg return D3D_OK; 28787ec681f3Smrg} 28797ec681f3Smrg 28807ec681f3SmrgHRESULT NINE_WINAPI 28817ec681f3SmrgNineDevice9_GetScissorRect( struct NineDevice9 *This, 28827ec681f3Smrg RECT *pRect ) 28837ec681f3Smrg{ 28847ec681f3Smrg user_assert(pRect != NULL, D3DERR_INVALIDCALL); 28857ec681f3Smrg 28867ec681f3Smrg pRect->left = This->state.scissor.minx; 28877ec681f3Smrg pRect->top = This->state.scissor.miny; 28887ec681f3Smrg pRect->right = This->state.scissor.maxx; 28897ec681f3Smrg pRect->bottom = This->state.scissor.maxy; 28907ec681f3Smrg 28917ec681f3Smrg return D3D_OK; 28927ec681f3Smrg} 28937ec681f3Smrg 28947ec681f3SmrgHRESULT NINE_WINAPI 28957ec681f3SmrgNineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, 28967ec681f3Smrg BOOL bSoftware ) 28977ec681f3Smrg{ 28987ec681f3Smrg if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { 28997ec681f3Smrg This->swvp = bSoftware; 29007ec681f3Smrg nine_context_set_swvp(This, bSoftware); 29017ec681f3Smrg return D3D_OK; 29027ec681f3Smrg } else 29037ec681f3Smrg return D3D_OK; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */ 29047ec681f3Smrg} 29057ec681f3Smrg 29067ec681f3SmrgBOOL NINE_WINAPI 29077ec681f3SmrgNineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) 29087ec681f3Smrg{ 29097ec681f3Smrg return This->swvp; 29107ec681f3Smrg} 29117ec681f3Smrg 29127ec681f3SmrgHRESULT NINE_WINAPI 29137ec681f3SmrgNineDevice9_SetNPatchMode( struct NineDevice9 *This, 29147ec681f3Smrg float nSegments ) 29157ec681f3Smrg{ 29167ec681f3Smrg return D3D_OK; /* Nothing to do because we don't advertise NPatch support */ 29177ec681f3Smrg} 29187ec681f3Smrg 29197ec681f3Smrgfloat NINE_WINAPI 29207ec681f3SmrgNineDevice9_GetNPatchMode( struct NineDevice9 *This ) 29217ec681f3Smrg{ 29227ec681f3Smrg STUB(0); 29237ec681f3Smrg} 29247ec681f3Smrg 29257ec681f3Smrg/* TODO: only go through dirty textures */ 29267ec681f3Smrgstatic void 29277ec681f3Smrgvalidate_textures(struct NineDevice9 *device) 29287ec681f3Smrg{ 29297ec681f3Smrg struct NineBaseTexture9 *tex, *ptr; 29307ec681f3Smrg LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) { 29317ec681f3Smrg list_delinit(&tex->list); 29327ec681f3Smrg NineBaseTexture9_Validate(tex); 29337ec681f3Smrg } 29347ec681f3Smrg} 29357ec681f3Smrg 29367ec681f3Smrgstatic void 29377ec681f3Smrgupdate_managed_buffers(struct NineDevice9 *device) 29387ec681f3Smrg{ 29397ec681f3Smrg struct NineBuffer9 *buf, *ptr; 29407ec681f3Smrg LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) { 29417ec681f3Smrg list_delinit(&buf->managed.list); 29427ec681f3Smrg NineBuffer9_Upload(buf); 29437ec681f3Smrg } 29447ec681f3Smrg} 29457ec681f3Smrg 29467ec681f3Smrgstatic void 29477ec681f3SmrgNineBeforeDraw( struct NineDevice9 *This ) 29487ec681f3Smrg{ 29497ec681f3Smrg /* Upload Managed dirty content */ 29507ec681f3Smrg validate_textures(This); /* may clobber state */ 29517ec681f3Smrg update_managed_buffers(This); 29527ec681f3Smrg} 29537ec681f3Smrg 29547ec681f3Smrgstatic void 29557ec681f3SmrgNineAfterDraw( struct NineDevice9 *This ) 29567ec681f3Smrg{ 29577ec681f3Smrg unsigned i; 29587ec681f3Smrg struct nine_state *state = &This->state; 29597ec681f3Smrg unsigned ps_mask = state->ps ? state->ps->rt_mask : 1; 29607ec681f3Smrg 29617ec681f3Smrg /* Flag render-targets with autogenmipmap for mipmap regeneration */ 29627ec681f3Smrg for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { 29637ec681f3Smrg struct NineSurface9 *rt = state->rt[i]; 29647ec681f3Smrg 29657ec681f3Smrg if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) && 29667ec681f3Smrg rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) { 29677ec681f3Smrg assert(rt->texture == D3DRTYPE_TEXTURE || 29687ec681f3Smrg rt->texture == D3DRTYPE_CUBETEXTURE); 29697ec681f3Smrg NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE; 29707ec681f3Smrg } 29717ec681f3Smrg } 29727ec681f3Smrg} 29737ec681f3Smrg 29747ec681f3Smrg#define IS_SYSTEMMEM_DYNAMIC(t) ((t) && (t)->base.pool == D3DPOOL_SYSTEMMEM && (t)->base.usage & D3DUSAGE_DYNAMIC) 29757ec681f3Smrg 29767ec681f3Smrg/* Indicates the region needed right now for these buffers and add them to the list 29777ec681f3Smrg * of buffers to process in NineBeforeDraw. 29787ec681f3Smrg * The reason we don't call the upload right now is to generate smaller code (no 29797ec681f3Smrg * duplication of the NineBuffer9_Upload inline) and to have one upload (of the correct size) 29807ec681f3Smrg * if a vertex buffer is twice input of the draw call. */ 29817ec681f3Smrgstatic void 29827ec681f3SmrgNineTrackSystemmemDynamic( struct NineBuffer9 *This, unsigned start, unsigned width ) 29837ec681f3Smrg{ 29847ec681f3Smrg struct pipe_box box; 29857ec681f3Smrg 29867ec681f3Smrg u_box_1d(start, width, &box); 29877ec681f3Smrg u_box_union_1d(&This->managed.required_valid_region, 29887ec681f3Smrg &This->managed.required_valid_region, 29897ec681f3Smrg &box); 29907ec681f3Smrg This->managed.dirty = TRUE; 29917ec681f3Smrg BASEBUF_REGISTER_UPDATE(This); 29927ec681f3Smrg} 29937ec681f3Smrg 29947ec681f3SmrgHRESULT NINE_WINAPI 29957ec681f3SmrgNineDevice9_DrawPrimitive( struct NineDevice9 *This, 29967ec681f3Smrg D3DPRIMITIVETYPE PrimitiveType, 29977ec681f3Smrg UINT StartVertex, 29987ec681f3Smrg UINT PrimitiveCount ) 29997ec681f3Smrg{ 30007ec681f3Smrg unsigned i; 30017ec681f3Smrg DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n", 30027ec681f3Smrg This, PrimitiveType, StartVertex, PrimitiveCount); 30037ec681f3Smrg 30047ec681f3Smrg /* Tracking for dynamic SYSTEMMEM */ 30057ec681f3Smrg for (i = 0; i < This->caps.MaxStreams; i++) { 30067ec681f3Smrg unsigned stride = This->state.vtxbuf[i].stride; 30077ec681f3Smrg if (IS_SYSTEMMEM_DYNAMIC((struct NineBuffer9*)This->state.stream[i])) { 30087ec681f3Smrg unsigned start = This->state.vtxbuf[i].buffer_offset + StartVertex * stride; 30097ec681f3Smrg unsigned full_size = This->state.stream[i]->base.size; 30107ec681f3Smrg unsigned num_vertices = prim_count_to_vertex_count(PrimitiveType, PrimitiveCount); 30117ec681f3Smrg unsigned size = MIN2(full_size-start, num_vertices * stride); 30127ec681f3Smrg if (!stride) /* Instancing. Not sure what to do. Require all */ 30137ec681f3Smrg size = full_size; 30147ec681f3Smrg NineTrackSystemmemDynamic(&This->state.stream[i]->base, start, size); 30157ec681f3Smrg } 30167ec681f3Smrg } 30177ec681f3Smrg 30187ec681f3Smrg NineBeforeDraw(This); 30197ec681f3Smrg nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount); 30207ec681f3Smrg NineAfterDraw(This); 30217ec681f3Smrg 30227ec681f3Smrg return D3D_OK; 30237ec681f3Smrg} 30247ec681f3Smrg 30257ec681f3SmrgHRESULT NINE_WINAPI 30267ec681f3SmrgNineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, 30277ec681f3Smrg D3DPRIMITIVETYPE PrimitiveType, 30287ec681f3Smrg INT BaseVertexIndex, 30297ec681f3Smrg UINT MinVertexIndex, 30307ec681f3Smrg UINT NumVertices, 30317ec681f3Smrg UINT StartIndex, 30327ec681f3Smrg UINT PrimitiveCount ) 30337ec681f3Smrg{ 30347ec681f3Smrg unsigned i, num_indices; 30357ec681f3Smrg DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u " 30367ec681f3Smrg "NumVertices %u, StartIndex %u, PrimitiveCount %u\n", 30377ec681f3Smrg This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, 30387ec681f3Smrg StartIndex, PrimitiveCount); 30397ec681f3Smrg 30407ec681f3Smrg user_assert(This->state.idxbuf, D3DERR_INVALIDCALL); 30417ec681f3Smrg user_assert(This->state.vdecl, D3DERR_INVALIDCALL); 30427ec681f3Smrg 30437ec681f3Smrg num_indices = prim_count_to_vertex_count(PrimitiveType, PrimitiveCount); 30447ec681f3Smrg 30457ec681f3Smrg /* Tracking for dynamic SYSTEMMEM */ 30467ec681f3Smrg if (IS_SYSTEMMEM_DYNAMIC(&This->state.idxbuf->base)) 30477ec681f3Smrg NineTrackSystemmemDynamic(&This->state.idxbuf->base, 30487ec681f3Smrg StartIndex * This->state.idxbuf->index_size, 30497ec681f3Smrg num_indices * This->state.idxbuf->index_size); 30507ec681f3Smrg 30517ec681f3Smrg for (i = 0; i < This->caps.MaxStreams; i++) { 30527ec681f3Smrg if (IS_SYSTEMMEM_DYNAMIC((struct NineBuffer9*)This->state.stream[i])) { 30537ec681f3Smrg uint32_t stride = This->state.vtxbuf[i].stride; 30547ec681f3Smrg uint32_t full_size = This->state.stream[i]->base.size; 30557ec681f3Smrg uint32_t start, stop; 30567ec681f3Smrg 30577ec681f3Smrg start = MAX2(0, This->state.vtxbuf[i].buffer_offset+(MinVertexIndex+BaseVertexIndex)*stride); 30587ec681f3Smrg stop = This->state.vtxbuf[i].buffer_offset+(MinVertexIndex+NumVertices+BaseVertexIndex)*stride; 30597ec681f3Smrg stop = MIN2(stop, full_size); 30607ec681f3Smrg NineTrackSystemmemDynamic(&This->state.stream[i]->base, 30617ec681f3Smrg start, stop-start); 30627ec681f3Smrg } 30637ec681f3Smrg } 30647ec681f3Smrg 30657ec681f3Smrg NineBeforeDraw(This); 30667ec681f3Smrg nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex, 30677ec681f3Smrg MinVertexIndex, NumVertices, StartIndex, 30687ec681f3Smrg PrimitiveCount); 30697ec681f3Smrg NineAfterDraw(This); 30707ec681f3Smrg 30717ec681f3Smrg return D3D_OK; 30727ec681f3Smrg} 30737ec681f3Smrg 30747ec681f3Smrgstatic void 30757ec681f3SmrgNineDevice9_SetStreamSourceNULL( struct NineDevice9 *This ); 30767ec681f3Smrg 30777ec681f3SmrgHRESULT NINE_WINAPI 30787ec681f3SmrgNineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, 30797ec681f3Smrg D3DPRIMITIVETYPE PrimitiveType, 30807ec681f3Smrg UINT PrimitiveCount, 30817ec681f3Smrg const void *pVertexStreamZeroData, 30827ec681f3Smrg UINT VertexStreamZeroStride ) 30837ec681f3Smrg{ 30847ec681f3Smrg struct pipe_resource *resource = NULL; 30857ec681f3Smrg unsigned buffer_offset; 30867ec681f3Smrg unsigned StartVertex = 0; 30877ec681f3Smrg 30887ec681f3Smrg DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n", 30897ec681f3Smrg This, PrimitiveType, PrimitiveCount, 30907ec681f3Smrg pVertexStreamZeroData, VertexStreamZeroStride); 30917ec681f3Smrg 30927ec681f3Smrg user_assert(pVertexStreamZeroData && VertexStreamZeroStride, 30937ec681f3Smrg D3DERR_INVALIDCALL); 30947ec681f3Smrg user_assert(PrimitiveCount, D3D_OK); 30957ec681f3Smrg 30967ec681f3Smrg u_upload_data(This->vertex_uploader, 30977ec681f3Smrg 0, 30987ec681f3Smrg (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, 30997ec681f3Smrg 1, 31007ec681f3Smrg pVertexStreamZeroData, 31017ec681f3Smrg &buffer_offset, 31027ec681f3Smrg &resource); 31037ec681f3Smrg u_upload_unmap(This->vertex_uploader); 31047ec681f3Smrg 31057ec681f3Smrg /* Optimization to skip changing the bound vertex buffer data 31067ec681f3Smrg * for consecutive DrawPrimitiveUp with identical VertexStreamZeroStride */ 31077ec681f3Smrg if (VertexStreamZeroStride > 0) { 31087ec681f3Smrg StartVertex = buffer_offset / VertexStreamZeroStride; 31097ec681f3Smrg buffer_offset -= StartVertex * VertexStreamZeroStride; 31107ec681f3Smrg } 31117ec681f3Smrg 31127ec681f3Smrg nine_context_set_stream_source_apply(This, 0, resource, 31137ec681f3Smrg buffer_offset, VertexStreamZeroStride); 31147ec681f3Smrg pipe_resource_reference(&resource, NULL); 31157ec681f3Smrg 31167ec681f3Smrg NineBeforeDraw(This); 31177ec681f3Smrg nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount); 31187ec681f3Smrg NineAfterDraw(This); 31197ec681f3Smrg 31207ec681f3Smrg NineDevice9_PauseRecording(This); 31217ec681f3Smrg NineDevice9_SetStreamSourceNULL(This); 31227ec681f3Smrg NineDevice9_ResumeRecording(This); 31237ec681f3Smrg 31247ec681f3Smrg return D3D_OK; 31257ec681f3Smrg} 31267ec681f3Smrg 31277ec681f3SmrgHRESULT NINE_WINAPI 31287ec681f3SmrgNineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, 31297ec681f3Smrg D3DPRIMITIVETYPE PrimitiveType, 31307ec681f3Smrg UINT MinVertexIndex, 31317ec681f3Smrg UINT NumVertices, 31327ec681f3Smrg UINT PrimitiveCount, 31337ec681f3Smrg const void *pIndexData, 31347ec681f3Smrg D3DFORMAT IndexDataFormat, 31357ec681f3Smrg const void *pVertexStreamZeroData, 31367ec681f3Smrg UINT VertexStreamZeroStride ) 31377ec681f3Smrg{ 31387ec681f3Smrg struct pipe_vertex_buffer vbuf; 31397ec681f3Smrg unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4; 31407ec681f3Smrg struct pipe_resource *ibuf = NULL; 31417ec681f3Smrg unsigned base; 31427ec681f3Smrg 31437ec681f3Smrg DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u " 31447ec681f3Smrg "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u " 31457ec681f3Smrg "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n", 31467ec681f3Smrg This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, 31477ec681f3Smrg pIndexData, IndexDataFormat, 31487ec681f3Smrg pVertexStreamZeroData, VertexStreamZeroStride); 31497ec681f3Smrg 31507ec681f3Smrg user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL); 31517ec681f3Smrg user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL); 31527ec681f3Smrg user_assert(IndexDataFormat == D3DFMT_INDEX16 || 31537ec681f3Smrg IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL); 31547ec681f3Smrg user_assert(PrimitiveCount, D3D_OK); 31557ec681f3Smrg 31567ec681f3Smrg base = MinVertexIndex * VertexStreamZeroStride; 31577ec681f3Smrg vbuf.is_user_buffer = false; 31587ec681f3Smrg vbuf.buffer.resource = NULL; 31597ec681f3Smrg vbuf.stride = VertexStreamZeroStride; 31607ec681f3Smrg u_upload_data(This->vertex_uploader, 31617ec681f3Smrg base, 31627ec681f3Smrg NumVertices * VertexStreamZeroStride, /* XXX */ 31637ec681f3Smrg 64, 31647ec681f3Smrg (const uint8_t *)pVertexStreamZeroData + base, 31657ec681f3Smrg &vbuf.buffer_offset, 31667ec681f3Smrg &vbuf.buffer.resource); 31677ec681f3Smrg u_upload_unmap(This->vertex_uploader); 31687ec681f3Smrg /* Won't be used: */ 31697ec681f3Smrg vbuf.buffer_offset -= base; 31707ec681f3Smrg 31717ec681f3Smrg unsigned index_offset = 0; 31727ec681f3Smrg u_upload_data(This->pipe_secondary->stream_uploader, 31737ec681f3Smrg 0, 31747ec681f3Smrg (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size, 31757ec681f3Smrg 64, 31767ec681f3Smrg pIndexData, 31777ec681f3Smrg &index_offset, 31787ec681f3Smrg &ibuf); 31797ec681f3Smrg u_upload_unmap(This->pipe_secondary->stream_uploader); 31807ec681f3Smrg 31817ec681f3Smrg NineBeforeDraw(This); 31827ec681f3Smrg nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType, 31837ec681f3Smrg MinVertexIndex, 31847ec681f3Smrg NumVertices, 31857ec681f3Smrg PrimitiveCount, 31867ec681f3Smrg &vbuf, 31877ec681f3Smrg ibuf, 31887ec681f3Smrg ibuf ? NULL : (void*)pIndexData, 31897ec681f3Smrg index_offset, 31907ec681f3Smrg index_size); 31917ec681f3Smrg NineAfterDraw(This); 31927ec681f3Smrg 31937ec681f3Smrg pipe_vertex_buffer_unreference(&vbuf); 31947ec681f3Smrg pipe_resource_reference(&ibuf, NULL); 31957ec681f3Smrg 31967ec681f3Smrg NineDevice9_PauseRecording(This); 31977ec681f3Smrg NineDevice9_SetIndices(This, NULL); 31987ec681f3Smrg NineDevice9_SetStreamSourceNULL(This); 31997ec681f3Smrg NineDevice9_ResumeRecording(This); 32007ec681f3Smrg 32017ec681f3Smrg return D3D_OK; 32027ec681f3Smrg} 32037ec681f3Smrg 32047ec681f3SmrgHRESULT NINE_WINAPI 32057ec681f3SmrgNineDevice9_ProcessVertices( struct NineDevice9 *This, 32067ec681f3Smrg UINT SrcStartIndex, 32077ec681f3Smrg UINT DestIndex, 32087ec681f3Smrg UINT VertexCount, 32097ec681f3Smrg IDirect3DVertexBuffer9 *pDestBuffer, 32107ec681f3Smrg IDirect3DVertexDeclaration9 *pVertexDecl, 32117ec681f3Smrg DWORD Flags ) 32127ec681f3Smrg{ 32137ec681f3Smrg struct pipe_screen *screen_sw = This->screen_sw; 32147ec681f3Smrg struct pipe_context *pipe_sw = This->pipe_sw; 32157ec681f3Smrg struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl); 32167ec681f3Smrg struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer); 32177ec681f3Smrg struct NineVertexShader9 *vs; 32187ec681f3Smrg struct pipe_resource *resource; 32197ec681f3Smrg struct pipe_transfer *transfer = NULL; 32207ec681f3Smrg struct pipe_stream_output_info so; 32217ec681f3Smrg struct pipe_stream_output_target *target; 32227ec681f3Smrg struct pipe_draw_info draw; 32237ec681f3Smrg struct pipe_draw_start_count_bias sc; 32247ec681f3Smrg struct pipe_box box; 32257ec681f3Smrg bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t); 32267ec681f3Smrg unsigned offsets[1] = {0}; 32277ec681f3Smrg HRESULT hr; 32287ec681f3Smrg unsigned buffer_size; 32297ec681f3Smrg void *map; 32307ec681f3Smrg 32317ec681f3Smrg DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u " 32327ec681f3Smrg "pDestBuffer=%p pVertexDecl=%p Flags=%d\n", 32337ec681f3Smrg This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, 32347ec681f3Smrg pVertexDecl, Flags); 32357ec681f3Smrg 32367ec681f3Smrg user_assert(pDestBuffer && pVertexDecl, D3DERR_INVALIDCALL); 32377ec681f3Smrg 32387ec681f3Smrg if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) { 32397ec681f3Smrg DBG("ProcessVertices not supported\n"); 32407ec681f3Smrg return D3DERR_INVALIDCALL; 32417ec681f3Smrg } 32427ec681f3Smrg 32437ec681f3Smrg 32447ec681f3Smrg vs = programmable_vs ? This->state.vs : This->ff.vs; 32457ec681f3Smrg /* Note: version is 0 for ff */ 32467ec681f3Smrg user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF), 32477ec681f3Smrg D3DERR_INVALIDCALL); 32487ec681f3Smrg if (!vdecl) { 32497ec681f3Smrg DWORD FVF = dst->desc.FVF; 32507ec681f3Smrg vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); 32517ec681f3Smrg if (!vdecl) { 32527ec681f3Smrg hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); 32537ec681f3Smrg if (FAILED(hr)) 32547ec681f3Smrg return hr; 32557ec681f3Smrg vdecl->fvf = FVF; 32567ec681f3Smrg _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); 32577ec681f3Smrg NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); 32587ec681f3Smrg } 32597ec681f3Smrg } 32607ec681f3Smrg 32617ec681f3Smrg /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags 32627ec681f3Smrg * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular 32637ec681f3Smrg * if not set, everything from src will be used, and dst 32647ec681f3Smrg * must match exactly the ff vs outputs. 32657ec681f3Smrg * TODO: Handle all the checks, etc for ff */ 32667ec681f3Smrg user_assert(vdecl->position_t || programmable_vs, 32677ec681f3Smrg D3DERR_INVALIDCALL); 32687ec681f3Smrg 32697ec681f3Smrg /* TODO: Support vs < 3 and ff */ 32707ec681f3Smrg user_assert(vs->byte_code.version == 0x30, 32717ec681f3Smrg D3DERR_INVALIDCALL); 32727ec681f3Smrg /* TODO: Not hardcode the constant buffers for swvp */ 32737ec681f3Smrg user_assert(This->may_swvp, 32747ec681f3Smrg D3DERR_INVALIDCALL); 32757ec681f3Smrg 32767ec681f3Smrg nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so); 32777ec681f3Smrg 32787ec681f3Smrg buffer_size = VertexCount * so.stride[0] * 4; 32797ec681f3Smrg { 32807ec681f3Smrg struct pipe_resource templ; 32817ec681f3Smrg 32827ec681f3Smrg memset(&templ, 0, sizeof(templ)); 32837ec681f3Smrg templ.target = PIPE_BUFFER; 32847ec681f3Smrg templ.format = PIPE_FORMAT_R8_UNORM; 32857ec681f3Smrg templ.width0 = buffer_size; 32867ec681f3Smrg templ.flags = 0; 32877ec681f3Smrg templ.bind = PIPE_BIND_STREAM_OUTPUT; 32887ec681f3Smrg templ.usage = PIPE_USAGE_STREAM; 32897ec681f3Smrg templ.height0 = templ.depth0 = templ.array_size = 1; 32907ec681f3Smrg templ.last_level = templ.nr_samples = templ.nr_storage_samples = 0; 32917ec681f3Smrg 32927ec681f3Smrg resource = screen_sw->resource_create(screen_sw, &templ); 32937ec681f3Smrg if (!resource) 32947ec681f3Smrg return E_OUTOFMEMORY; 32957ec681f3Smrg } 32967ec681f3Smrg target = pipe_sw->create_stream_output_target(pipe_sw, resource, 32977ec681f3Smrg 0, buffer_size); 32987ec681f3Smrg if (!target) { 32997ec681f3Smrg pipe_resource_reference(&resource, NULL); 33007ec681f3Smrg return D3DERR_DRIVERINTERNALERROR; 33017ec681f3Smrg } 33027ec681f3Smrg 33037ec681f3Smrg draw.mode = PIPE_PRIM_POINTS; 33047ec681f3Smrg sc.count = VertexCount; 33057ec681f3Smrg draw.start_instance = 0; 33067ec681f3Smrg draw.primitive_restart = FALSE; 33077ec681f3Smrg draw.restart_index = 0; 33087ec681f3Smrg draw.instance_count = 1; 33097ec681f3Smrg draw.index_size = 0; 33107ec681f3Smrg sc.start = 0; 33117ec681f3Smrg sc.index_bias = 0; 33127ec681f3Smrg draw.min_index = 0; 33137ec681f3Smrg draw.max_index = VertexCount - 1; 33147ec681f3Smrg 33157ec681f3Smrg 33167ec681f3Smrg pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets); 33177ec681f3Smrg 33187ec681f3Smrg pipe_sw->draw_vbo(pipe_sw, &draw, 0, NULL, &sc, 1); 33197ec681f3Smrg 33207ec681f3Smrg pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0); 33217ec681f3Smrg pipe_sw->stream_output_target_destroy(pipe_sw, target); 33227ec681f3Smrg 33237ec681f3Smrg u_box_1d(0, VertexCount * so.stride[0] * 4, &box); 33247ec681f3Smrg map = pipe_sw->buffer_map(pipe_sw, resource, 0, PIPE_MAP_READ, &box, 33257ec681f3Smrg &transfer); 33267ec681f3Smrg if (!map) { 33277ec681f3Smrg hr = D3DERR_DRIVERINTERNALERROR; 33287ec681f3Smrg goto out; 33297ec681f3Smrg } 33307ec681f3Smrg 33317ec681f3Smrg hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl, 33327ec681f3Smrg dst, DestIndex, VertexCount, 33337ec681f3Smrg map, &so); 33347ec681f3Smrg if (transfer) 33357ec681f3Smrg pipe_sw->buffer_unmap(pipe_sw, transfer); 33367ec681f3Smrg 33377ec681f3Smrgout: 33387ec681f3Smrg nine_state_after_draw_sw(This); 33397ec681f3Smrg pipe_resource_reference(&resource, NULL); 33407ec681f3Smrg return hr; 33417ec681f3Smrg} 33427ec681f3Smrg 33437ec681f3SmrgHRESULT NINE_WINAPI 33447ec681f3SmrgNineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, 33457ec681f3Smrg const D3DVERTEXELEMENT9 *pVertexElements, 33467ec681f3Smrg IDirect3DVertexDeclaration9 **ppDecl ) 33477ec681f3Smrg{ 33487ec681f3Smrg struct NineVertexDeclaration9 *vdecl; 33497ec681f3Smrg 33507ec681f3Smrg DBG("This=%p pVertexElements=%p ppDecl=%p\n", 33517ec681f3Smrg This, pVertexElements, ppDecl); 33527ec681f3Smrg 33537ec681f3Smrg user_assert(pVertexElements && ppDecl, D3DERR_INVALIDCALL); 33547ec681f3Smrg 33557ec681f3Smrg HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl); 33567ec681f3Smrg if (SUCCEEDED(hr)) 33577ec681f3Smrg *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl; 33587ec681f3Smrg 33597ec681f3Smrg return hr; 33607ec681f3Smrg} 33617ec681f3Smrg 33627ec681f3SmrgHRESULT NINE_WINAPI 33637ec681f3SmrgNineDevice9_SetVertexDeclaration( struct NineDevice9 *This, 33647ec681f3Smrg IDirect3DVertexDeclaration9 *pDecl ) 33657ec681f3Smrg{ 33667ec681f3Smrg struct nine_state *state = This->update; 33677ec681f3Smrg struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl); 33687ec681f3Smrg 33697ec681f3Smrg DBG("This=%p pDecl=%p\n", This, pDecl); 33707ec681f3Smrg 33717ec681f3Smrg if (unlikely(This->is_recording)) { 33727ec681f3Smrg nine_bind(&state->vdecl, vdecl); 33737ec681f3Smrg state->changed.group |= NINE_STATE_VDECL; 33747ec681f3Smrg return D3D_OK; 33757ec681f3Smrg } 33767ec681f3Smrg 33777ec681f3Smrg if (state->vdecl == vdecl) 33787ec681f3Smrg return D3D_OK; 33797ec681f3Smrg 33807ec681f3Smrg nine_bind(&state->vdecl, vdecl); 33817ec681f3Smrg 33827ec681f3Smrg nine_context_set_vertex_declaration(This, vdecl); 33837ec681f3Smrg 33847ec681f3Smrg return D3D_OK; 33857ec681f3Smrg} 33867ec681f3Smrg 33877ec681f3SmrgHRESULT NINE_WINAPI 33887ec681f3SmrgNineDevice9_GetVertexDeclaration( struct NineDevice9 *This, 33897ec681f3Smrg IDirect3DVertexDeclaration9 **ppDecl ) 33907ec681f3Smrg{ 33917ec681f3Smrg user_assert(ppDecl, D3DERR_INVALIDCALL); 33927ec681f3Smrg 33937ec681f3Smrg *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl; 33947ec681f3Smrg if (*ppDecl) 33957ec681f3Smrg NineUnknown_AddRef(NineUnknown(*ppDecl)); 33967ec681f3Smrg return D3D_OK; 33977ec681f3Smrg} 33987ec681f3Smrg 33997ec681f3SmrgHRESULT NINE_WINAPI 34007ec681f3SmrgNineDevice9_SetFVF( struct NineDevice9 *This, 34017ec681f3Smrg DWORD FVF ) 34027ec681f3Smrg{ 34037ec681f3Smrg struct NineVertexDeclaration9 *vdecl; 34047ec681f3Smrg HRESULT hr; 34057ec681f3Smrg 34067ec681f3Smrg DBG("FVF = %08x\n", FVF); 34077ec681f3Smrg if (!FVF) 34087ec681f3Smrg return D3D_OK; /* like wine */ 34097ec681f3Smrg 34107ec681f3Smrg vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); 34117ec681f3Smrg if (!vdecl) { 34127ec681f3Smrg hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); 34137ec681f3Smrg if (FAILED(hr)) 34147ec681f3Smrg return hr; 34157ec681f3Smrg vdecl->fvf = FVF; 34167ec681f3Smrg _mesa_hash_table_insert(This->ff.ht_fvf, &vdecl->fvf, vdecl); 34177ec681f3Smrg NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); 34187ec681f3Smrg } 34197ec681f3Smrg return NineDevice9_SetVertexDeclaration( 34207ec681f3Smrg This, (IDirect3DVertexDeclaration9 *)vdecl); 34217ec681f3Smrg} 34227ec681f3Smrg 34237ec681f3SmrgHRESULT NINE_WINAPI 34247ec681f3SmrgNineDevice9_GetFVF( struct NineDevice9 *This, 34257ec681f3Smrg DWORD *pFVF ) 34267ec681f3Smrg{ 34277ec681f3Smrg user_assert(pFVF != NULL, D3DERR_INVALIDCALL); 34287ec681f3Smrg *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0; 34297ec681f3Smrg return D3D_OK; 34307ec681f3Smrg} 34317ec681f3Smrg 34327ec681f3SmrgHRESULT NINE_WINAPI 34337ec681f3SmrgNineDevice9_CreateVertexShader( struct NineDevice9 *This, 34347ec681f3Smrg const DWORD *pFunction, 34357ec681f3Smrg IDirect3DVertexShader9 **ppShader ) 34367ec681f3Smrg{ 34377ec681f3Smrg struct NineVertexShader9 *vs; 34387ec681f3Smrg HRESULT hr; 34397ec681f3Smrg 34407ec681f3Smrg DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 34417ec681f3Smrg 34427ec681f3Smrg user_assert(pFunction && ppShader, D3DERR_INVALIDCALL); 34437ec681f3Smrg 34447ec681f3Smrg hr = NineVertexShader9_new(This, &vs, pFunction, NULL); 34457ec681f3Smrg if (FAILED(hr)) 34467ec681f3Smrg return hr; 34477ec681f3Smrg *ppShader = (IDirect3DVertexShader9 *)vs; 34487ec681f3Smrg return D3D_OK; 34497ec681f3Smrg} 34507ec681f3Smrg 34517ec681f3SmrgHRESULT NINE_WINAPI 34527ec681f3SmrgNineDevice9_SetVertexShader( struct NineDevice9 *This, 34537ec681f3Smrg IDirect3DVertexShader9 *pShader ) 34547ec681f3Smrg{ 34557ec681f3Smrg struct nine_state *state = This->update; 34567ec681f3Smrg struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader; 34577ec681f3Smrg 34587ec681f3Smrg DBG("This=%p pShader=%p\n", This, pShader); 34597ec681f3Smrg 34607ec681f3Smrg if (unlikely(This->is_recording)) { 34617ec681f3Smrg nine_bind(&state->vs, vs_shader); 34627ec681f3Smrg state->changed.group |= NINE_STATE_VS; 34637ec681f3Smrg return D3D_OK; 34647ec681f3Smrg } 34657ec681f3Smrg 34667ec681f3Smrg if (state->vs == vs_shader) 34677ec681f3Smrg return D3D_OK; 34687ec681f3Smrg 34697ec681f3Smrg nine_bind(&state->vs, vs_shader); 34707ec681f3Smrg 34717ec681f3Smrg nine_context_set_vertex_shader(This, vs_shader); 34727ec681f3Smrg 34737ec681f3Smrg return D3D_OK; 34747ec681f3Smrg} 34757ec681f3Smrg 34767ec681f3SmrgHRESULT NINE_WINAPI 34777ec681f3SmrgNineDevice9_GetVertexShader( struct NineDevice9 *This, 34787ec681f3Smrg IDirect3DVertexShader9 **ppShader ) 34797ec681f3Smrg{ 34807ec681f3Smrg user_assert(ppShader, D3DERR_INVALIDCALL); 34817ec681f3Smrg nine_reference_set(ppShader, This->state.vs); 34827ec681f3Smrg return D3D_OK; 34837ec681f3Smrg} 34847ec681f3Smrg 34857ec681f3SmrgHRESULT NINE_WINAPI 34867ec681f3SmrgNineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, 34877ec681f3Smrg UINT StartRegister, 34887ec681f3Smrg const float *pConstantData, 34897ec681f3Smrg UINT Vector4fCount ) 34907ec681f3Smrg{ 34917ec681f3Smrg struct nine_state *state = This->update; 34927ec681f3Smrg float *vs_const_f = state->vs_const_f; 34937ec681f3Smrg 34947ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 34957ec681f3Smrg This, StartRegister, pConstantData, Vector4fCount); 34967ec681f3Smrg 34977ec681f3Smrg user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 34987ec681f3Smrg user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 34997ec681f3Smrg 35007ec681f3Smrg if (!Vector4fCount) 35017ec681f3Smrg return D3D_OK; 35027ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 35037ec681f3Smrg 35047ec681f3Smrg if (unlikely(This->is_recording)) { 35057ec681f3Smrg memcpy(&vs_const_f[StartRegister * 4], 35067ec681f3Smrg pConstantData, 35077ec681f3Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 35087ec681f3Smrg 35097ec681f3Smrg nine_ranges_insert(&state->changed.vs_const_f, 35107ec681f3Smrg StartRegister, StartRegister + Vector4fCount, 35117ec681f3Smrg &This->range_pool); 35127ec681f3Smrg 35137ec681f3Smrg state->changed.group |= NINE_STATE_VS_CONST; 35147ec681f3Smrg 35157ec681f3Smrg return D3D_OK; 35167ec681f3Smrg } 35177ec681f3Smrg 35187ec681f3Smrg if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData, 35197ec681f3Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0]))) 35207ec681f3Smrg return D3D_OK; 35217ec681f3Smrg 35227ec681f3Smrg memcpy(&vs_const_f[StartRegister * 4], 35237ec681f3Smrg pConstantData, 35247ec681f3Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 35257ec681f3Smrg 35267ec681f3Smrg nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData, 35277ec681f3Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0]), 35287ec681f3Smrg Vector4fCount); 35297ec681f3Smrg 35307ec681f3Smrg return D3D_OK; 35317ec681f3Smrg} 35327ec681f3Smrg 35337ec681f3SmrgHRESULT NINE_WINAPI 35347ec681f3SmrgNineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, 35357ec681f3Smrg UINT StartRegister, 35367ec681f3Smrg float *pConstantData, 35377ec681f3Smrg UINT Vector4fCount ) 35387ec681f3Smrg{ 35397ec681f3Smrg const struct nine_state *state = &This->state; 35407ec681f3Smrg 35417ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 35427ec681f3Smrg user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 35437ec681f3Smrg user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 35447ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 35457ec681f3Smrg 35467ec681f3Smrg memcpy(pConstantData, 35477ec681f3Smrg &state->vs_const_f[StartRegister * 4], 35487ec681f3Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 35497ec681f3Smrg 35507ec681f3Smrg return D3D_OK; 35517ec681f3Smrg} 35527ec681f3Smrg 35537ec681f3SmrgHRESULT NINE_WINAPI 35547ec681f3SmrgNineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, 35557ec681f3Smrg UINT StartRegister, 35567ec681f3Smrg const int *pConstantData, 35577ec681f3Smrg UINT Vector4iCount ) 35587ec681f3Smrg{ 35597ec681f3Smrg struct nine_state *state = This->update; 35607ec681f3Smrg int i; 35617ec681f3Smrg 35627ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 35637ec681f3Smrg This, StartRegister, pConstantData, Vector4iCount); 35647ec681f3Smrg 35657ec681f3Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 35667ec681f3Smrg D3DERR_INVALIDCALL); 35677ec681f3Smrg user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 35687ec681f3Smrg D3DERR_INVALIDCALL); 35697ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 35707ec681f3Smrg 35717ec681f3Smrg if (This->driver_caps.vs_integer) { 35727ec681f3Smrg if (!This->is_recording) { 35737ec681f3Smrg if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData, 35747ec681f3Smrg Vector4iCount * sizeof(int[4]))) 35757ec681f3Smrg return D3D_OK; 35767ec681f3Smrg } 35777ec681f3Smrg memcpy(&state->vs_const_i[4 * StartRegister], 35787ec681f3Smrg pConstantData, 35797ec681f3Smrg Vector4iCount * sizeof(int[4])); 35807ec681f3Smrg } else { 35817ec681f3Smrg for (i = 0; i < Vector4iCount; i++) { 35827ec681f3Smrg state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); 35837ec681f3Smrg state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); 35847ec681f3Smrg state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); 35857ec681f3Smrg state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); 35867ec681f3Smrg } 35877ec681f3Smrg } 35887ec681f3Smrg 35897ec681f3Smrg if (unlikely(This->is_recording)) { 35907ec681f3Smrg nine_ranges_insert(&state->changed.vs_const_i, 35917ec681f3Smrg StartRegister, StartRegister + Vector4iCount, 35927ec681f3Smrg &This->range_pool); 35937ec681f3Smrg state->changed.group |= NINE_STATE_VS_CONST; 35947ec681f3Smrg } else 35957ec681f3Smrg nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData, 35967ec681f3Smrg Vector4iCount * sizeof(int[4]), Vector4iCount); 35977ec681f3Smrg 35987ec681f3Smrg return D3D_OK; 35997ec681f3Smrg} 36007ec681f3Smrg 36017ec681f3SmrgHRESULT NINE_WINAPI 36027ec681f3SmrgNineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, 36037ec681f3Smrg UINT StartRegister, 36047ec681f3Smrg int *pConstantData, 36057ec681f3Smrg UINT Vector4iCount ) 36067ec681f3Smrg{ 36077ec681f3Smrg const struct nine_state *state = &This->state; 36087ec681f3Smrg int i; 36097ec681f3Smrg 36107ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 36117ec681f3Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 36127ec681f3Smrg D3DERR_INVALIDCALL); 36137ec681f3Smrg user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 36147ec681f3Smrg D3DERR_INVALIDCALL); 36157ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 36167ec681f3Smrg 36177ec681f3Smrg if (This->driver_caps.vs_integer) { 36187ec681f3Smrg memcpy(pConstantData, 36197ec681f3Smrg &state->vs_const_i[4 * StartRegister], 36207ec681f3Smrg Vector4iCount * sizeof(int[4])); 36217ec681f3Smrg } else { 36227ec681f3Smrg for (i = 0; i < Vector4iCount; i++) { 36237ec681f3Smrg pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]); 36247ec681f3Smrg pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]); 36257ec681f3Smrg pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]); 36267ec681f3Smrg pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]); 36277ec681f3Smrg } 36287ec681f3Smrg } 36297ec681f3Smrg 36307ec681f3Smrg return D3D_OK; 36317ec681f3Smrg} 36327ec681f3Smrg 36337ec681f3SmrgHRESULT NINE_WINAPI 36347ec681f3SmrgNineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, 36357ec681f3Smrg UINT StartRegister, 36367ec681f3Smrg const BOOL *pConstantData, 36377ec681f3Smrg UINT BoolCount ) 36387ec681f3Smrg{ 36397ec681f3Smrg struct nine_state *state = This->update; 36407ec681f3Smrg int i; 36417ec681f3Smrg uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); 36427ec681f3Smrg 36437ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 36447ec681f3Smrg This, StartRegister, pConstantData, BoolCount); 36457ec681f3Smrg 36467ec681f3Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 36477ec681f3Smrg D3DERR_INVALIDCALL); 36487ec681f3Smrg user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 36497ec681f3Smrg D3DERR_INVALIDCALL); 36507ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 36517ec681f3Smrg 36527ec681f3Smrg if (!This->is_recording) { 36537ec681f3Smrg bool noChange = true; 36547ec681f3Smrg for (i = 0; i < BoolCount; i++) { 36557ec681f3Smrg if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i]) 36567ec681f3Smrg noChange = false; 36577ec681f3Smrg } 36587ec681f3Smrg if (noChange) 36597ec681f3Smrg return D3D_OK; 36607ec681f3Smrg } 36617ec681f3Smrg 36627ec681f3Smrg for (i = 0; i < BoolCount; i++) 36637ec681f3Smrg state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 36647ec681f3Smrg 36657ec681f3Smrg if (unlikely(This->is_recording)) { 36667ec681f3Smrg nine_ranges_insert(&state->changed.vs_const_b, 36677ec681f3Smrg StartRegister, StartRegister + BoolCount, 36687ec681f3Smrg &This->range_pool); 36697ec681f3Smrg state->changed.group |= NINE_STATE_VS_CONST; 36707ec681f3Smrg } else 36717ec681f3Smrg nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData, 36727ec681f3Smrg sizeof(BOOL) * BoolCount, BoolCount); 36737ec681f3Smrg 36747ec681f3Smrg return D3D_OK; 36757ec681f3Smrg} 36767ec681f3Smrg 36777ec681f3SmrgHRESULT NINE_WINAPI 36787ec681f3SmrgNineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, 36797ec681f3Smrg UINT StartRegister, 36807ec681f3Smrg BOOL *pConstantData, 36817ec681f3Smrg UINT BoolCount ) 36827ec681f3Smrg{ 36837ec681f3Smrg const struct nine_state *state = &This->state; 36847ec681f3Smrg int i; 36857ec681f3Smrg 36867ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 36877ec681f3Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 36887ec681f3Smrg D3DERR_INVALIDCALL); 36897ec681f3Smrg user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 36907ec681f3Smrg D3DERR_INVALIDCALL); 36917ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 36927ec681f3Smrg 36937ec681f3Smrg for (i = 0; i < BoolCount; i++) 36947ec681f3Smrg pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE; 36957ec681f3Smrg 36967ec681f3Smrg return D3D_OK; 36977ec681f3Smrg} 36987ec681f3Smrg 36997ec681f3SmrgHRESULT NINE_WINAPI 37007ec681f3SmrgNineDevice9_SetStreamSource( struct NineDevice9 *This, 37017ec681f3Smrg UINT StreamNumber, 37027ec681f3Smrg IDirect3DVertexBuffer9 *pStreamData, 37037ec681f3Smrg UINT OffsetInBytes, 37047ec681f3Smrg UINT Stride ) 37057ec681f3Smrg{ 37067ec681f3Smrg struct nine_state *state = This->update; 37077ec681f3Smrg struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData); 37087ec681f3Smrg const unsigned i = StreamNumber; 37097ec681f3Smrg 37107ec681f3Smrg DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n", 37117ec681f3Smrg This, StreamNumber, pStreamData, OffsetInBytes, Stride); 37127ec681f3Smrg 37137ec681f3Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 37147ec681f3Smrg user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL); 37157ec681f3Smrg 37167ec681f3Smrg if (unlikely(This->is_recording)) { 37177ec681f3Smrg nine_bind(&state->stream[i], pStreamData); 37187ec681f3Smrg state->changed.vtxbuf |= 1 << StreamNumber; 37197ec681f3Smrg state->vtxbuf[i].stride = Stride; 37207ec681f3Smrg state->vtxbuf[i].buffer_offset = OffsetInBytes; 37217ec681f3Smrg return D3D_OK; 37227ec681f3Smrg } 37237ec681f3Smrg 37247ec681f3Smrg if (state->stream[i] == NineVertexBuffer9(pStreamData) && 37257ec681f3Smrg state->vtxbuf[i].stride == Stride && 37267ec681f3Smrg state->vtxbuf[i].buffer_offset == OffsetInBytes) 37277ec681f3Smrg return D3D_OK; 37287ec681f3Smrg 37297ec681f3Smrg state->vtxbuf[i].stride = Stride; 37307ec681f3Smrg state->vtxbuf[i].buffer_offset = OffsetInBytes; 37317ec681f3Smrg 37327ec681f3Smrg NineBindBufferToDevice(This, 37337ec681f3Smrg (struct NineBuffer9 **)&state->stream[i], 37347ec681f3Smrg (struct NineBuffer9 *)pVBuf9); 37357ec681f3Smrg 37367ec681f3Smrg nine_context_set_stream_source(This, 37377ec681f3Smrg StreamNumber, 37387ec681f3Smrg pVBuf9, 37397ec681f3Smrg OffsetInBytes, 37407ec681f3Smrg Stride); 37417ec681f3Smrg 37427ec681f3Smrg return D3D_OK; 37437ec681f3Smrg} 37447ec681f3Smrg 37457ec681f3Smrgstatic void 37467ec681f3SmrgNineDevice9_SetStreamSourceNULL( struct NineDevice9 *This ) 37477ec681f3Smrg{ 37487ec681f3Smrg struct nine_state *state = This->update; 37497ec681f3Smrg 37507ec681f3Smrg DBG("This=%p\n", This); 37517ec681f3Smrg 37527ec681f3Smrg state->vtxbuf[0].stride = 0; 37537ec681f3Smrg state->vtxbuf[0].buffer_offset = 0; 37547ec681f3Smrg 37557ec681f3Smrg if (!state->stream[0]) 37567ec681f3Smrg return; 37577ec681f3Smrg 37587ec681f3Smrg NineBindBufferToDevice(This, 37597ec681f3Smrg (struct NineBuffer9 **)&state->stream[0], 37607ec681f3Smrg NULL); 37617ec681f3Smrg} 37627ec681f3Smrg 37637ec681f3SmrgHRESULT NINE_WINAPI 37647ec681f3SmrgNineDevice9_GetStreamSource( struct NineDevice9 *This, 37657ec681f3Smrg UINT StreamNumber, 37667ec681f3Smrg IDirect3DVertexBuffer9 **ppStreamData, 37677ec681f3Smrg UINT *pOffsetInBytes, 37687ec681f3Smrg UINT *pStride ) 37697ec681f3Smrg{ 37707ec681f3Smrg const struct nine_state *state = &This->state; 37717ec681f3Smrg const unsigned i = StreamNumber; 37727ec681f3Smrg 37737ec681f3Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 37747ec681f3Smrg user_assert(ppStreamData && pOffsetInBytes && pStride, D3DERR_INVALIDCALL); 37757ec681f3Smrg 37767ec681f3Smrg nine_reference_set(ppStreamData, state->stream[i]); 37777ec681f3Smrg *pStride = state->vtxbuf[i].stride; 37787ec681f3Smrg *pOffsetInBytes = state->vtxbuf[i].buffer_offset; 37797ec681f3Smrg 37807ec681f3Smrg return D3D_OK; 37817ec681f3Smrg} 37827ec681f3Smrg 37837ec681f3SmrgHRESULT NINE_WINAPI 37847ec681f3SmrgNineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, 37857ec681f3Smrg UINT StreamNumber, 37867ec681f3Smrg UINT Setting ) 37877ec681f3Smrg{ 37887ec681f3Smrg struct nine_state *state = This->update; 37897ec681f3Smrg /* const UINT freq = Setting & 0x7FFFFF; */ 37907ec681f3Smrg 37917ec681f3Smrg DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This, 37927ec681f3Smrg StreamNumber, Setting); 37937ec681f3Smrg 37947ec681f3Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 37957ec681f3Smrg user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA), 37967ec681f3Smrg D3DERR_INVALIDCALL); 37977ec681f3Smrg user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) && 37987ec681f3Smrg (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL); 37997ec681f3Smrg user_assert(Setting, D3DERR_INVALIDCALL); 38007ec681f3Smrg 38017ec681f3Smrg if (unlikely(This->is_recording)) { 38027ec681f3Smrg state->stream_freq[StreamNumber] = Setting; 38037ec681f3Smrg state->changed.stream_freq |= 1 << StreamNumber; 38047ec681f3Smrg return D3D_OK; 38057ec681f3Smrg } 38067ec681f3Smrg 38077ec681f3Smrg if (state->stream_freq[StreamNumber] == Setting) 38087ec681f3Smrg return D3D_OK; 38097ec681f3Smrg 38107ec681f3Smrg state->stream_freq[StreamNumber] = Setting; 38117ec681f3Smrg 38127ec681f3Smrg nine_context_set_stream_source_freq(This, StreamNumber, Setting); 38137ec681f3Smrg return D3D_OK; 38147ec681f3Smrg} 38157ec681f3Smrg 38167ec681f3SmrgHRESULT NINE_WINAPI 38177ec681f3SmrgNineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, 38187ec681f3Smrg UINT StreamNumber, 38197ec681f3Smrg UINT *pSetting ) 38207ec681f3Smrg{ 38217ec681f3Smrg user_assert(pSetting != NULL, D3DERR_INVALIDCALL); 38227ec681f3Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 38237ec681f3Smrg *pSetting = This->state.stream_freq[StreamNumber]; 38247ec681f3Smrg return D3D_OK; 38257ec681f3Smrg} 38267ec681f3Smrg 38277ec681f3SmrgHRESULT NINE_WINAPI 38287ec681f3SmrgNineDevice9_SetIndices( struct NineDevice9 *This, 38297ec681f3Smrg IDirect3DIndexBuffer9 *pIndexData ) 38307ec681f3Smrg{ 38317ec681f3Smrg struct nine_state *state = This->update; 38327ec681f3Smrg struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData); 38337ec681f3Smrg 38347ec681f3Smrg DBG("This=%p pIndexData=%p\n", This, pIndexData); 38357ec681f3Smrg 38367ec681f3Smrg if (unlikely(This->is_recording)) { 38377ec681f3Smrg nine_bind(&state->idxbuf, idxbuf); 38387ec681f3Smrg state->changed.group |= NINE_STATE_IDXBUF; 38397ec681f3Smrg return D3D_OK; 38407ec681f3Smrg } 38417ec681f3Smrg 38427ec681f3Smrg if (state->idxbuf == idxbuf) 38437ec681f3Smrg return D3D_OK; 38447ec681f3Smrg 38457ec681f3Smrg NineBindBufferToDevice(This, 38467ec681f3Smrg (struct NineBuffer9 **)&state->idxbuf, 38477ec681f3Smrg (struct NineBuffer9 *)idxbuf); 38487ec681f3Smrg 38497ec681f3Smrg nine_context_set_indices(This, idxbuf); 38507ec681f3Smrg 38517ec681f3Smrg return D3D_OK; 38527ec681f3Smrg} 38537ec681f3Smrg 38547ec681f3Smrg/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense 38557ec681f3Smrg * here because it's an argument passed to the Draw calls. 38567ec681f3Smrg */ 38577ec681f3SmrgHRESULT NINE_WINAPI 38587ec681f3SmrgNineDevice9_GetIndices( struct NineDevice9 *This, 38597ec681f3Smrg IDirect3DIndexBuffer9 **ppIndexData) 38607ec681f3Smrg{ 38617ec681f3Smrg user_assert(ppIndexData, D3DERR_INVALIDCALL); 38627ec681f3Smrg nine_reference_set(ppIndexData, This->state.idxbuf); 38637ec681f3Smrg return D3D_OK; 38647ec681f3Smrg} 38657ec681f3Smrg 38667ec681f3SmrgHRESULT NINE_WINAPI 38677ec681f3SmrgNineDevice9_CreatePixelShader( struct NineDevice9 *This, 38687ec681f3Smrg const DWORD *pFunction, 38697ec681f3Smrg IDirect3DPixelShader9 **ppShader ) 38707ec681f3Smrg{ 38717ec681f3Smrg struct NinePixelShader9 *ps; 38727ec681f3Smrg HRESULT hr; 38737ec681f3Smrg 38747ec681f3Smrg DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 38757ec681f3Smrg 38767ec681f3Smrg user_assert(pFunction && ppShader, D3DERR_INVALIDCALL); 38777ec681f3Smrg 38787ec681f3Smrg hr = NinePixelShader9_new(This, &ps, pFunction, NULL); 38797ec681f3Smrg if (FAILED(hr)) 38807ec681f3Smrg return hr; 38817ec681f3Smrg *ppShader = (IDirect3DPixelShader9 *)ps; 38827ec681f3Smrg return D3D_OK; 38837ec681f3Smrg} 38847ec681f3Smrg 38857ec681f3SmrgHRESULT NINE_WINAPI 38867ec681f3SmrgNineDevice9_SetPixelShader( struct NineDevice9 *This, 38877ec681f3Smrg IDirect3DPixelShader9 *pShader ) 38887ec681f3Smrg{ 38897ec681f3Smrg struct nine_state *state = This->update; 38907ec681f3Smrg struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader; 38917ec681f3Smrg 38927ec681f3Smrg DBG("This=%p pShader=%p\n", This, pShader); 38937ec681f3Smrg 38947ec681f3Smrg if (unlikely(This->is_recording)) { 38957ec681f3Smrg nine_bind(&state->ps, pShader); 38967ec681f3Smrg state->changed.group |= NINE_STATE_PS; 38977ec681f3Smrg return D3D_OK; 38987ec681f3Smrg } 38997ec681f3Smrg 39007ec681f3Smrg if (state->ps == ps) 39017ec681f3Smrg return D3D_OK; 39027ec681f3Smrg 39037ec681f3Smrg nine_bind(&state->ps, ps); 39047ec681f3Smrg 39057ec681f3Smrg nine_context_set_pixel_shader(This, ps); 39067ec681f3Smrg 39077ec681f3Smrg return D3D_OK; 39087ec681f3Smrg} 39097ec681f3Smrg 39107ec681f3SmrgHRESULT NINE_WINAPI 39117ec681f3SmrgNineDevice9_GetPixelShader( struct NineDevice9 *This, 39127ec681f3Smrg IDirect3DPixelShader9 **ppShader ) 39137ec681f3Smrg{ 39147ec681f3Smrg user_assert(ppShader, D3DERR_INVALIDCALL); 39157ec681f3Smrg nine_reference_set(ppShader, This->state.ps); 39167ec681f3Smrg return D3D_OK; 39177ec681f3Smrg} 39187ec681f3Smrg 39197ec681f3SmrgHRESULT NINE_WINAPI 39207ec681f3SmrgNineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, 39217ec681f3Smrg UINT StartRegister, 39227ec681f3Smrg const float *pConstantData, 39237ec681f3Smrg UINT Vector4fCount ) 39247ec681f3Smrg{ 39257ec681f3Smrg struct nine_state *state = This->update; 39267ec681f3Smrg 39277ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 39287ec681f3Smrg This, StartRegister, pConstantData, Vector4fCount); 39297ec681f3Smrg 39307ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 39317ec681f3Smrg user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 39327ec681f3Smrg 39337ec681f3Smrg if (!Vector4fCount) 39347ec681f3Smrg return D3D_OK; 39357ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 39367ec681f3Smrg 39377ec681f3Smrg if (unlikely(This->is_recording)) { 39387ec681f3Smrg memcpy(&state->ps_const_f[StartRegister * 4], 39397ec681f3Smrg pConstantData, 39407ec681f3Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 39417ec681f3Smrg 39427ec681f3Smrg nine_ranges_insert(&state->changed.ps_const_f, 39437ec681f3Smrg StartRegister, StartRegister + Vector4fCount, 39447ec681f3Smrg &This->range_pool); 39457ec681f3Smrg 39467ec681f3Smrg state->changed.group |= NINE_STATE_PS_CONST; 39477ec681f3Smrg return D3D_OK; 39487ec681f3Smrg } 39497ec681f3Smrg 39507ec681f3Smrg if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData, 39517ec681f3Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0]))) 39527ec681f3Smrg return D3D_OK; 39537ec681f3Smrg 39547ec681f3Smrg memcpy(&state->ps_const_f[StartRegister * 4], 39557ec681f3Smrg pConstantData, 39567ec681f3Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 39577ec681f3Smrg 39587ec681f3Smrg nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData, 39597ec681f3Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0]), 39607ec681f3Smrg Vector4fCount); 39617ec681f3Smrg 39627ec681f3Smrg return D3D_OK; 39637ec681f3Smrg} 39647ec681f3Smrg 39657ec681f3SmrgHRESULT NINE_WINAPI 39667ec681f3SmrgNineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, 39677ec681f3Smrg UINT StartRegister, 39687ec681f3Smrg float *pConstantData, 39697ec681f3Smrg UINT Vector4fCount ) 39707ec681f3Smrg{ 39717ec681f3Smrg const struct nine_state *state = &This->state; 39727ec681f3Smrg 39737ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 39747ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 39757ec681f3Smrg user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 39767ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 39777ec681f3Smrg 39787ec681f3Smrg memcpy(pConstantData, 39797ec681f3Smrg &state->ps_const_f[StartRegister * 4], 39807ec681f3Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 39817ec681f3Smrg 39827ec681f3Smrg return D3D_OK; 39837ec681f3Smrg} 39847ec681f3Smrg 39857ec681f3SmrgHRESULT NINE_WINAPI 39867ec681f3SmrgNineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, 39877ec681f3Smrg UINT StartRegister, 39887ec681f3Smrg const int *pConstantData, 39897ec681f3Smrg UINT Vector4iCount ) 39907ec681f3Smrg{ 39917ec681f3Smrg struct nine_state *state = This->update; 39927ec681f3Smrg int i; 39937ec681f3Smrg 39947ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 39957ec681f3Smrg This, StartRegister, pConstantData, Vector4iCount); 39967ec681f3Smrg 39977ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 39987ec681f3Smrg user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 39997ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 40007ec681f3Smrg 40017ec681f3Smrg if (This->driver_caps.ps_integer) { 40027ec681f3Smrg if (!This->is_recording) { 40037ec681f3Smrg if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData, 40047ec681f3Smrg Vector4iCount * sizeof(state->ps_const_i[0]))) 40057ec681f3Smrg return D3D_OK; 40067ec681f3Smrg } 40077ec681f3Smrg memcpy(&state->ps_const_i[StartRegister][0], 40087ec681f3Smrg pConstantData, 40097ec681f3Smrg Vector4iCount * sizeof(state->ps_const_i[0])); 40107ec681f3Smrg } else { 40117ec681f3Smrg for (i = 0; i < Vector4iCount; i++) { 40127ec681f3Smrg state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); 40137ec681f3Smrg state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); 40147ec681f3Smrg state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); 40157ec681f3Smrg state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); 40167ec681f3Smrg } 40177ec681f3Smrg } 40187ec681f3Smrg 40197ec681f3Smrg if (unlikely(This->is_recording)) { 40207ec681f3Smrg state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; 40217ec681f3Smrg state->changed.group |= NINE_STATE_PS_CONST; 40227ec681f3Smrg } else 40237ec681f3Smrg nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData, 40247ec681f3Smrg sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount); 40257ec681f3Smrg 40267ec681f3Smrg return D3D_OK; 40277ec681f3Smrg} 40287ec681f3Smrg 40297ec681f3SmrgHRESULT NINE_WINAPI 40307ec681f3SmrgNineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, 40317ec681f3Smrg UINT StartRegister, 40327ec681f3Smrg int *pConstantData, 40337ec681f3Smrg UINT Vector4iCount ) 40347ec681f3Smrg{ 40357ec681f3Smrg const struct nine_state *state = &This->state; 40367ec681f3Smrg int i; 40377ec681f3Smrg 40387ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 40397ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 40407ec681f3Smrg user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 40417ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 40427ec681f3Smrg 40437ec681f3Smrg if (This->driver_caps.ps_integer) { 40447ec681f3Smrg memcpy(pConstantData, 40457ec681f3Smrg &state->ps_const_i[StartRegister][0], 40467ec681f3Smrg Vector4iCount * sizeof(state->ps_const_i[0])); 40477ec681f3Smrg } else { 40487ec681f3Smrg for (i = 0; i < Vector4iCount; i++) { 40497ec681f3Smrg pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]); 40507ec681f3Smrg pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]); 40517ec681f3Smrg pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]); 40527ec681f3Smrg pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]); 40537ec681f3Smrg } 40547ec681f3Smrg } 40557ec681f3Smrg 40567ec681f3Smrg return D3D_OK; 40577ec681f3Smrg} 40587ec681f3Smrg 40597ec681f3SmrgHRESULT NINE_WINAPI 40607ec681f3SmrgNineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, 40617ec681f3Smrg UINT StartRegister, 40627ec681f3Smrg const BOOL *pConstantData, 40637ec681f3Smrg UINT BoolCount ) 40647ec681f3Smrg{ 40657ec681f3Smrg struct nine_state *state = This->update; 40667ec681f3Smrg int i; 40677ec681f3Smrg uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); 40687ec681f3Smrg 40697ec681f3Smrg DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 40707ec681f3Smrg This, StartRegister, pConstantData, BoolCount); 40717ec681f3Smrg 40727ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 40737ec681f3Smrg user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 40747ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 40757ec681f3Smrg 40767ec681f3Smrg if (!This->is_recording) { 40777ec681f3Smrg bool noChange = true; 40787ec681f3Smrg for (i = 0; i < BoolCount; i++) { 40797ec681f3Smrg if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i]) 40807ec681f3Smrg noChange = false; 40817ec681f3Smrg } 40827ec681f3Smrg if (noChange) 40837ec681f3Smrg return D3D_OK; 40847ec681f3Smrg } 40857ec681f3Smrg 40867ec681f3Smrg for (i = 0; i < BoolCount; i++) 40877ec681f3Smrg state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 40887ec681f3Smrg 40897ec681f3Smrg if (unlikely(This->is_recording)) { 40907ec681f3Smrg state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister; 40917ec681f3Smrg state->changed.group |= NINE_STATE_PS_CONST; 40927ec681f3Smrg } else 40937ec681f3Smrg nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData, 40947ec681f3Smrg sizeof(BOOL) * BoolCount, BoolCount); 40957ec681f3Smrg 40967ec681f3Smrg return D3D_OK; 40977ec681f3Smrg} 40987ec681f3Smrg 40997ec681f3SmrgHRESULT NINE_WINAPI 41007ec681f3SmrgNineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, 41017ec681f3Smrg UINT StartRegister, 41027ec681f3Smrg BOOL *pConstantData, 41037ec681f3Smrg UINT BoolCount ) 41047ec681f3Smrg{ 41057ec681f3Smrg const struct nine_state *state = &This->state; 41067ec681f3Smrg int i; 41077ec681f3Smrg 41087ec681f3Smrg user_assert(!This->pure, D3DERR_INVALIDCALL); 41097ec681f3Smrg user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 41107ec681f3Smrg user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 41117ec681f3Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 41127ec681f3Smrg 41137ec681f3Smrg for (i = 0; i < BoolCount; i++) 41147ec681f3Smrg pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE; 41157ec681f3Smrg 41167ec681f3Smrg return D3D_OK; 41177ec681f3Smrg} 41187ec681f3Smrg 41197ec681f3SmrgHRESULT NINE_WINAPI 41207ec681f3SmrgNineDevice9_DrawRectPatch( struct NineDevice9 *This, 41217ec681f3Smrg UINT Handle, 41227ec681f3Smrg const float *pNumSegs, 41237ec681f3Smrg const D3DRECTPATCH_INFO *pRectPatchInfo ) 41247ec681f3Smrg{ 41257ec681f3Smrg STUB(D3DERR_INVALIDCALL); 41267ec681f3Smrg} 41277ec681f3Smrg 41287ec681f3SmrgHRESULT NINE_WINAPI 41297ec681f3SmrgNineDevice9_DrawTriPatch( struct NineDevice9 *This, 41307ec681f3Smrg UINT Handle, 41317ec681f3Smrg const float *pNumSegs, 41327ec681f3Smrg const D3DTRIPATCH_INFO *pTriPatchInfo ) 41337ec681f3Smrg{ 41347ec681f3Smrg STUB(D3DERR_INVALIDCALL); 41357ec681f3Smrg} 41367ec681f3Smrg 41377ec681f3SmrgHRESULT NINE_WINAPI 41387ec681f3SmrgNineDevice9_DeletePatch( struct NineDevice9 *This, 41397ec681f3Smrg UINT Handle ) 41407ec681f3Smrg{ 41417ec681f3Smrg STUB(D3DERR_INVALIDCALL); 41427ec681f3Smrg} 41437ec681f3Smrg 41447ec681f3SmrgHRESULT NINE_WINAPI 41457ec681f3SmrgNineDevice9_CreateQuery( struct NineDevice9 *This, 41467ec681f3Smrg D3DQUERYTYPE Type, 41477ec681f3Smrg IDirect3DQuery9 **ppQuery ) 41487ec681f3Smrg{ 41497ec681f3Smrg struct NineQuery9 *query; 41507ec681f3Smrg HRESULT hr; 41517ec681f3Smrg 41527ec681f3Smrg DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery); 41537ec681f3Smrg 41547ec681f3Smrg hr = nine_is_query_supported(This->screen, Type); 41557ec681f3Smrg if (!ppQuery || hr != D3D_OK) 41567ec681f3Smrg return hr; 41577ec681f3Smrg 41587ec681f3Smrg hr = NineQuery9_new(This, &query, Type); 41597ec681f3Smrg if (FAILED(hr)) 41607ec681f3Smrg return hr; 41617ec681f3Smrg *ppQuery = (IDirect3DQuery9 *)query; 41627ec681f3Smrg return D3D_OK; 41637ec681f3Smrg} 41647ec681f3Smrg 41657ec681f3SmrgIDirect3DDevice9Vtbl NineDevice9_vtable = { 41667ec681f3Smrg (void *)NineUnknown_QueryInterface, 41677ec681f3Smrg (void *)NineUnknown_AddRef, 41687ec681f3Smrg (void *)NineUnknown_Release, 41697ec681f3Smrg (void *)NineDevice9_TestCooperativeLevel, 41707ec681f3Smrg (void *)NineDevice9_GetAvailableTextureMem, 41717ec681f3Smrg (void *)NineDevice9_EvictManagedResources, 41727ec681f3Smrg (void *)NineDevice9_GetDirect3D, 41737ec681f3Smrg (void *)NineDevice9_GetDeviceCaps, 41747ec681f3Smrg (void *)NineDevice9_GetDisplayMode, 41757ec681f3Smrg (void *)NineDevice9_GetCreationParameters, 41767ec681f3Smrg (void *)NineDevice9_SetCursorProperties, 41777ec681f3Smrg (void *)NineDevice9_SetCursorPosition, 41787ec681f3Smrg (void *)NineDevice9_ShowCursor, 41797ec681f3Smrg (void *)NineDevice9_CreateAdditionalSwapChain, 41807ec681f3Smrg (void *)NineDevice9_GetSwapChain, 41817ec681f3Smrg (void *)NineDevice9_GetNumberOfSwapChains, 41827ec681f3Smrg (void *)NineDevice9_Reset, 41837ec681f3Smrg (void *)NineDevice9_Present, 41847ec681f3Smrg (void *)NineDevice9_GetBackBuffer, 41857ec681f3Smrg (void *)NineDevice9_GetRasterStatus, 41867ec681f3Smrg (void *)NineDevice9_SetDialogBoxMode, 41877ec681f3Smrg (void *)NineDevice9_SetGammaRamp, 41887ec681f3Smrg (void *)NineDevice9_GetGammaRamp, 41897ec681f3Smrg (void *)NineDevice9_CreateTexture, 41907ec681f3Smrg (void *)NineDevice9_CreateVolumeTexture, 41917ec681f3Smrg (void *)NineDevice9_CreateCubeTexture, 41927ec681f3Smrg (void *)NineDevice9_CreateVertexBuffer, 41937ec681f3Smrg (void *)NineDevice9_CreateIndexBuffer, 41947ec681f3Smrg (void *)NineDevice9_CreateRenderTarget, 41957ec681f3Smrg (void *)NineDevice9_CreateDepthStencilSurface, 41967ec681f3Smrg (void *)NineDevice9_UpdateSurface, 41977ec681f3Smrg (void *)NineDevice9_UpdateTexture, 41987ec681f3Smrg (void *)NineDevice9_GetRenderTargetData, 41997ec681f3Smrg (void *)NineDevice9_GetFrontBufferData, 42007ec681f3Smrg (void *)NineDevice9_StretchRect, 42017ec681f3Smrg (void *)NineDevice9_ColorFill, 42027ec681f3Smrg (void *)NineDevice9_CreateOffscreenPlainSurface, 42037ec681f3Smrg (void *)NineDevice9_SetRenderTarget, 42047ec681f3Smrg (void *)NineDevice9_GetRenderTarget, 42057ec681f3Smrg (void *)NineDevice9_SetDepthStencilSurface, 42067ec681f3Smrg (void *)NineDevice9_GetDepthStencilSurface, 42077ec681f3Smrg (void *)NineDevice9_BeginScene, 42087ec681f3Smrg (void *)NineDevice9_EndScene, 42097ec681f3Smrg (void *)NineDevice9_Clear, 42107ec681f3Smrg (void *)NineDevice9_SetTransform, 42117ec681f3Smrg (void *)NineDevice9_GetTransform, 42127ec681f3Smrg (void *)NineDevice9_MultiplyTransform, 42137ec681f3Smrg (void *)NineDevice9_SetViewport, 42147ec681f3Smrg (void *)NineDevice9_GetViewport, 42157ec681f3Smrg (void *)NineDevice9_SetMaterial, 42167ec681f3Smrg (void *)NineDevice9_GetMaterial, 42177ec681f3Smrg (void *)NineDevice9_SetLight, 42187ec681f3Smrg (void *)NineDevice9_GetLight, 42197ec681f3Smrg (void *)NineDevice9_LightEnable, 42207ec681f3Smrg (void *)NineDevice9_GetLightEnable, 42217ec681f3Smrg (void *)NineDevice9_SetClipPlane, 42227ec681f3Smrg (void *)NineDevice9_GetClipPlane, 42237ec681f3Smrg (void *)NineDevice9_SetRenderState, 42247ec681f3Smrg (void *)NineDevice9_GetRenderState, 42257ec681f3Smrg (void *)NineDevice9_CreateStateBlock, 42267ec681f3Smrg (void *)NineDevice9_BeginStateBlock, 42277ec681f3Smrg (void *)NineDevice9_EndStateBlock, 42287ec681f3Smrg (void *)NineDevice9_SetClipStatus, 42297ec681f3Smrg (void *)NineDevice9_GetClipStatus, 42307ec681f3Smrg (void *)NineDevice9_GetTexture, 42317ec681f3Smrg (void *)NineDevice9_SetTexture, 42327ec681f3Smrg (void *)NineDevice9_GetTextureStageState, 42337ec681f3Smrg (void *)NineDevice9_SetTextureStageState, 42347ec681f3Smrg (void *)NineDevice9_GetSamplerState, 42357ec681f3Smrg (void *)NineDevice9_SetSamplerState, 42367ec681f3Smrg (void *)NineDevice9_ValidateDevice, 42377ec681f3Smrg (void *)NineDevice9_SetPaletteEntries, 42387ec681f3Smrg (void *)NineDevice9_GetPaletteEntries, 42397ec681f3Smrg (void *)NineDevice9_SetCurrentTexturePalette, 42407ec681f3Smrg (void *)NineDevice9_GetCurrentTexturePalette, 42417ec681f3Smrg (void *)NineDevice9_SetScissorRect, 42427ec681f3Smrg (void *)NineDevice9_GetScissorRect, 42437ec681f3Smrg (void *)NineDevice9_SetSoftwareVertexProcessing, 42447ec681f3Smrg (void *)NineDevice9_GetSoftwareVertexProcessing, 42457ec681f3Smrg (void *)NineDevice9_SetNPatchMode, 42467ec681f3Smrg (void *)NineDevice9_GetNPatchMode, 42477ec681f3Smrg (void *)NineDevice9_DrawPrimitive, 42487ec681f3Smrg (void *)NineDevice9_DrawIndexedPrimitive, 42497ec681f3Smrg (void *)NineDevice9_DrawPrimitiveUP, 42507ec681f3Smrg (void *)NineDevice9_DrawIndexedPrimitiveUP, 42517ec681f3Smrg (void *)NineDevice9_ProcessVertices, 42527ec681f3Smrg (void *)NineDevice9_CreateVertexDeclaration, 42537ec681f3Smrg (void *)NineDevice9_SetVertexDeclaration, 42547ec681f3Smrg (void *)NineDevice9_GetVertexDeclaration, 42557ec681f3Smrg (void *)NineDevice9_SetFVF, 42567ec681f3Smrg (void *)NineDevice9_GetFVF, 42577ec681f3Smrg (void *)NineDevice9_CreateVertexShader, 42587ec681f3Smrg (void *)NineDevice9_SetVertexShader, 42597ec681f3Smrg (void *)NineDevice9_GetVertexShader, 42607ec681f3Smrg (void *)NineDevice9_SetVertexShaderConstantF, 42617ec681f3Smrg (void *)NineDevice9_GetVertexShaderConstantF, 42627ec681f3Smrg (void *)NineDevice9_SetVertexShaderConstantI, 42637ec681f3Smrg (void *)NineDevice9_GetVertexShaderConstantI, 42647ec681f3Smrg (void *)NineDevice9_SetVertexShaderConstantB, 42657ec681f3Smrg (void *)NineDevice9_GetVertexShaderConstantB, 42667ec681f3Smrg (void *)NineDevice9_SetStreamSource, 42677ec681f3Smrg (void *)NineDevice9_GetStreamSource, 42687ec681f3Smrg (void *)NineDevice9_SetStreamSourceFreq, 42697ec681f3Smrg (void *)NineDevice9_GetStreamSourceFreq, 42707ec681f3Smrg (void *)NineDevice9_SetIndices, 42717ec681f3Smrg (void *)NineDevice9_GetIndices, 42727ec681f3Smrg (void *)NineDevice9_CreatePixelShader, 42737ec681f3Smrg (void *)NineDevice9_SetPixelShader, 42747ec681f3Smrg (void *)NineDevice9_GetPixelShader, 42757ec681f3Smrg (void *)NineDevice9_SetPixelShaderConstantF, 42767ec681f3Smrg (void *)NineDevice9_GetPixelShaderConstantF, 42777ec681f3Smrg (void *)NineDevice9_SetPixelShaderConstantI, 42787ec681f3Smrg (void *)NineDevice9_GetPixelShaderConstantI, 42797ec681f3Smrg (void *)NineDevice9_SetPixelShaderConstantB, 42807ec681f3Smrg (void *)NineDevice9_GetPixelShaderConstantB, 42817ec681f3Smrg (void *)NineDevice9_DrawRectPatch, 42827ec681f3Smrg (void *)NineDevice9_DrawTriPatch, 42837ec681f3Smrg (void *)NineDevice9_DeletePatch, 42847ec681f3Smrg (void *)NineDevice9_CreateQuery 42857ec681f3Smrg}; 42867ec681f3Smrg 42877ec681f3Smrgstatic const GUID *NineDevice9_IIDs[] = { 42887ec681f3Smrg &IID_IDirect3DDevice9, 42897ec681f3Smrg &IID_IUnknown, 42907ec681f3Smrg NULL 42917ec681f3Smrg}; 42927ec681f3Smrg 42937ec681f3SmrgHRESULT 42947ec681f3SmrgNineDevice9_new( struct pipe_screen *pScreen, 42957ec681f3Smrg D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 42967ec681f3Smrg D3DCAPS9 *pCaps, 42977ec681f3Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 42987ec681f3Smrg IDirect3D9 *pD3D9, 42997ec681f3Smrg ID3DPresentGroup *pPresentationGroup, 43007ec681f3Smrg struct d3dadapter9_context *pCTX, 43017ec681f3Smrg boolean ex, 43027ec681f3Smrg D3DDISPLAYMODEEX *pFullscreenDisplayMode, 43037ec681f3Smrg struct NineDevice9 **ppOut, 43047ec681f3Smrg int minorVersionNum ) 43057ec681f3Smrg{ 43067ec681f3Smrg BOOL lock; 43077ec681f3Smrg lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); 43087ec681f3Smrg 43097ec681f3Smrg NINE_NEW(Device9, ppOut, lock, /* args */ 43107ec681f3Smrg pScreen, pCreationParameters, pCaps, 43117ec681f3Smrg pPresentationParameters, pD3D9, pPresentationGroup, pCTX, 43127ec681f3Smrg ex, pFullscreenDisplayMode, minorVersionNum ); 43137ec681f3Smrg} 4314