1b8e80941Smrg/* 2b8e80941Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 8b8e80941Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9b8e80941Smrg * the Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19b8e80941Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20b8e80941Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21b8e80941Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22b8e80941Smrg 23b8e80941Smrg#include "device9.h" 24b8e80941Smrg#include "stateblock9.h" 25b8e80941Smrg#include "surface9.h" 26b8e80941Smrg#include "swapchain9.h" 27b8e80941Smrg#include "swapchain9ex.h" 28b8e80941Smrg#include "indexbuffer9.h" 29b8e80941Smrg#include "vertexbuffer9.h" 30b8e80941Smrg#include "vertexdeclaration9.h" 31b8e80941Smrg#include "vertexshader9.h" 32b8e80941Smrg#include "pixelshader9.h" 33b8e80941Smrg#include "query9.h" 34b8e80941Smrg#include "texture9.h" 35b8e80941Smrg#include "cubetexture9.h" 36b8e80941Smrg#include "volumetexture9.h" 37b8e80941Smrg#include "nine_buffer_upload.h" 38b8e80941Smrg#include "nine_helpers.h" 39b8e80941Smrg#include "nine_pipe.h" 40b8e80941Smrg#include "nine_ff.h" 41b8e80941Smrg#include "nine_dump.h" 42b8e80941Smrg#include "nine_limits.h" 43b8e80941Smrg 44b8e80941Smrg#include "pipe/p_screen.h" 45b8e80941Smrg#include "pipe/p_context.h" 46b8e80941Smrg#include "pipe/p_config.h" 47b8e80941Smrg#include "util/u_math.h" 48b8e80941Smrg#include "util/u_inlines.h" 49b8e80941Smrg#include "util/u_hash_table.h" 50b8e80941Smrg#include "util/u_format.h" 51b8e80941Smrg#include "util/u_surface.h" 52b8e80941Smrg#include "util/u_upload_mgr.h" 53b8e80941Smrg#include "hud/hud_context.h" 54b8e80941Smrg 55b8e80941Smrg#include "cso_cache/cso_context.h" 56b8e80941Smrg 57b8e80941Smrg#define DBG_CHANNEL DBG_DEVICE 58b8e80941Smrg 59b8e80941Smrg#if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) 60b8e80941Smrg 61b8e80941Smrgstatic void nine_setup_fpu() 62b8e80941Smrg{ 63b8e80941Smrg uint16_t c; 64b8e80941Smrg 65b8e80941Smrg __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c)); 66b8e80941Smrg 67b8e80941Smrg /* clear the control word */ 68b8e80941Smrg c &= 0xF0C0; 69b8e80941Smrg /* d3d9 doc/wine tests: mask all exceptions, use single-precision 70b8e80941Smrg * and round to nearest */ 71b8e80941Smrg c |= 0x003F; 72b8e80941Smrg 73b8e80941Smrg __asm__ __volatile__ ("fldcw %0" : : "m" (*&c)); 74b8e80941Smrg} 75b8e80941Smrg 76b8e80941Smrg#else 77b8e80941Smrg 78b8e80941Smrgstatic void nine_setup_fpu(void) 79b8e80941Smrg{ 80b8e80941Smrg WARN_ONCE("FPU setup not supported on non-x86 platforms\n"); 81b8e80941Smrg} 82b8e80941Smrg 83b8e80941Smrg#endif 84b8e80941Smrg 85b8e80941Smrgvoid 86b8e80941SmrgNineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ) 87b8e80941Smrg{ 88b8e80941Smrg struct NineSurface9 *refSurf = NULL; 89b8e80941Smrg 90b8e80941Smrg DBG("This=%p is_reset=%d\n", This, (int) is_reset); 91b8e80941Smrg 92b8e80941Smrg assert(!This->is_recording); 93b8e80941Smrg 94b8e80941Smrg nine_state_set_defaults(This, &This->caps, is_reset); 95b8e80941Smrg 96b8e80941Smrg refSurf = This->swapchains[0]->buffers[0]; 97b8e80941Smrg assert(refSurf); 98b8e80941Smrg 99b8e80941Smrg This->state.viewport.X = 0; 100b8e80941Smrg This->state.viewport.Y = 0; 101b8e80941Smrg This->state.viewport.Width = refSurf->desc.Width; 102b8e80941Smrg This->state.viewport.Height = refSurf->desc.Height; 103b8e80941Smrg 104b8e80941Smrg nine_context_set_viewport(This, &This->state.viewport); 105b8e80941Smrg 106b8e80941Smrg This->state.scissor.minx = 0; 107b8e80941Smrg This->state.scissor.miny = 0; 108b8e80941Smrg This->state.scissor.maxx = refSurf->desc.Width; 109b8e80941Smrg This->state.scissor.maxy = refSurf->desc.Height; 110b8e80941Smrg 111b8e80941Smrg nine_context_set_scissor(This, &This->state.scissor); 112b8e80941Smrg 113b8e80941Smrg if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) { 114b8e80941Smrg nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE); 115b8e80941Smrg This->state.rs_advertised[D3DRS_ZENABLE] = TRUE; 116b8e80941Smrg } 117b8e80941Smrg if (This->state.rs_advertised[D3DRS_ZENABLE]) 118b8e80941Smrg NineDevice9_SetDepthStencilSurface( 119b8e80941Smrg This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf); 120b8e80941Smrg} 121b8e80941Smrg 122b8e80941Smrg#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n) 123b8e80941SmrgHRESULT 124b8e80941SmrgNineDevice9_ctor( struct NineDevice9 *This, 125b8e80941Smrg struct NineUnknownParams *pParams, 126b8e80941Smrg struct pipe_screen *pScreen, 127b8e80941Smrg D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 128b8e80941Smrg D3DCAPS9 *pCaps, 129b8e80941Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 130b8e80941Smrg IDirect3D9 *pD3D9, 131b8e80941Smrg ID3DPresentGroup *pPresentationGroup, 132b8e80941Smrg struct d3dadapter9_context *pCTX, 133b8e80941Smrg boolean ex, 134b8e80941Smrg D3DDISPLAYMODEEX *pFullscreenDisplayMode, 135b8e80941Smrg int minorVersionNum ) 136b8e80941Smrg{ 137b8e80941Smrg unsigned i; 138b8e80941Smrg HRESULT hr = NineUnknown_ctor(&This->base, pParams); 139b8e80941Smrg 140b8e80941Smrg DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p " 141b8e80941Smrg "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n", 142b8e80941Smrg This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9, 143b8e80941Smrg pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode); 144b8e80941Smrg 145b8e80941Smrg if (FAILED(hr)) { return hr; } 146b8e80941Smrg 147b8e80941Smrg list_inithead(&This->update_buffers); 148b8e80941Smrg list_inithead(&This->update_textures); 149b8e80941Smrg list_inithead(&This->managed_buffers); 150b8e80941Smrg list_inithead(&This->managed_textures); 151b8e80941Smrg 152b8e80941Smrg This->screen = pScreen; 153b8e80941Smrg This->screen_sw = pCTX->ref; 154b8e80941Smrg This->caps = *pCaps; 155b8e80941Smrg This->d3d9 = pD3D9; 156b8e80941Smrg This->params = *pCreationParameters; 157b8e80941Smrg This->ex = ex; 158b8e80941Smrg This->present = pPresentationGroup; 159b8e80941Smrg This->minor_version_num = minorVersionNum; 160b8e80941Smrg 161b8e80941Smrg IDirect3D9_AddRef(This->d3d9); 162b8e80941Smrg ID3DPresentGroup_AddRef(This->present); 163b8e80941Smrg 164b8e80941Smrg if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE)) 165b8e80941Smrg nine_setup_fpu(); 166b8e80941Smrg 167b8e80941Smrg if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) { 168b8e80941Smrg DBG("Application asked full Software Vertex Processing.\n"); 169b8e80941Smrg This->swvp = true; 170b8e80941Smrg This->may_swvp = true; 171b8e80941Smrg } else 172b8e80941Smrg This->swvp = false; 173b8e80941Smrg if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { 174b8e80941Smrg DBG("Application asked mixed Software Vertex Processing.\n"); 175b8e80941Smrg This->may_swvp = true; 176b8e80941Smrg } 177b8e80941Smrg This->context.swvp = This->swvp; 178b8e80941Smrg /* TODO: check if swvp is resetted by device Resets */ 179b8e80941Smrg 180b8e80941Smrg if (This->may_swvp && 181b8e80941Smrg (This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, 182b8e80941Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) 183b8e80941Smrg < (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) || 184b8e80941Smrg This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX, 185b8e80941Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) { 186b8e80941Smrg /* Note: We just go on, some apps never use the abilities of 187b8e80941Smrg * swvp, and just set more constants than allowed at init. 188b8e80941Smrg * Only cards we support that are affected are the r500 */ 189b8e80941Smrg WARN("Card unable to handle Software Vertex Processing. Game may fail\n"); 190b8e80941Smrg } 191b8e80941Smrg 192b8e80941Smrg /* When may_swvp, SetConstant* limits are different */ 193b8e80941Smrg if (This->may_swvp) 194b8e80941Smrg This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP; 195b8e80941Smrg 196b8e80941Smrg This->context.pipe = This->screen->context_create(This->screen, NULL, 0); 197b8e80941Smrg This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0); 198b8e80941Smrg if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */ 199b8e80941Smrg This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0); 200b8e80941Smrg if (!This->pipe_sw) { return E_OUTOFMEMORY; } 201b8e80941Smrg 202b8e80941Smrg This->context.cso = cso_create_context(This->context.pipe, 0); 203b8e80941Smrg if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */ 204b8e80941Smrg This->cso_sw = cso_create_context(This->pipe_sw, 0); 205b8e80941Smrg if (!This->cso_sw) { return E_OUTOFMEMORY; } 206b8e80941Smrg 207b8e80941Smrg /* Create first, it messes up our state. */ 208b8e80941Smrg This->hud = hud_create(This->context.cso, NULL); /* NULL result is fine */ 209b8e80941Smrg 210b8e80941Smrg /* Available memory counter. Updated only for allocations with this device 211b8e80941Smrg * instance. This is the Win 7 behavior. 212b8e80941Smrg * Win XP shares this counter across multiple devices. */ 213b8e80941Smrg This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY); 214b8e80941Smrg if (This->available_texture_mem < 4096) 215b8e80941Smrg This->available_texture_mem <<= 20; 216b8e80941Smrg else 217b8e80941Smrg This->available_texture_mem = UINT_MAX; 218b8e80941Smrg /* We cap texture memory usage to 80% of what is reported free initially 219b8e80941Smrg * This helps get closer Win behaviour. For example VertexBuffer allocation 220b8e80941Smrg * still succeeds when texture allocation fails. */ 221b8e80941Smrg This->available_texture_limit = This->available_texture_mem * 20LL / 100LL; 222b8e80941Smrg 223b8e80941Smrg /* create implicit swapchains */ 224b8e80941Smrg This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present); 225b8e80941Smrg This->swapchains = CALLOC(This->nswapchains, 226b8e80941Smrg sizeof(struct NineSwapChain9 *)); 227b8e80941Smrg if (!This->swapchains) { return E_OUTOFMEMORY; } 228b8e80941Smrg 229b8e80941Smrg for (i = 0; i < This->nswapchains; ++i) { 230b8e80941Smrg ID3DPresent *present; 231b8e80941Smrg 232b8e80941Smrg hr = ID3DPresentGroup_GetPresent(This->present, i, &present); 233b8e80941Smrg if (FAILED(hr)) 234b8e80941Smrg return hr; 235b8e80941Smrg 236b8e80941Smrg if (ex) { 237b8e80941Smrg D3DDISPLAYMODEEX *mode = NULL; 238b8e80941Smrg struct NineSwapChain9Ex **ret = 239b8e80941Smrg (struct NineSwapChain9Ex **)&This->swapchains[i]; 240b8e80941Smrg 241b8e80941Smrg if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); 242b8e80941Smrg /* when this is a Device9Ex, it should create SwapChain9Exs */ 243b8e80941Smrg hr = NineSwapChain9Ex_new(This, TRUE, present, 244b8e80941Smrg &pPresentationParameters[i], pCTX, 245b8e80941Smrg This->params.hFocusWindow, mode, ret); 246b8e80941Smrg } else { 247b8e80941Smrg hr = NineSwapChain9_new(This, TRUE, present, 248b8e80941Smrg &pPresentationParameters[i], pCTX, 249b8e80941Smrg This->params.hFocusWindow, 250b8e80941Smrg &This->swapchains[i]); 251b8e80941Smrg } 252b8e80941Smrg 253b8e80941Smrg ID3DPresent_Release(present); 254b8e80941Smrg if (FAILED(hr)) 255b8e80941Smrg return hr; 256b8e80941Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i])); 257b8e80941Smrg 258b8e80941Smrg hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0, 259b8e80941Smrg D3DBACKBUFFER_TYPE_MONO, 260b8e80941Smrg (IDirect3DSurface9 **) 261b8e80941Smrg &This->state.rt[i]); 262b8e80941Smrg if (FAILED(hr)) 263b8e80941Smrg return hr; 264b8e80941Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i])); 265b8e80941Smrg nine_bind(&This->context.rt[i], This->state.rt[i]); 266b8e80941Smrg } 267b8e80941Smrg 268b8e80941Smrg /* Initialize CSMT */ 269b8e80941Smrg /* r600, radeonsi and iris are thread safe. */ 270b8e80941Smrg if (pCTX->csmt_force == 1) 271b8e80941Smrg This->csmt_active = true; 272b8e80941Smrg else if (pCTX->csmt_force == 0) 273b8e80941Smrg This->csmt_active = false; 274b8e80941Smrg else if (strstr(pScreen->get_name(pScreen), "AMD") != NULL) 275b8e80941Smrg This->csmt_active = true; 276b8e80941Smrg else if (strstr(pScreen->get_name(pScreen), "Intel") != NULL) 277b8e80941Smrg This->csmt_active = true; 278b8e80941Smrg 279b8e80941Smrg /* We rely on u_upload_mgr using persistent coherent buffers (which don't 280b8e80941Smrg * require flush to work in multi-pipe_context scenario) for vertex and 281b8e80941Smrg * index buffers */ 282b8e80941Smrg if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT)) 283b8e80941Smrg This->csmt_active = false; 284b8e80941Smrg 285b8e80941Smrg if (This->csmt_active) { 286b8e80941Smrg This->csmt_ctx = nine_csmt_create(This); 287b8e80941Smrg if (!This->csmt_ctx) 288b8e80941Smrg return E_OUTOFMEMORY; 289b8e80941Smrg } 290b8e80941Smrg 291b8e80941Smrg if (This->csmt_active) 292b8e80941Smrg DBG("\033[1;32mCSMT is active\033[0m\n"); 293b8e80941Smrg 294b8e80941Smrg This->workarounds.dynamic_texture_workaround = pCTX->dynamic_texture_workaround; 295b8e80941Smrg 296b8e80941Smrg This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4); 297b8e80941Smrg 298b8e80941Smrg /* Initialize a dummy VBO to be used when a vertex declaration does not 299b8e80941Smrg * specify all the inputs needed by vertex shader, on win default behavior 300b8e80941Smrg * is to pass 0,0,0,0 to the shader */ 301b8e80941Smrg { 302b8e80941Smrg struct pipe_transfer *transfer; 303b8e80941Smrg struct pipe_resource tmpl; 304b8e80941Smrg struct pipe_box box; 305b8e80941Smrg unsigned char *data; 306b8e80941Smrg 307b8e80941Smrg memset(&tmpl, 0, sizeof(tmpl)); 308b8e80941Smrg tmpl.target = PIPE_BUFFER; 309b8e80941Smrg tmpl.format = PIPE_FORMAT_R8_UNORM; 310b8e80941Smrg tmpl.width0 = 16; /* 4 floats */ 311b8e80941Smrg tmpl.height0 = 1; 312b8e80941Smrg tmpl.depth0 = 1; 313b8e80941Smrg tmpl.array_size = 1; 314b8e80941Smrg tmpl.last_level = 0; 315b8e80941Smrg tmpl.nr_samples = 0; 316b8e80941Smrg tmpl.usage = PIPE_USAGE_DEFAULT; 317b8e80941Smrg tmpl.bind = PIPE_BIND_VERTEX_BUFFER; 318b8e80941Smrg tmpl.flags = 0; 319b8e80941Smrg This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl); 320b8e80941Smrg 321b8e80941Smrg if (!This->dummy_vbo) 322b8e80941Smrg return D3DERR_OUTOFVIDEOMEMORY; 323b8e80941Smrg 324b8e80941Smrg u_box_1d(0, 16, &box); 325b8e80941Smrg data = This->context.pipe->transfer_map(This->context.pipe, This->dummy_vbo, 0, 326b8e80941Smrg PIPE_TRANSFER_WRITE | 327b8e80941Smrg PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, 328b8e80941Smrg &box, &transfer); 329b8e80941Smrg assert(data); 330b8e80941Smrg assert(transfer); 331b8e80941Smrg memset(data, 0, 16); 332b8e80941Smrg This->context.pipe->transfer_unmap(This->context.pipe, transfer); 333b8e80941Smrg } 334b8e80941Smrg 335b8e80941Smrg This->cursor.software = FALSE; 336b8e80941Smrg This->cursor.hotspot.x = -1; 337b8e80941Smrg This->cursor.hotspot.y = -1; 338b8e80941Smrg This->cursor.w = This->cursor.h = 0; 339b8e80941Smrg This->cursor.visible = FALSE; 340b8e80941Smrg if (ID3DPresent_GetCursorPos(This->swapchains[0]->present, &This->cursor.pos) != S_OK) { 341b8e80941Smrg This->cursor.pos.x = 0; 342b8e80941Smrg This->cursor.pos.y = 0; 343b8e80941Smrg } 344b8e80941Smrg 345b8e80941Smrg { 346b8e80941Smrg struct pipe_resource tmpl; 347b8e80941Smrg memset(&tmpl, 0, sizeof(tmpl)); 348b8e80941Smrg tmpl.target = PIPE_TEXTURE_2D; 349b8e80941Smrg tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; 350b8e80941Smrg tmpl.width0 = 64; 351b8e80941Smrg tmpl.height0 = 64; 352b8e80941Smrg tmpl.depth0 = 1; 353b8e80941Smrg tmpl.array_size = 1; 354b8e80941Smrg tmpl.last_level = 0; 355b8e80941Smrg tmpl.nr_samples = 0; 356b8e80941Smrg tmpl.usage = PIPE_USAGE_DEFAULT; 357b8e80941Smrg tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW; 358b8e80941Smrg tmpl.flags = 0; 359b8e80941Smrg 360b8e80941Smrg This->cursor.image = pScreen->resource_create(pScreen, &tmpl); 361b8e80941Smrg if (!This->cursor.image) 362b8e80941Smrg return D3DERR_OUTOFVIDEOMEMORY; 363b8e80941Smrg 364b8e80941Smrg /* For uploading 32x32 (argb) cursor */ 365b8e80941Smrg This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32); 366b8e80941Smrg if (!This->cursor.hw_upload_temp) 367b8e80941Smrg return D3DERR_OUTOFVIDEOMEMORY; 368b8e80941Smrg } 369b8e80941Smrg 370b8e80941Smrg /* Create constant buffers. */ 371b8e80941Smrg { 372b8e80941Smrg unsigned max_const_vs, max_const_ps; 373b8e80941Smrg 374b8e80941Smrg /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots, 375b8e80941Smrg * we have to take in some more slots for int and bool*/ 376b8e80941Smrg max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, 377b8e80941Smrg PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / 378b8e80941Smrg sizeof(float[4]), 379b8e80941Smrg NINE_MAX_CONST_ALL); 380b8e80941Smrg /* ps 3.0: 224 float constants. All cards supported support at least 381b8e80941Smrg * 256 constants for ps */ 382b8e80941Smrg max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 383b8e80941Smrg 384b8e80941Smrg This->max_vs_const_f = max_const_vs - 385b8e80941Smrg (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 386b8e80941Smrg This->max_ps_const_f = max_const_ps - 387b8e80941Smrg (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 388b8e80941Smrg 389b8e80941Smrg This->vs_const_size = max_const_vs * sizeof(float[4]); 390b8e80941Smrg This->ps_const_size = max_const_ps * sizeof(float[4]); 391b8e80941Smrg /* Include space for I,B constants for user constbuf. */ 392b8e80941Smrg if (This->may_swvp) { 393b8e80941Smrg This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 394b8e80941Smrg This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 395b8e80941Smrg if (!This->context.vs_const_f_swvp) 396b8e80941Smrg return E_OUTOFMEMORY; 397b8e80941Smrg This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 398b8e80941Smrg This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1); 399b8e80941Smrg This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); 400b8e80941Smrg This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1); 401b8e80941Smrg This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); 402b8e80941Smrg This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1); 403b8e80941Smrg } else { 404b8e80941Smrg This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1); 405b8e80941Smrg This->context.vs_const_f_swvp = NULL; 406b8e80941Smrg This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1); 407b8e80941Smrg This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1); 408b8e80941Smrg This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); 409b8e80941Smrg This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1); 410b8e80941Smrg This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); 411b8e80941Smrg This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1); 412b8e80941Smrg } 413b8e80941Smrg This->context.vs_const_f = CALLOC(This->vs_const_size, 1); 414b8e80941Smrg This->state.ps_const_f = CALLOC(This->ps_const_size, 1); 415b8e80941Smrg This->context.ps_const_f = CALLOC(This->ps_const_size, 1); 416b8e80941Smrg This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1); 417b8e80941Smrg if (!This->state.vs_const_f || !This->context.vs_const_f || 418b8e80941Smrg !This->state.ps_const_f || !This->context.ps_const_f || 419b8e80941Smrg !This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp || 420b8e80941Smrg !This->context.ps_lconstf_temp || 421b8e80941Smrg !This->state.vs_const_i || !This->context.vs_const_i || 422b8e80941Smrg !This->state.vs_const_b || !This->context.vs_const_b) 423b8e80941Smrg return E_OUTOFMEMORY; 424b8e80941Smrg 425b8e80941Smrg if (strstr(pScreen->get_name(pScreen), "AMD") || 426b8e80941Smrg strstr(pScreen->get_name(pScreen), "ATI")) { 427b8e80941Smrg This->driver_bugs.buggy_barycentrics = TRUE; 428b8e80941Smrg } 429b8e80941Smrg } 430b8e80941Smrg 431b8e80941Smrg /* allocate dummy texture/sampler for when there are missing ones bound */ 432b8e80941Smrg { 433b8e80941Smrg struct pipe_resource tmplt; 434b8e80941Smrg struct pipe_sampler_view templ; 435b8e80941Smrg struct pipe_sampler_state samp; 436b8e80941Smrg memset(&tmplt, 0, sizeof(tmplt)); 437b8e80941Smrg memset(&samp, 0, sizeof(samp)); 438b8e80941Smrg 439b8e80941Smrg tmplt.target = PIPE_TEXTURE_2D; 440b8e80941Smrg tmplt.width0 = 1; 441b8e80941Smrg tmplt.height0 = 1; 442b8e80941Smrg tmplt.depth0 = 1; 443b8e80941Smrg tmplt.last_level = 0; 444b8e80941Smrg tmplt.array_size = 1; 445b8e80941Smrg tmplt.usage = PIPE_USAGE_DEFAULT; 446b8e80941Smrg tmplt.flags = 0; 447b8e80941Smrg tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM; 448b8e80941Smrg tmplt.bind = PIPE_BIND_SAMPLER_VIEW; 449b8e80941Smrg tmplt.nr_samples = 0; 450b8e80941Smrg 451b8e80941Smrg This->dummy_texture = This->screen->resource_create(This->screen, &tmplt); 452b8e80941Smrg if (!This->dummy_texture) 453b8e80941Smrg return D3DERR_DRIVERINTERNALERROR; 454b8e80941Smrg 455b8e80941Smrg templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; 456b8e80941Smrg templ.u.tex.first_layer = 0; 457b8e80941Smrg templ.u.tex.last_layer = 0; 458b8e80941Smrg templ.u.tex.first_level = 0; 459b8e80941Smrg templ.u.tex.last_level = 0; 460b8e80941Smrg templ.swizzle_r = PIPE_SWIZZLE_0; 461b8e80941Smrg templ.swizzle_g = PIPE_SWIZZLE_0; 462b8e80941Smrg templ.swizzle_b = PIPE_SWIZZLE_0; 463b8e80941Smrg templ.swizzle_a = PIPE_SWIZZLE_1; 464b8e80941Smrg templ.target = This->dummy_texture->target; 465b8e80941Smrg 466b8e80941Smrg This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ); 467b8e80941Smrg if (!This->dummy_sampler_view) 468b8e80941Smrg return D3DERR_DRIVERINTERNALERROR; 469b8e80941Smrg 470b8e80941Smrg samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 471b8e80941Smrg samp.max_lod = 15.0f; 472b8e80941Smrg samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 473b8e80941Smrg samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 474b8e80941Smrg samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 475b8e80941Smrg samp.min_img_filter = PIPE_TEX_FILTER_NEAREST; 476b8e80941Smrg samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 477b8e80941Smrg samp.compare_mode = PIPE_TEX_COMPARE_NONE; 478b8e80941Smrg samp.compare_func = PIPE_FUNC_LEQUAL; 479b8e80941Smrg samp.normalized_coords = 1; 480b8e80941Smrg samp.seamless_cube_map = 0; 481b8e80941Smrg This->dummy_sampler_state = samp; 482b8e80941Smrg } 483b8e80941Smrg 484b8e80941Smrg /* Allocate upload helper for drivers that suck (from st pov ;). */ 485b8e80941Smrg 486b8e80941Smrg This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS) && !This->csmt_active; 487b8e80941Smrg This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS); 488b8e80941Smrg This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader; 489b8e80941Smrg This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION); 490b8e80941Smrg This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); 491b8e80941Smrg This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); 492b8e80941Smrg This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED); 493b8e80941Smrg 494b8e80941Smrg This->context.inline_constants = pCTX->shader_inline_constants; 495b8e80941Smrg /* Code would be needed when integers are not available to correctly 496b8e80941Smrg * handle the conversion of integer constants */ 497b8e80941Smrg This->context.inline_constants &= This->driver_caps.vs_integer && This->driver_caps.ps_integer; 498b8e80941Smrg 499b8e80941Smrg nine_ff_init(This); /* initialize fixed function code */ 500b8e80941Smrg 501b8e80941Smrg NineDevice9_SetDefaultState(This, FALSE); 502b8e80941Smrg 503b8e80941Smrg { 504b8e80941Smrg struct pipe_poly_stipple stipple; 505b8e80941Smrg memset(&stipple, ~0, sizeof(stipple)); 506b8e80941Smrg This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple); 507b8e80941Smrg } 508b8e80941Smrg 509b8e80941Smrg This->update = &This->state; 510b8e80941Smrg 511b8e80941Smrg nine_state_init_sw(This); 512b8e80941Smrg 513b8e80941Smrg ID3DPresentGroup_Release(This->present); 514b8e80941Smrg nine_csmt_process(This); 515b8e80941Smrg 516b8e80941Smrg return D3D_OK; 517b8e80941Smrg} 518b8e80941Smrg#undef GET_PCAP 519b8e80941Smrg 520b8e80941Smrgvoid 521b8e80941SmrgNineDevice9_dtor( struct NineDevice9 *This ) 522b8e80941Smrg{ 523b8e80941Smrg unsigned i; 524b8e80941Smrg 525b8e80941Smrg DBG("This=%p\n", This); 526b8e80941Smrg 527b8e80941Smrg /* Flush all pending commands to get refcount right, 528b8e80941Smrg * and properly release bound objects. It is ok to still 529b8e80941Smrg * execute commands while we are in device dtor, because 530b8e80941Smrg * we haven't released anything yet. Note that no pending 531b8e80941Smrg * command can increase the device refcount. */ 532b8e80941Smrg if (This->csmt_active && This->csmt_ctx) { 533b8e80941Smrg nine_csmt_process(This); 534b8e80941Smrg nine_csmt_destroy(This, This->csmt_ctx); 535b8e80941Smrg This->csmt_active = FALSE; 536b8e80941Smrg This->csmt_ctx = NULL; 537b8e80941Smrg } 538b8e80941Smrg 539b8e80941Smrg nine_ff_fini(This); 540b8e80941Smrg nine_state_destroy_sw(This); 541b8e80941Smrg nine_device_state_clear(This); 542b8e80941Smrg nine_context_clear(This); 543b8e80941Smrg 544b8e80941Smrg nine_bind(&This->record, NULL); 545b8e80941Smrg 546b8e80941Smrg pipe_sampler_view_reference(&This->dummy_sampler_view, NULL); 547b8e80941Smrg pipe_resource_reference(&This->dummy_texture, NULL); 548b8e80941Smrg pipe_resource_reference(&This->dummy_vbo, NULL); 549b8e80941Smrg FREE(This->state.vs_const_f); 550b8e80941Smrg FREE(This->context.vs_const_f); 551b8e80941Smrg FREE(This->state.ps_const_f); 552b8e80941Smrg FREE(This->context.ps_const_f); 553b8e80941Smrg FREE(This->state.vs_lconstf_temp); 554b8e80941Smrg FREE(This->context.vs_lconstf_temp); 555b8e80941Smrg FREE(This->context.ps_lconstf_temp); 556b8e80941Smrg FREE(This->state.vs_const_i); 557b8e80941Smrg FREE(This->context.vs_const_i); 558b8e80941Smrg FREE(This->state.vs_const_b); 559b8e80941Smrg FREE(This->context.vs_const_b); 560b8e80941Smrg FREE(This->context.vs_const_f_swvp); 561b8e80941Smrg 562b8e80941Smrg pipe_resource_reference(&This->cursor.image, NULL); 563b8e80941Smrg FREE(This->cursor.hw_upload_temp); 564b8e80941Smrg 565b8e80941Smrg if (This->swapchains) { 566b8e80941Smrg for (i = 0; i < This->nswapchains; ++i) 567b8e80941Smrg if (This->swapchains[i]) 568b8e80941Smrg NineUnknown_Unbind(NineUnknown(This->swapchains[i])); 569b8e80941Smrg FREE(This->swapchains); 570b8e80941Smrg } 571b8e80941Smrg 572b8e80941Smrg if (This->buffer_upload) 573b8e80941Smrg nine_upload_destroy(This->buffer_upload); 574b8e80941Smrg 575b8e80941Smrg /* Destroy cso first */ 576b8e80941Smrg if (This->context.cso) { cso_destroy_context(This->context.cso); } 577b8e80941Smrg if (This->cso_sw) { cso_destroy_context(This->cso_sw); } 578b8e80941Smrg if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); } 579b8e80941Smrg if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); } 580b8e80941Smrg if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); } 581b8e80941Smrg 582b8e80941Smrg if (This->present) { ID3DPresentGroup_Release(This->present); } 583b8e80941Smrg if (This->d3d9) { IDirect3D9_Release(This->d3d9); } 584b8e80941Smrg 585b8e80941Smrg NineUnknown_dtor(&This->base); 586b8e80941Smrg} 587b8e80941Smrg 588b8e80941Smrgstruct pipe_screen * 589b8e80941SmrgNineDevice9_GetScreen( struct NineDevice9 *This ) 590b8e80941Smrg{ 591b8e80941Smrg return This->screen; 592b8e80941Smrg} 593b8e80941Smrg 594b8e80941Smrgstruct pipe_context * 595b8e80941SmrgNineDevice9_GetPipe( struct NineDevice9 *This ) 596b8e80941Smrg{ 597b8e80941Smrg return nine_context_get_pipe(This); 598b8e80941Smrg} 599b8e80941Smrg 600b8e80941Smrgconst D3DCAPS9 * 601b8e80941SmrgNineDevice9_GetCaps( struct NineDevice9 *This ) 602b8e80941Smrg{ 603b8e80941Smrg return &This->caps; 604b8e80941Smrg} 605b8e80941Smrg 606b8e80941Smrgstatic inline void 607b8e80941SmrgNineDevice9_PauseRecording( struct NineDevice9 *This ) 608b8e80941Smrg{ 609b8e80941Smrg if (This->record) { 610b8e80941Smrg This->update = &This->state; 611b8e80941Smrg This->is_recording = FALSE; 612b8e80941Smrg } 613b8e80941Smrg} 614b8e80941Smrg 615b8e80941Smrgstatic inline void 616b8e80941SmrgNineDevice9_ResumeRecording( struct NineDevice9 *This ) 617b8e80941Smrg{ 618b8e80941Smrg if (This->record) { 619b8e80941Smrg This->update = &This->record->state; 620b8e80941Smrg This->is_recording = TRUE; 621b8e80941Smrg } 622b8e80941Smrg} 623b8e80941Smrg 624b8e80941SmrgHRESULT NINE_WINAPI 625b8e80941SmrgNineDevice9_TestCooperativeLevel( struct NineDevice9 *This ) 626b8e80941Smrg{ 627b8e80941Smrg if (NineSwapChain9_GetOccluded(This->swapchains[0])) { 628b8e80941Smrg This->device_needs_reset = TRUE; 629b8e80941Smrg return D3DERR_DEVICELOST; 630b8e80941Smrg } else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) { 631b8e80941Smrg This->device_needs_reset = TRUE; 632b8e80941Smrg return D3DERR_DEVICENOTRESET; 633b8e80941Smrg } else if (This->device_needs_reset) { 634b8e80941Smrg return D3DERR_DEVICENOTRESET; 635b8e80941Smrg } 636b8e80941Smrg 637b8e80941Smrg return D3D_OK; 638b8e80941Smrg} 639b8e80941Smrg 640b8e80941SmrgUINT NINE_WINAPI 641b8e80941SmrgNineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) 642b8e80941Smrg{ 643b8e80941Smrg return This->available_texture_mem; 644b8e80941Smrg} 645b8e80941Smrg 646b8e80941SmrgHRESULT NINE_WINAPI 647b8e80941SmrgNineDevice9_EvictManagedResources( struct NineDevice9 *This ) 648b8e80941Smrg{ 649b8e80941Smrg struct NineBaseTexture9 *tex; 650b8e80941Smrg struct NineBuffer9 *buf; 651b8e80941Smrg 652b8e80941Smrg DBG("This=%p\n", This); 653b8e80941Smrg LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) { 654b8e80941Smrg NineBaseTexture9_UnLoad(tex); 655b8e80941Smrg } 656b8e80941Smrg /* Vertex/index buffers don't take a lot of space and aren't accounted 657b8e80941Smrg * for d3d memory usage. Instead of actually freeing from memory, 658b8e80941Smrg * just mark the buffer dirty to trigger a re-upload later. We 659b8e80941Smrg * could just ignore, but some bad behaving apps could rely on it (if 660b8e80941Smrg * they write outside the locked regions typically). */ 661b8e80941Smrg LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) { 662b8e80941Smrg NineBuffer9_SetDirty(buf); 663b8e80941Smrg } 664b8e80941Smrg 665b8e80941Smrg return D3D_OK; 666b8e80941Smrg} 667b8e80941Smrg 668b8e80941SmrgHRESULT NINE_WINAPI 669b8e80941SmrgNineDevice9_GetDirect3D( struct NineDevice9 *This, 670b8e80941Smrg IDirect3D9 **ppD3D9 ) 671b8e80941Smrg{ 672b8e80941Smrg user_assert(ppD3D9 != NULL, E_POINTER); 673b8e80941Smrg IDirect3D9_AddRef(This->d3d9); 674b8e80941Smrg *ppD3D9 = This->d3d9; 675b8e80941Smrg return D3D_OK; 676b8e80941Smrg} 677b8e80941Smrg 678b8e80941SmrgHRESULT NINE_WINAPI 679b8e80941SmrgNineDevice9_GetDeviceCaps( struct NineDevice9 *This, 680b8e80941Smrg D3DCAPS9 *pCaps ) 681b8e80941Smrg{ 682b8e80941Smrg user_assert(pCaps != NULL, D3DERR_INVALIDCALL); 683b8e80941Smrg *pCaps = This->caps; 684b8e80941Smrg return D3D_OK; 685b8e80941Smrg} 686b8e80941Smrg 687b8e80941SmrgHRESULT NINE_WINAPI 688b8e80941SmrgNineDevice9_GetDisplayMode( struct NineDevice9 *This, 689b8e80941Smrg UINT iSwapChain, 690b8e80941Smrg D3DDISPLAYMODE *pMode ) 691b8e80941Smrg{ 692b8e80941Smrg DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode); 693b8e80941Smrg 694b8e80941Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 695b8e80941Smrg 696b8e80941Smrg return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode); 697b8e80941Smrg} 698b8e80941Smrg 699b8e80941SmrgHRESULT NINE_WINAPI 700b8e80941SmrgNineDevice9_GetCreationParameters( struct NineDevice9 *This, 701b8e80941Smrg D3DDEVICE_CREATION_PARAMETERS *pParameters ) 702b8e80941Smrg{ 703b8e80941Smrg user_assert(pParameters != NULL, D3DERR_INVALIDCALL); 704b8e80941Smrg *pParameters = This->params; 705b8e80941Smrg return D3D_OK; 706b8e80941Smrg} 707b8e80941Smrg 708b8e80941SmrgHRESULT NINE_WINAPI 709b8e80941SmrgNineDevice9_SetCursorProperties( struct NineDevice9 *This, 710b8e80941Smrg UINT XHotSpot, 711b8e80941Smrg UINT YHotSpot, 712b8e80941Smrg IDirect3DSurface9 *pCursorBitmap ) 713b8e80941Smrg{ 714b8e80941Smrg struct NineSurface9 *surf = NineSurface9(pCursorBitmap); 715b8e80941Smrg struct pipe_context *pipe = NineDevice9_GetPipe(This); 716b8e80941Smrg struct pipe_box box; 717b8e80941Smrg struct pipe_transfer *transfer; 718b8e80941Smrg BOOL hw_cursor; 719b8e80941Smrg void *ptr; 720b8e80941Smrg 721b8e80941Smrg DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u " 722b8e80941Smrg "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap); 723b8e80941Smrg 724b8e80941Smrg user_assert(pCursorBitmap, D3DERR_INVALIDCALL); 725b8e80941Smrg user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL); 726b8e80941Smrg 727b8e80941Smrg if (This->swapchains[0]->params.Windowed) { 728b8e80941Smrg This->cursor.w = MIN2(surf->desc.Width, 32); 729b8e80941Smrg This->cursor.h = MIN2(surf->desc.Height, 32); 730b8e80941Smrg hw_cursor = 1; /* always use hw cursor for windowed mode */ 731b8e80941Smrg } else { 732b8e80941Smrg This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0); 733b8e80941Smrg This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0); 734b8e80941Smrg hw_cursor = This->cursor.w == 32 && This->cursor.h == 32; 735b8e80941Smrg } 736b8e80941Smrg 737b8e80941Smrg u_box_origin_2d(This->cursor.w, This->cursor.h, &box); 738b8e80941Smrg 739b8e80941Smrg ptr = pipe->transfer_map(pipe, This->cursor.image, 0, 740b8e80941Smrg PIPE_TRANSFER_WRITE | 741b8e80941Smrg PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, 742b8e80941Smrg &box, &transfer); 743b8e80941Smrg if (!ptr) 744b8e80941Smrg ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR); 745b8e80941Smrg 746b8e80941Smrg This->cursor.hotspot.x = XHotSpot; 747b8e80941Smrg This->cursor.hotspot.y = YHotSpot; 748b8e80941Smrg 749b8e80941Smrg /* Copy cursor image to internal storage. */ 750b8e80941Smrg { 751b8e80941Smrg D3DLOCKED_RECT lock; 752b8e80941Smrg HRESULT hr; 753b8e80941Smrg const struct util_format_description *sfmt = 754b8e80941Smrg util_format_description(surf->base.info.format); 755b8e80941Smrg assert(sfmt); 756b8e80941Smrg 757b8e80941Smrg hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY); 758b8e80941Smrg if (FAILED(hr)) 759b8e80941Smrg ret_err("Failed to map cursor source image.\n", 760b8e80941Smrg D3DERR_DRIVERINTERNALERROR); 761b8e80941Smrg 762b8e80941Smrg sfmt->unpack_rgba_8unorm(ptr, transfer->stride, 763b8e80941Smrg lock.pBits, lock.Pitch, 764b8e80941Smrg This->cursor.w, This->cursor.h); 765b8e80941Smrg 766b8e80941Smrg if (hw_cursor) { 767b8e80941Smrg void *data = lock.pBits; 768b8e80941Smrg /* SetCursor assumes 32x32 argb with pitch 128 */ 769b8e80941Smrg if (lock.Pitch != 128) { 770b8e80941Smrg sfmt->unpack_rgba_8unorm(This->cursor.hw_upload_temp, 128, 771b8e80941Smrg lock.pBits, lock.Pitch, 772b8e80941Smrg 32, 32); 773b8e80941Smrg data = This->cursor.hw_upload_temp; 774b8e80941Smrg } 775b8e80941Smrg hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present, 776b8e80941Smrg data, 777b8e80941Smrg &This->cursor.hotspot, 778b8e80941Smrg This->cursor.visible) == D3D_OK; 779b8e80941Smrg } 780b8e80941Smrg 781b8e80941Smrg NineSurface9_UnlockRect(surf); 782b8e80941Smrg } 783b8e80941Smrg pipe->transfer_unmap(pipe, transfer); 784b8e80941Smrg 785b8e80941Smrg /* hide cursor if we emulate it */ 786b8e80941Smrg if (!hw_cursor) 787b8e80941Smrg ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE); 788b8e80941Smrg This->cursor.software = !hw_cursor; 789b8e80941Smrg 790b8e80941Smrg return D3D_OK; 791b8e80941Smrg} 792b8e80941Smrg 793b8e80941Smrgvoid NINE_WINAPI 794b8e80941SmrgNineDevice9_SetCursorPosition( struct NineDevice9 *This, 795b8e80941Smrg int X, 796b8e80941Smrg int Y, 797b8e80941Smrg DWORD Flags ) 798b8e80941Smrg{ 799b8e80941Smrg struct NineSwapChain9 *swap = This->swapchains[0]; 800b8e80941Smrg 801b8e80941Smrg DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags); 802b8e80941Smrg 803b8e80941Smrg /* present >= v1.4 handles this itself */ 804b8e80941Smrg if (This->minor_version_num < 4) { 805b8e80941Smrg if (This->cursor.pos.x == X && This->cursor.pos.y == Y) 806b8e80941Smrg return; 807b8e80941Smrg } 808b8e80941Smrg 809b8e80941Smrg This->cursor.pos.x = X; 810b8e80941Smrg This->cursor.pos.y = Y; 811b8e80941Smrg 812b8e80941Smrg if (!This->cursor.software) 813b8e80941Smrg This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK; 814b8e80941Smrg} 815b8e80941Smrg 816b8e80941SmrgBOOL NINE_WINAPI 817b8e80941SmrgNineDevice9_ShowCursor( struct NineDevice9 *This, 818b8e80941Smrg BOOL bShow ) 819b8e80941Smrg{ 820b8e80941Smrg BOOL old = This->cursor.visible; 821b8e80941Smrg 822b8e80941Smrg DBG("This=%p bShow=%d\n", This, (int) bShow); 823b8e80941Smrg 824b8e80941Smrg /* No-op until a cursor is set in d3d */ 825b8e80941Smrg if (This->cursor.hotspot.x == -1) 826b8e80941Smrg return old; 827b8e80941Smrg 828b8e80941Smrg This->cursor.visible = bShow; 829b8e80941Smrg /* Note: Don't optimize by avoiding the call if This->cursor.visible 830b8e80941Smrg * hasn't changed. One has to keep in mind the app may do SetCursor 831b8e80941Smrg * calls outside d3d, thus such an optimization affects behaviour. */ 832b8e80941Smrg if (!This->cursor.software) 833b8e80941Smrg This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK; 834b8e80941Smrg 835b8e80941Smrg return old; 836b8e80941Smrg} 837b8e80941Smrg 838b8e80941SmrgHRESULT NINE_WINAPI 839b8e80941SmrgNineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, 840b8e80941Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 841b8e80941Smrg IDirect3DSwapChain9 **pSwapChain ) 842b8e80941Smrg{ 843b8e80941Smrg struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0]; 844b8e80941Smrg ID3DPresent *present; 845b8e80941Smrg HRESULT hr; 846b8e80941Smrg 847b8e80941Smrg DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n", 848b8e80941Smrg This, pPresentationParameters, pSwapChain); 849b8e80941Smrg 850b8e80941Smrg user_assert(pPresentationParameters, D3DERR_INVALIDCALL); 851b8e80941Smrg user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL); 852b8e80941Smrg 853b8e80941Smrg /* TODO: this deserves more tests */ 854b8e80941Smrg if (!pPresentationParameters->hDeviceWindow) 855b8e80941Smrg pPresentationParameters->hDeviceWindow = This->params.hFocusWindow; 856b8e80941Smrg 857b8e80941Smrg hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present); 858b8e80941Smrg 859b8e80941Smrg if (FAILED(hr)) 860b8e80941Smrg return hr; 861b8e80941Smrg 862b8e80941Smrg hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters, 863b8e80941Smrg tmplt->actx, 864b8e80941Smrg tmplt->params.hDeviceWindow, 865b8e80941Smrg &swapchain); 866b8e80941Smrg if (FAILED(hr)) 867b8e80941Smrg return hr; 868b8e80941Smrg 869b8e80941Smrg *pSwapChain = (IDirect3DSwapChain9 *)swapchain; 870b8e80941Smrg return D3D_OK; 871b8e80941Smrg} 872b8e80941Smrg 873b8e80941SmrgHRESULT NINE_WINAPI 874b8e80941SmrgNineDevice9_GetSwapChain( struct NineDevice9 *This, 875b8e80941Smrg UINT iSwapChain, 876b8e80941Smrg IDirect3DSwapChain9 **pSwapChain ) 877b8e80941Smrg{ 878b8e80941Smrg user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); 879b8e80941Smrg 880b8e80941Smrg *pSwapChain = NULL; 881b8e80941Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 882b8e80941Smrg 883b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain])); 884b8e80941Smrg *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain]; 885b8e80941Smrg 886b8e80941Smrg return D3D_OK; 887b8e80941Smrg} 888b8e80941Smrg 889b8e80941SmrgUINT NINE_WINAPI 890b8e80941SmrgNineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) 891b8e80941Smrg{ 892b8e80941Smrg return This->nswapchains; 893b8e80941Smrg} 894b8e80941Smrg 895b8e80941SmrgHRESULT NINE_WINAPI 896b8e80941SmrgNineDevice9_Reset( struct NineDevice9 *This, 897b8e80941Smrg D3DPRESENT_PARAMETERS *pPresentationParameters ) 898b8e80941Smrg{ 899b8e80941Smrg HRESULT hr = D3D_OK; 900b8e80941Smrg unsigned i; 901b8e80941Smrg 902b8e80941Smrg DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); 903b8e80941Smrg 904b8e80941Smrg if (NineSwapChain9_GetOccluded(This->swapchains[0])) { 905b8e80941Smrg This->device_needs_reset = TRUE; 906b8e80941Smrg return D3DERR_DEVICELOST; 907b8e80941Smrg } 908b8e80941Smrg 909b8e80941Smrg for (i = 0; i < This->nswapchains; ++i) { 910b8e80941Smrg D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; 911b8e80941Smrg hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL); 912b8e80941Smrg if (hr != D3D_OK) 913b8e80941Smrg break; 914b8e80941Smrg } 915b8e80941Smrg 916b8e80941Smrg nine_csmt_process(This); 917b8e80941Smrg nine_device_state_clear(This); 918b8e80941Smrg nine_context_clear(This); 919b8e80941Smrg 920b8e80941Smrg NineDevice9_SetDefaultState(This, TRUE); 921b8e80941Smrg NineDevice9_SetRenderTarget( 922b8e80941Smrg This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]); 923b8e80941Smrg /* XXX: better use GetBackBuffer here ? */ 924b8e80941Smrg 925b8e80941Smrg This->device_needs_reset = (hr != D3D_OK); 926b8e80941Smrg return hr; 927b8e80941Smrg} 928b8e80941Smrg 929b8e80941SmrgHRESULT NINE_WINAPI 930b8e80941SmrgNineDevice9_Present( struct NineDevice9 *This, 931b8e80941Smrg const RECT *pSourceRect, 932b8e80941Smrg const RECT *pDestRect, 933b8e80941Smrg HWND hDestWindowOverride, 934b8e80941Smrg const RGNDATA *pDirtyRegion ) 935b8e80941Smrg{ 936b8e80941Smrg unsigned i; 937b8e80941Smrg HRESULT hr; 938b8e80941Smrg 939b8e80941Smrg DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n", 940b8e80941Smrg This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); 941b8e80941Smrg 942b8e80941Smrg /* XXX is this right? */ 943b8e80941Smrg for (i = 0; i < This->nswapchains; ++i) { 944b8e80941Smrg hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect, 945b8e80941Smrg hDestWindowOverride, pDirtyRegion, 0); 946b8e80941Smrg if (FAILED(hr)) { return hr; } 947b8e80941Smrg } 948b8e80941Smrg 949b8e80941Smrg return D3D_OK; 950b8e80941Smrg} 951b8e80941Smrg 952b8e80941SmrgHRESULT NINE_WINAPI 953b8e80941SmrgNineDevice9_GetBackBuffer( struct NineDevice9 *This, 954b8e80941Smrg UINT iSwapChain, 955b8e80941Smrg UINT iBackBuffer, 956b8e80941Smrg D3DBACKBUFFER_TYPE Type, 957b8e80941Smrg IDirect3DSurface9 **ppBackBuffer ) 958b8e80941Smrg{ 959b8e80941Smrg user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); 960b8e80941Smrg /* return NULL on error */ 961b8e80941Smrg *ppBackBuffer = NULL; 962b8e80941Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 963b8e80941Smrg 964b8e80941Smrg return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain], 965b8e80941Smrg iBackBuffer, Type, ppBackBuffer); 966b8e80941Smrg} 967b8e80941Smrg 968b8e80941SmrgHRESULT NINE_WINAPI 969b8e80941SmrgNineDevice9_GetRasterStatus( struct NineDevice9 *This, 970b8e80941Smrg UINT iSwapChain, 971b8e80941Smrg D3DRASTER_STATUS *pRasterStatus ) 972b8e80941Smrg{ 973b8e80941Smrg user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL); 974b8e80941Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 975b8e80941Smrg 976b8e80941Smrg return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain], 977b8e80941Smrg pRasterStatus); 978b8e80941Smrg} 979b8e80941Smrg 980b8e80941SmrgHRESULT NINE_WINAPI 981b8e80941SmrgNineDevice9_SetDialogBoxMode( struct NineDevice9 *This, 982b8e80941Smrg BOOL bEnableDialogs ) 983b8e80941Smrg{ 984b8e80941Smrg STUB(D3DERR_INVALIDCALL); 985b8e80941Smrg} 986b8e80941Smrg 987b8e80941Smrgvoid NINE_WINAPI 988b8e80941SmrgNineDevice9_SetGammaRamp( struct NineDevice9 *This, 989b8e80941Smrg UINT iSwapChain, 990b8e80941Smrg DWORD Flags, 991b8e80941Smrg const D3DGAMMARAMP *pRamp ) 992b8e80941Smrg{ 993b8e80941Smrg DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This, 994b8e80941Smrg iSwapChain, Flags, pRamp); 995b8e80941Smrg 996b8e80941Smrg user_warn(iSwapChain >= This->nswapchains); 997b8e80941Smrg user_warn(!pRamp); 998b8e80941Smrg 999b8e80941Smrg if (pRamp && (iSwapChain < This->nswapchains)) { 1000b8e80941Smrg struct NineSwapChain9 *swap = This->swapchains[iSwapChain]; 1001b8e80941Smrg swap->gamma = *pRamp; 1002b8e80941Smrg ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow); 1003b8e80941Smrg } 1004b8e80941Smrg} 1005b8e80941Smrg 1006b8e80941Smrgvoid NINE_WINAPI 1007b8e80941SmrgNineDevice9_GetGammaRamp( struct NineDevice9 *This, 1008b8e80941Smrg UINT iSwapChain, 1009b8e80941Smrg D3DGAMMARAMP *pRamp ) 1010b8e80941Smrg{ 1011b8e80941Smrg DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp); 1012b8e80941Smrg 1013b8e80941Smrg user_warn(iSwapChain >= This->nswapchains); 1014b8e80941Smrg user_warn(!pRamp); 1015b8e80941Smrg 1016b8e80941Smrg if (pRamp && (iSwapChain < This->nswapchains)) 1017b8e80941Smrg *pRamp = This->swapchains[iSwapChain]->gamma; 1018b8e80941Smrg} 1019b8e80941Smrg 1020b8e80941SmrgHRESULT NINE_WINAPI 1021b8e80941SmrgNineDevice9_CreateTexture( struct NineDevice9 *This, 1022b8e80941Smrg UINT Width, 1023b8e80941Smrg UINT Height, 1024b8e80941Smrg UINT Levels, 1025b8e80941Smrg DWORD Usage, 1026b8e80941Smrg D3DFORMAT Format, 1027b8e80941Smrg D3DPOOL Pool, 1028b8e80941Smrg IDirect3DTexture9 **ppTexture, 1029b8e80941Smrg HANDLE *pSharedHandle ) 1030b8e80941Smrg{ 1031b8e80941Smrg struct NineTexture9 *tex; 1032b8e80941Smrg HRESULT hr; 1033b8e80941Smrg 1034b8e80941Smrg DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " 1035b8e80941Smrg "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels, 1036b8e80941Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 1037b8e80941Smrg nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle); 1038b8e80941Smrg 1039b8e80941Smrg Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP | 1040b8e80941Smrg D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 1041b8e80941Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI; 1042b8e80941Smrg 1043b8e80941Smrg *ppTexture = NULL; 1044b8e80941Smrg 1045b8e80941Smrg hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool, 1046b8e80941Smrg &tex, pSharedHandle); 1047b8e80941Smrg if (SUCCEEDED(hr)) 1048b8e80941Smrg *ppTexture = (IDirect3DTexture9 *)tex; 1049b8e80941Smrg 1050b8e80941Smrg return hr; 1051b8e80941Smrg} 1052b8e80941Smrg 1053b8e80941SmrgHRESULT NINE_WINAPI 1054b8e80941SmrgNineDevice9_CreateVolumeTexture( struct NineDevice9 *This, 1055b8e80941Smrg UINT Width, 1056b8e80941Smrg UINT Height, 1057b8e80941Smrg UINT Depth, 1058b8e80941Smrg UINT Levels, 1059b8e80941Smrg DWORD Usage, 1060b8e80941Smrg D3DFORMAT Format, 1061b8e80941Smrg D3DPOOL Pool, 1062b8e80941Smrg IDirect3DVolumeTexture9 **ppVolumeTexture, 1063b8e80941Smrg HANDLE *pSharedHandle ) 1064b8e80941Smrg{ 1065b8e80941Smrg struct NineVolumeTexture9 *tex; 1066b8e80941Smrg HRESULT hr; 1067b8e80941Smrg 1068b8e80941Smrg DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s " 1069b8e80941Smrg "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels, 1070b8e80941Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 1071b8e80941Smrg nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle); 1072b8e80941Smrg 1073b8e80941Smrg Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 1074b8e80941Smrg D3DUSAGE_SOFTWAREPROCESSING; 1075b8e80941Smrg 1076b8e80941Smrg *ppVolumeTexture = NULL; 1077b8e80941Smrg 1078b8e80941Smrg hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels, 1079b8e80941Smrg Usage, Format, Pool, &tex, pSharedHandle); 1080b8e80941Smrg if (SUCCEEDED(hr)) 1081b8e80941Smrg *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex; 1082b8e80941Smrg 1083b8e80941Smrg return hr; 1084b8e80941Smrg} 1085b8e80941Smrg 1086b8e80941SmrgHRESULT NINE_WINAPI 1087b8e80941SmrgNineDevice9_CreateCubeTexture( struct NineDevice9 *This, 1088b8e80941Smrg UINT EdgeLength, 1089b8e80941Smrg UINT Levels, 1090b8e80941Smrg DWORD Usage, 1091b8e80941Smrg D3DFORMAT Format, 1092b8e80941Smrg D3DPOOL Pool, 1093b8e80941Smrg IDirect3DCubeTexture9 **ppCubeTexture, 1094b8e80941Smrg HANDLE *pSharedHandle ) 1095b8e80941Smrg{ 1096b8e80941Smrg struct NineCubeTexture9 *tex; 1097b8e80941Smrg HRESULT hr; 1098b8e80941Smrg 1099b8e80941Smrg DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p " 1100b8e80941Smrg "pSharedHandle=%p\n", This, EdgeLength, Levels, 1101b8e80941Smrg nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 1102b8e80941Smrg nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle); 1103b8e80941Smrg 1104b8e80941Smrg Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | 1105b8e80941Smrg D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 1106b8e80941Smrg D3DUSAGE_SOFTWAREPROCESSING; 1107b8e80941Smrg 1108b8e80941Smrg *ppCubeTexture = NULL; 1109b8e80941Smrg 1110b8e80941Smrg hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool, 1111b8e80941Smrg &tex, pSharedHandle); 1112b8e80941Smrg if (SUCCEEDED(hr)) 1113b8e80941Smrg *ppCubeTexture = (IDirect3DCubeTexture9 *)tex; 1114b8e80941Smrg 1115b8e80941Smrg return hr; 1116b8e80941Smrg} 1117b8e80941Smrg 1118b8e80941SmrgHRESULT NINE_WINAPI 1119b8e80941SmrgNineDevice9_CreateVertexBuffer( struct NineDevice9 *This, 1120b8e80941Smrg UINT Length, 1121b8e80941Smrg DWORD Usage, 1122b8e80941Smrg DWORD FVF, 1123b8e80941Smrg D3DPOOL Pool, 1124b8e80941Smrg IDirect3DVertexBuffer9 **ppVertexBuffer, 1125b8e80941Smrg HANDLE *pSharedHandle ) 1126b8e80941Smrg{ 1127b8e80941Smrg struct NineVertexBuffer9 *buf; 1128b8e80941Smrg HRESULT hr; 1129b8e80941Smrg D3DVERTEXBUFFER_DESC desc; 1130b8e80941Smrg 1131b8e80941Smrg DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n", 1132b8e80941Smrg This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); 1133b8e80941Smrg 1134b8e80941Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 1135b8e80941Smrg 1136b8e80941Smrg desc.Format = D3DFMT_VERTEXDATA; 1137b8e80941Smrg desc.Type = D3DRTYPE_VERTEXBUFFER; 1138b8e80941Smrg desc.Usage = Usage & 1139b8e80941Smrg (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 1140b8e80941Smrg D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 1141b8e80941Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI | 1142b8e80941Smrg D3DUSAGE_WRITEONLY); 1143b8e80941Smrg desc.Pool = Pool; 1144b8e80941Smrg desc.Size = Length; 1145b8e80941Smrg desc.FVF = FVF; 1146b8e80941Smrg 1147b8e80941Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1148b8e80941Smrg user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 1149b8e80941Smrg 1150b8e80941Smrg hr = NineVertexBuffer9_new(This, &desc, &buf); 1151b8e80941Smrg if (SUCCEEDED(hr)) 1152b8e80941Smrg *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf; 1153b8e80941Smrg return hr; 1154b8e80941Smrg} 1155b8e80941Smrg 1156b8e80941SmrgHRESULT NINE_WINAPI 1157b8e80941SmrgNineDevice9_CreateIndexBuffer( struct NineDevice9 *This, 1158b8e80941Smrg UINT Length, 1159b8e80941Smrg DWORD Usage, 1160b8e80941Smrg D3DFORMAT Format, 1161b8e80941Smrg D3DPOOL Pool, 1162b8e80941Smrg IDirect3DIndexBuffer9 **ppIndexBuffer, 1163b8e80941Smrg HANDLE *pSharedHandle ) 1164b8e80941Smrg{ 1165b8e80941Smrg struct NineIndexBuffer9 *buf; 1166b8e80941Smrg HRESULT hr; 1167b8e80941Smrg D3DINDEXBUFFER_DESC desc; 1168b8e80941Smrg 1169b8e80941Smrg DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p " 1170b8e80941Smrg "pSharedHandle=%p\n", This, Length, Usage, 1171b8e80941Smrg d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle); 1172b8e80941Smrg 1173b8e80941Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 1174b8e80941Smrg 1175b8e80941Smrg desc.Format = Format; 1176b8e80941Smrg desc.Type = D3DRTYPE_INDEXBUFFER; 1177b8e80941Smrg desc.Usage = Usage & 1178b8e80941Smrg (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 1179b8e80941Smrg D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 1180b8e80941Smrg D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY); 1181b8e80941Smrg desc.Pool = Pool; 1182b8e80941Smrg desc.Size = Length; 1183b8e80941Smrg 1184b8e80941Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1185b8e80941Smrg user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 1186b8e80941Smrg 1187b8e80941Smrg hr = NineIndexBuffer9_new(This, &desc, &buf); 1188b8e80941Smrg if (SUCCEEDED(hr)) 1189b8e80941Smrg *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf; 1190b8e80941Smrg return hr; 1191b8e80941Smrg} 1192b8e80941Smrg 1193b8e80941Smrgstatic HRESULT 1194b8e80941Smrgcreate_zs_or_rt_surface(struct NineDevice9 *This, 1195b8e80941Smrg unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */ 1196b8e80941Smrg D3DPOOL Pool, 1197b8e80941Smrg UINT Width, UINT Height, 1198b8e80941Smrg D3DFORMAT Format, 1199b8e80941Smrg D3DMULTISAMPLE_TYPE MultiSample, 1200b8e80941Smrg DWORD MultisampleQuality, 1201b8e80941Smrg BOOL Discard_or_Lockable, 1202b8e80941Smrg IDirect3DSurface9 **ppSurface, 1203b8e80941Smrg HANDLE *pSharedHandle) 1204b8e80941Smrg{ 1205b8e80941Smrg struct NineSurface9 *surface; 1206b8e80941Smrg HRESULT hr; 1207b8e80941Smrg D3DSURFACE_DESC desc; 1208b8e80941Smrg 1209b8e80941Smrg DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u " 1210b8e80941Smrg "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n", 1211b8e80941Smrg This, type, nine_D3DPOOL_to_str(Pool), Width, Height, 1212b8e80941Smrg d3dformat_to_string(Format), MultiSample, MultisampleQuality, 1213b8e80941Smrg Discard_or_Lockable, ppSurface, pSharedHandle); 1214b8e80941Smrg 1215b8e80941Smrg if (pSharedHandle) 1216b8e80941Smrg DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n"); 1217b8e80941Smrg 1218b8e80941Smrg user_assert(Width && Height, D3DERR_INVALIDCALL); 1219b8e80941Smrg user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 1220b8e80941Smrg 1221b8e80941Smrg desc.Format = Format; 1222b8e80941Smrg desc.Type = D3DRTYPE_SURFACE; 1223b8e80941Smrg desc.Usage = 0; 1224b8e80941Smrg desc.Pool = Pool; 1225b8e80941Smrg desc.MultiSampleType = MultiSample; 1226b8e80941Smrg desc.MultiSampleQuality = MultisampleQuality; 1227b8e80941Smrg desc.Width = Width; 1228b8e80941Smrg desc.Height = Height; 1229b8e80941Smrg switch (type) { 1230b8e80941Smrg case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break; 1231b8e80941Smrg case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break; 1232b8e80941Smrg default: assert(type == 2); break; 1233b8e80941Smrg } 1234b8e80941Smrg 1235b8e80941Smrg hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface); 1236b8e80941Smrg if (SUCCEEDED(hr)) { 1237b8e80941Smrg *ppSurface = (IDirect3DSurface9 *)surface; 1238b8e80941Smrg 1239b8e80941Smrg if (surface->base.resource && Discard_or_Lockable && (type != 1)) 1240b8e80941Smrg surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; 1241b8e80941Smrg } 1242b8e80941Smrg 1243b8e80941Smrg return hr; 1244b8e80941Smrg} 1245b8e80941Smrg 1246b8e80941SmrgHRESULT NINE_WINAPI 1247b8e80941SmrgNineDevice9_CreateRenderTarget( struct NineDevice9 *This, 1248b8e80941Smrg UINT Width, 1249b8e80941Smrg UINT Height, 1250b8e80941Smrg D3DFORMAT Format, 1251b8e80941Smrg D3DMULTISAMPLE_TYPE MultiSample, 1252b8e80941Smrg DWORD MultisampleQuality, 1253b8e80941Smrg BOOL Lockable, 1254b8e80941Smrg IDirect3DSurface9 **ppSurface, 1255b8e80941Smrg HANDLE *pSharedHandle ) 1256b8e80941Smrg{ 1257b8e80941Smrg *ppSurface = NULL; 1258b8e80941Smrg return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT, 1259b8e80941Smrg Width, Height, Format, 1260b8e80941Smrg MultiSample, MultisampleQuality, 1261b8e80941Smrg Lockable, ppSurface, pSharedHandle); 1262b8e80941Smrg} 1263b8e80941Smrg 1264b8e80941SmrgHRESULT NINE_WINAPI 1265b8e80941SmrgNineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, 1266b8e80941Smrg UINT Width, 1267b8e80941Smrg UINT Height, 1268b8e80941Smrg D3DFORMAT Format, 1269b8e80941Smrg D3DMULTISAMPLE_TYPE MultiSample, 1270b8e80941Smrg DWORD MultisampleQuality, 1271b8e80941Smrg BOOL Discard, 1272b8e80941Smrg IDirect3DSurface9 **ppSurface, 1273b8e80941Smrg HANDLE *pSharedHandle ) 1274b8e80941Smrg{ 1275b8e80941Smrg *ppSurface = NULL; 1276b8e80941Smrg if (!depth_stencil_format(Format)) 1277b8e80941Smrg return D3DERR_NOTAVAILABLE; 1278b8e80941Smrg return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT, 1279b8e80941Smrg Width, Height, Format, 1280b8e80941Smrg MultiSample, MultisampleQuality, 1281b8e80941Smrg Discard, ppSurface, pSharedHandle); 1282b8e80941Smrg} 1283b8e80941Smrg 1284b8e80941SmrgHRESULT NINE_WINAPI 1285b8e80941SmrgNineDevice9_UpdateSurface( struct NineDevice9 *This, 1286b8e80941Smrg IDirect3DSurface9 *pSourceSurface, 1287b8e80941Smrg const RECT *pSourceRect, 1288b8e80941Smrg IDirect3DSurface9 *pDestinationSurface, 1289b8e80941Smrg const POINT *pDestPoint ) 1290b8e80941Smrg{ 1291b8e80941Smrg struct NineSurface9 *dst = NineSurface9(pDestinationSurface); 1292b8e80941Smrg struct NineSurface9 *src = NineSurface9(pSourceSurface); 1293b8e80941Smrg int copy_width, copy_height; 1294b8e80941Smrg RECT destRect; 1295b8e80941Smrg 1296b8e80941Smrg DBG("This=%p pSourceSurface=%p pDestinationSurface=%p " 1297b8e80941Smrg "pSourceRect=%p pDestPoint=%p\n", This, 1298b8e80941Smrg pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint); 1299b8e80941Smrg if (pSourceRect) 1300b8e80941Smrg DBG("pSourceRect = (%u,%u)-(%u,%u)\n", 1301b8e80941Smrg pSourceRect->left, pSourceRect->top, 1302b8e80941Smrg pSourceRect->right, pSourceRect->bottom); 1303b8e80941Smrg if (pDestPoint) 1304b8e80941Smrg DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y); 1305b8e80941Smrg 1306b8e80941Smrg user_assert(dst && src, D3DERR_INVALIDCALL); 1307b8e80941Smrg 1308b8e80941Smrg user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1309b8e80941Smrg user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1310b8e80941Smrg 1311b8e80941Smrg user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 1312b8e80941Smrg user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 1313b8e80941Smrg 1314b8e80941Smrg user_assert(!src->lock_count, D3DERR_INVALIDCALL); 1315b8e80941Smrg user_assert(!dst->lock_count, D3DERR_INVALIDCALL); 1316b8e80941Smrg 1317b8e80941Smrg user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL); 1318b8e80941Smrg user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL); 1319b8e80941Smrg 1320b8e80941Smrg if (pSourceRect) { 1321b8e80941Smrg copy_width = pSourceRect->right - pSourceRect->left; 1322b8e80941Smrg copy_height = pSourceRect->bottom - pSourceRect->top; 1323b8e80941Smrg 1324b8e80941Smrg user_assert(pSourceRect->left >= 0 && 1325b8e80941Smrg copy_width > 0 && 1326b8e80941Smrg pSourceRect->right <= src->desc.Width && 1327b8e80941Smrg pSourceRect->top >= 0 && 1328b8e80941Smrg copy_height > 0 && 1329b8e80941Smrg pSourceRect->bottom <= src->desc.Height, 1330b8e80941Smrg D3DERR_INVALIDCALL); 1331b8e80941Smrg } else { 1332b8e80941Smrg copy_width = src->desc.Width; 1333b8e80941Smrg copy_height = src->desc.Height; 1334b8e80941Smrg } 1335b8e80941Smrg 1336b8e80941Smrg destRect.right = copy_width; 1337b8e80941Smrg destRect.bottom = copy_height; 1338b8e80941Smrg 1339b8e80941Smrg if (pDestPoint) { 1340b8e80941Smrg user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0, 1341b8e80941Smrg D3DERR_INVALIDCALL); 1342b8e80941Smrg destRect.right += pDestPoint->x; 1343b8e80941Smrg destRect.bottom += pDestPoint->y; 1344b8e80941Smrg } 1345b8e80941Smrg 1346b8e80941Smrg user_assert(destRect.right <= dst->desc.Width && 1347b8e80941Smrg destRect.bottom <= dst->desc.Height, 1348b8e80941Smrg D3DERR_INVALIDCALL); 1349b8e80941Smrg 1350b8e80941Smrg if (compressed_format(dst->desc.Format)) { 1351b8e80941Smrg const unsigned w = util_format_get_blockwidth(dst->base.info.format); 1352b8e80941Smrg const unsigned h = util_format_get_blockheight(dst->base.info.format); 1353b8e80941Smrg 1354b8e80941Smrg if (pDestPoint) { 1355b8e80941Smrg user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h), 1356b8e80941Smrg D3DERR_INVALIDCALL); 1357b8e80941Smrg } 1358b8e80941Smrg 1359b8e80941Smrg if (pSourceRect) { 1360b8e80941Smrg user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h), 1361b8e80941Smrg D3DERR_INVALIDCALL); 1362b8e80941Smrg } 1363b8e80941Smrg if (!(copy_width == src->desc.Width && 1364b8e80941Smrg copy_width == dst->desc.Width && 1365b8e80941Smrg copy_height == src->desc.Height && 1366b8e80941Smrg copy_height == dst->desc.Height)) { 1367b8e80941Smrg user_assert(!(copy_width % w) && !(copy_height % h), 1368b8e80941Smrg D3DERR_INVALIDCALL); 1369b8e80941Smrg } 1370b8e80941Smrg } 1371b8e80941Smrg 1372b8e80941Smrg NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect); 1373b8e80941Smrg 1374b8e80941Smrg return D3D_OK; 1375b8e80941Smrg} 1376b8e80941Smrg 1377b8e80941SmrgHRESULT NINE_WINAPI 1378b8e80941SmrgNineDevice9_UpdateTexture( struct NineDevice9 *This, 1379b8e80941Smrg IDirect3DBaseTexture9 *pSourceTexture, 1380b8e80941Smrg IDirect3DBaseTexture9 *pDestinationTexture ) 1381b8e80941Smrg{ 1382b8e80941Smrg struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture); 1383b8e80941Smrg struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture); 1384b8e80941Smrg unsigned l, m; 1385b8e80941Smrg unsigned last_src_level, last_dst_level; 1386b8e80941Smrg RECT rect; 1387b8e80941Smrg 1388b8e80941Smrg DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This, 1389b8e80941Smrg pSourceTexture, pDestinationTexture); 1390b8e80941Smrg 1391b8e80941Smrg user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL); 1392b8e80941Smrg user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL); 1393b8e80941Smrg 1394b8e80941Smrg user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1395b8e80941Smrg user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1396b8e80941Smrg user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL); 1397b8e80941Smrg user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) || 1398b8e80941Smrg dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL); 1399b8e80941Smrg 1400b8e80941Smrg /* Spec: Failure if 1401b8e80941Smrg * . Different formats 1402b8e80941Smrg * . Fewer src levels than dst levels (if the opposite, only matching levels 1403b8e80941Smrg * are supposed to be copied) 1404b8e80941Smrg * . Levels do not match 1405b8e80941Smrg * DDI: Actually the above should pass because of legacy applications 1406b8e80941Smrg * Do what you want about these, but you shouldn't crash. 1407b8e80941Smrg * However driver can expect that the top dimension is greater for src than dst. 1408b8e80941Smrg * Wine tests: Every combination that passes the initial checks should pass. 1409b8e80941Smrg * . Different formats => conversion driver and format dependent. 1410b8e80941Smrg * . 1 level, but size not matching => copy is done (and even crash if src bigger 1411b8e80941Smrg * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied 1412b8e80941Smrg * or if a subrect is copied). 1413b8e80941Smrg * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect 1414b8e80941Smrg * copied to 7x7. 1415b8e80941Smrg * 1416b8e80941Smrg * From these, the proposal is: 1417b8e80941Smrg * . Different formats -> use util_format_translate to translate if possible for surfaces. 1418b8e80941Smrg * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations 1419b8e80941Smrg * . First level copied -> the first level such that src is smaller or equal to dst first level 1420b8e80941Smrg * . number of levels copied -> as long as it fits and textures have levels 1421b8e80941Smrg * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK) 1422b8e80941Smrg */ 1423b8e80941Smrg 1424b8e80941Smrg last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level; 1425b8e80941Smrg last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level; 1426b8e80941Smrg 1427b8e80941Smrg for (m = 0; m <= last_src_level; ++m) { 1428b8e80941Smrg unsigned w = u_minify(srcb->base.info.width0, m); 1429b8e80941Smrg unsigned h = u_minify(srcb->base.info.height0, m); 1430b8e80941Smrg unsigned d = u_minify(srcb->base.info.depth0, m); 1431b8e80941Smrg 1432b8e80941Smrg if (w <= dstb->base.info.width0 && 1433b8e80941Smrg h <= dstb->base.info.height0 && 1434b8e80941Smrg d <= dstb->base.info.depth0) 1435b8e80941Smrg break; 1436b8e80941Smrg } 1437b8e80941Smrg user_assert(m <= last_src_level, D3D_OK); 1438b8e80941Smrg 1439b8e80941Smrg last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level); 1440b8e80941Smrg 1441b8e80941Smrg if (dstb->base.type == D3DRTYPE_TEXTURE) { 1442b8e80941Smrg struct NineTexture9 *dst = NineTexture9(dstb); 1443b8e80941Smrg struct NineTexture9 *src = NineTexture9(srcb); 1444b8e80941Smrg 1445b8e80941Smrg if (src->dirty_rect.width == 0) 1446b8e80941Smrg return D3D_OK; 1447b8e80941Smrg 1448b8e80941Smrg pipe_box_to_rect(&rect, &src->dirty_rect); 1449b8e80941Smrg for (l = 0; l < m; ++l) 1450b8e80941Smrg rect_minify_inclusive(&rect); 1451b8e80941Smrg 1452b8e80941Smrg for (l = 0; l <= last_dst_level; ++l, ++m) { 1453b8e80941Smrg fit_rect_format_inclusive(dst->base.base.info.format, 1454b8e80941Smrg &rect, 1455b8e80941Smrg dst->surfaces[l]->desc.Width, 1456b8e80941Smrg dst->surfaces[l]->desc.Height); 1457b8e80941Smrg NineSurface9_CopyMemToDefault(dst->surfaces[l], 1458b8e80941Smrg src->surfaces[m], 1459b8e80941Smrg (POINT *)&rect, 1460b8e80941Smrg &rect); 1461b8e80941Smrg rect_minify_inclusive(&rect); 1462b8e80941Smrg } 1463b8e80941Smrg u_box_origin_2d(0, 0, &src->dirty_rect); 1464b8e80941Smrg } else 1465b8e80941Smrg if (dstb->base.type == D3DRTYPE_CUBETEXTURE) { 1466b8e80941Smrg struct NineCubeTexture9 *dst = NineCubeTexture9(dstb); 1467b8e80941Smrg struct NineCubeTexture9 *src = NineCubeTexture9(srcb); 1468b8e80941Smrg unsigned z; 1469b8e80941Smrg 1470b8e80941Smrg /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */ 1471b8e80941Smrg for (z = 0; z < 6; ++z) { 1472b8e80941Smrg if (src->dirty_rect[z].width == 0) 1473b8e80941Smrg continue; 1474b8e80941Smrg 1475b8e80941Smrg pipe_box_to_rect(&rect, &src->dirty_rect[z]); 1476b8e80941Smrg for (l = 0; l < m; ++l) 1477b8e80941Smrg rect_minify_inclusive(&rect); 1478b8e80941Smrg 1479b8e80941Smrg for (l = 0; l <= last_dst_level; ++l, ++m) { 1480b8e80941Smrg fit_rect_format_inclusive(dst->base.base.info.format, 1481b8e80941Smrg &rect, 1482b8e80941Smrg dst->surfaces[l * 6 + z]->desc.Width, 1483b8e80941Smrg dst->surfaces[l * 6 + z]->desc.Height); 1484b8e80941Smrg NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z], 1485b8e80941Smrg src->surfaces[m * 6 + z], 1486b8e80941Smrg (POINT *)&rect, 1487b8e80941Smrg &rect); 1488b8e80941Smrg rect_minify_inclusive(&rect); 1489b8e80941Smrg } 1490b8e80941Smrg u_box_origin_2d(0, 0, &src->dirty_rect[z]); 1491b8e80941Smrg m -= l; 1492b8e80941Smrg } 1493b8e80941Smrg } else 1494b8e80941Smrg if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) { 1495b8e80941Smrg struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb); 1496b8e80941Smrg struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb); 1497b8e80941Smrg 1498b8e80941Smrg if (src->dirty_box.width == 0) 1499b8e80941Smrg return D3D_OK; 1500b8e80941Smrg for (l = 0; l <= last_dst_level; ++l, ++m) 1501b8e80941Smrg NineVolume9_CopyMemToDefault(dst->volumes[l], 1502b8e80941Smrg src->volumes[m], 0, 0, 0, NULL); 1503b8e80941Smrg u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box); 1504b8e80941Smrg } else{ 1505b8e80941Smrg assert(!"invalid texture type"); 1506b8e80941Smrg } 1507b8e80941Smrg 1508b8e80941Smrg if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) { 1509b8e80941Smrg dstb->dirty_mip = TRUE; 1510b8e80941Smrg NineBaseTexture9_GenerateMipSubLevels(dstb); 1511b8e80941Smrg } 1512b8e80941Smrg 1513b8e80941Smrg return D3D_OK; 1514b8e80941Smrg} 1515b8e80941Smrg 1516b8e80941SmrgHRESULT NINE_WINAPI 1517b8e80941SmrgNineDevice9_GetRenderTargetData( struct NineDevice9 *This, 1518b8e80941Smrg IDirect3DSurface9 *pRenderTarget, 1519b8e80941Smrg IDirect3DSurface9 *pDestSurface ) 1520b8e80941Smrg{ 1521b8e80941Smrg struct NineSurface9 *dst = NineSurface9(pDestSurface); 1522b8e80941Smrg struct NineSurface9 *src = NineSurface9(pRenderTarget); 1523b8e80941Smrg 1524b8e80941Smrg DBG("This=%p pRenderTarget=%p pDestSurface=%p\n", 1525b8e80941Smrg This, pRenderTarget, pDestSurface); 1526b8e80941Smrg 1527b8e80941Smrg user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL); 1528b8e80941Smrg 1529b8e80941Smrg user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1530b8e80941Smrg user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1531b8e80941Smrg 1532b8e80941Smrg user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 1533b8e80941Smrg user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 1534b8e80941Smrg 1535b8e80941Smrg user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL); 1536b8e80941Smrg user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL); 1537b8e80941Smrg 1538b8e80941Smrg user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL); 1539b8e80941Smrg 1540b8e80941Smrg NineSurface9_CopyDefaultToMem(dst, src); 1541b8e80941Smrg 1542b8e80941Smrg return D3D_OK; 1543b8e80941Smrg} 1544b8e80941Smrg 1545b8e80941SmrgHRESULT NINE_WINAPI 1546b8e80941SmrgNineDevice9_GetFrontBufferData( struct NineDevice9 *This, 1547b8e80941Smrg UINT iSwapChain, 1548b8e80941Smrg IDirect3DSurface9 *pDestSurface ) 1549b8e80941Smrg{ 1550b8e80941Smrg DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This, 1551b8e80941Smrg iSwapChain, pDestSurface); 1552b8e80941Smrg 1553b8e80941Smrg user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL); 1554b8e80941Smrg user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 1555b8e80941Smrg 1556b8e80941Smrg return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain], 1557b8e80941Smrg pDestSurface); 1558b8e80941Smrg} 1559b8e80941Smrg 1560b8e80941SmrgHRESULT NINE_WINAPI 1561b8e80941SmrgNineDevice9_StretchRect( struct NineDevice9 *This, 1562b8e80941Smrg IDirect3DSurface9 *pSourceSurface, 1563b8e80941Smrg const RECT *pSourceRect, 1564b8e80941Smrg IDirect3DSurface9 *pDestSurface, 1565b8e80941Smrg const RECT *pDestRect, 1566b8e80941Smrg D3DTEXTUREFILTERTYPE Filter ) 1567b8e80941Smrg{ 1568b8e80941Smrg struct pipe_screen *screen = This->screen; 1569b8e80941Smrg struct NineSurface9 *dst = NineSurface9(pDestSurface); 1570b8e80941Smrg struct NineSurface9 *src = NineSurface9(pSourceSurface); 1571b8e80941Smrg struct pipe_resource *dst_res = NineSurface9_GetResource(dst); 1572b8e80941Smrg struct pipe_resource *src_res = NineSurface9_GetResource(src); 1573b8e80941Smrg boolean zs; 1574b8e80941Smrg struct pipe_blit_info blit; 1575b8e80941Smrg boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE; 1576b8e80941Smrg 1577b8e80941Smrg DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p " 1578b8e80941Smrg "pDestRect=%p Filter=%u\n", 1579b8e80941Smrg This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); 1580b8e80941Smrg if (pSourceRect) 1581b8e80941Smrg DBG("pSourceRect=(%u,%u)-(%u,%u)\n", 1582b8e80941Smrg pSourceRect->left, pSourceRect->top, 1583b8e80941Smrg pSourceRect->right, pSourceRect->bottom); 1584b8e80941Smrg if (pDestRect) 1585b8e80941Smrg DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top, 1586b8e80941Smrg pDestRect->right, pDestRect->bottom); 1587b8e80941Smrg 1588b8e80941Smrg user_assert(dst->base.pool == D3DPOOL_DEFAULT && 1589b8e80941Smrg src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1590b8e80941Smrg zs = util_format_is_depth_or_stencil(dst_res->format); 1591b8e80941Smrg user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL); 1592b8e80941Smrg user_assert(!zs || !pSourceRect || 1593b8e80941Smrg (pSourceRect->left == 0 && 1594b8e80941Smrg pSourceRect->top == 0 && 1595b8e80941Smrg pSourceRect->right == src->desc.Width && 1596b8e80941Smrg pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL); 1597b8e80941Smrg user_assert(!zs || !pDestRect || 1598b8e80941Smrg (pDestRect->left == 0 && 1599b8e80941Smrg pDestRect->top == 0 && 1600b8e80941Smrg pDestRect->right == dst->desc.Width && 1601b8e80941Smrg pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL); 1602b8e80941Smrg user_assert(!zs || 1603b8e80941Smrg (dst->desc.Width == src->desc.Width && 1604b8e80941Smrg dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL); 1605b8e80941Smrg user_assert(zs || !util_format_is_depth_or_stencil(src_res->format), 1606b8e80941Smrg D3DERR_INVALIDCALL); 1607b8e80941Smrg user_assert(!zs || dst->desc.Format == src->desc.Format, 1608b8e80941Smrg D3DERR_INVALIDCALL); 1609b8e80941Smrg user_assert(screen->is_format_supported(screen, src_res->format, 1610b8e80941Smrg src_res->target, 1611b8e80941Smrg src_res->nr_samples, 1612b8e80941Smrg src_res->nr_storage_samples, 1613b8e80941Smrg PIPE_BIND_SAMPLER_VIEW), 1614b8e80941Smrg D3DERR_INVALIDCALL); 1615b8e80941Smrg 1616b8e80941Smrg /* We might want to permit these, but wine thinks we shouldn't. */ 1617b8e80941Smrg user_assert(!pDestRect || 1618b8e80941Smrg (pDestRect->left <= pDestRect->right && 1619b8e80941Smrg pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL); 1620b8e80941Smrg user_assert(!pSourceRect || 1621b8e80941Smrg (pSourceRect->left <= pSourceRect->right && 1622b8e80941Smrg pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL); 1623b8e80941Smrg 1624b8e80941Smrg memset(&blit, 0, sizeof(blit)); 1625b8e80941Smrg blit.dst.resource = dst_res; 1626b8e80941Smrg blit.dst.level = dst->level; 1627b8e80941Smrg blit.dst.box.z = dst->layer; 1628b8e80941Smrg blit.dst.box.depth = 1; 1629b8e80941Smrg blit.dst.format = dst_res->format; 1630b8e80941Smrg if (pDestRect) { 1631b8e80941Smrg flip_x = pDestRect->left > pDestRect->right; 1632b8e80941Smrg if (flip_x) { 1633b8e80941Smrg blit.dst.box.x = pDestRect->right; 1634b8e80941Smrg blit.dst.box.width = pDestRect->left - pDestRect->right; 1635b8e80941Smrg } else { 1636b8e80941Smrg blit.dst.box.x = pDestRect->left; 1637b8e80941Smrg blit.dst.box.width = pDestRect->right - pDestRect->left; 1638b8e80941Smrg } 1639b8e80941Smrg flip_y = pDestRect->top > pDestRect->bottom; 1640b8e80941Smrg if (flip_y) { 1641b8e80941Smrg blit.dst.box.y = pDestRect->bottom; 1642b8e80941Smrg blit.dst.box.height = pDestRect->top - pDestRect->bottom; 1643b8e80941Smrg } else { 1644b8e80941Smrg blit.dst.box.y = pDestRect->top; 1645b8e80941Smrg blit.dst.box.height = pDestRect->bottom - pDestRect->top; 1646b8e80941Smrg } 1647b8e80941Smrg } else { 1648b8e80941Smrg blit.dst.box.x = 0; 1649b8e80941Smrg blit.dst.box.y = 0; 1650b8e80941Smrg blit.dst.box.width = dst->desc.Width; 1651b8e80941Smrg blit.dst.box.height = dst->desc.Height; 1652b8e80941Smrg } 1653b8e80941Smrg blit.src.resource = src_res; 1654b8e80941Smrg blit.src.level = src->level; 1655b8e80941Smrg blit.src.box.z = src->layer; 1656b8e80941Smrg blit.src.box.depth = 1; 1657b8e80941Smrg blit.src.format = src_res->format; 1658b8e80941Smrg if (pSourceRect) { 1659b8e80941Smrg if (flip_x ^ (pSourceRect->left > pSourceRect->right)) { 1660b8e80941Smrg blit.src.box.x = pSourceRect->right; 1661b8e80941Smrg blit.src.box.width = pSourceRect->left - pSourceRect->right; 1662b8e80941Smrg } else { 1663b8e80941Smrg blit.src.box.x = pSourceRect->left; 1664b8e80941Smrg blit.src.box.width = pSourceRect->right - pSourceRect->left; 1665b8e80941Smrg } 1666b8e80941Smrg if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) { 1667b8e80941Smrg blit.src.box.y = pSourceRect->bottom; 1668b8e80941Smrg blit.src.box.height = pSourceRect->top - pSourceRect->bottom; 1669b8e80941Smrg } else { 1670b8e80941Smrg blit.src.box.y = pSourceRect->top; 1671b8e80941Smrg blit.src.box.height = pSourceRect->bottom - pSourceRect->top; 1672b8e80941Smrg } 1673b8e80941Smrg } else { 1674b8e80941Smrg blit.src.box.x = flip_x ? src->desc.Width : 0; 1675b8e80941Smrg blit.src.box.y = flip_y ? src->desc.Height : 0; 1676b8e80941Smrg blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width; 1677b8e80941Smrg blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height; 1678b8e80941Smrg } 1679b8e80941Smrg blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA; 1680b8e80941Smrg blit.filter = Filter == D3DTEXF_LINEAR ? 1681b8e80941Smrg PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST; 1682b8e80941Smrg blit.scissor_enable = FALSE; 1683b8e80941Smrg blit.alpha_blend = FALSE; 1684b8e80941Smrg 1685b8e80941Smrg /* If both of a src and dst dimension are negative, flip them. */ 1686b8e80941Smrg if (blit.dst.box.width < 0 && blit.src.box.width < 0) { 1687b8e80941Smrg blit.dst.box.width = -blit.dst.box.width; 1688b8e80941Smrg blit.src.box.width = -blit.src.box.width; 1689b8e80941Smrg } 1690b8e80941Smrg if (blit.dst.box.height < 0 && blit.src.box.height < 0) { 1691b8e80941Smrg blit.dst.box.height = -blit.dst.box.height; 1692b8e80941Smrg blit.src.box.height = -blit.src.box.height; 1693b8e80941Smrg } 1694b8e80941Smrg scaled = 1695b8e80941Smrg blit.dst.box.width != blit.src.box.width || 1696b8e80941Smrg blit.dst.box.height != blit.src.box.height; 1697b8e80941Smrg 1698b8e80941Smrg user_assert(!scaled || dst != src, D3DERR_INVALIDCALL); 1699b8e80941Smrg user_assert(!scaled || 1700b8e80941Smrg !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL); 1701b8e80941Smrg user_assert(!NineSurface9_IsOffscreenPlain(dst) || 1702b8e80941Smrg NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL); 1703b8e80941Smrg user_assert(NineSurface9_IsOffscreenPlain(dst) || 1704b8e80941Smrg dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL), 1705b8e80941Smrg D3DERR_INVALIDCALL); 1706b8e80941Smrg user_assert(!scaled || 1707b8e80941Smrg (!util_format_is_compressed(dst->base.info.format) && 1708b8e80941Smrg !util_format_is_compressed(src->base.info.format)), 1709b8e80941Smrg D3DERR_INVALIDCALL); 1710b8e80941Smrg 1711b8e80941Smrg user_warn(src == dst && 1712b8e80941Smrg u_box_test_intersection_2d(&blit.src.box, &blit.dst.box)); 1713b8e80941Smrg 1714b8e80941Smrg /* Check for clipping/clamping: */ 1715b8e80941Smrg { 1716b8e80941Smrg struct pipe_box box; 1717b8e80941Smrg int xy; 1718b8e80941Smrg 1719b8e80941Smrg xy = u_box_clip_2d(&box, &blit.dst.box, 1720b8e80941Smrg dst->desc.Width, dst->desc.Height); 1721b8e80941Smrg if (xy < 0) 1722b8e80941Smrg return D3D_OK; 1723b8e80941Smrg if (xy == 0) 1724b8e80941Smrg xy = u_box_clip_2d(&box, &blit.src.box, 1725b8e80941Smrg src->desc.Width, src->desc.Height); 1726b8e80941Smrg clamped = !!xy; 1727b8e80941Smrg } 1728b8e80941Smrg 1729b8e80941Smrg ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) || 1730b8e80941Smrg (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality); 1731b8e80941Smrg 1732b8e80941Smrg if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { 1733b8e80941Smrg DBG("using pipe->blit()\n"); 1734b8e80941Smrg /* TODO: software scaling */ 1735b8e80941Smrg user_assert(screen->is_format_supported(screen, dst_res->format, 1736b8e80941Smrg dst_res->target, 1737b8e80941Smrg dst_res->nr_samples, 1738b8e80941Smrg dst_res->nr_storage_samples, 1739b8e80941Smrg zs ? PIPE_BIND_DEPTH_STENCIL : 1740b8e80941Smrg PIPE_BIND_RENDER_TARGET), 1741b8e80941Smrg D3DERR_INVALIDCALL); 1742b8e80941Smrg 1743b8e80941Smrg nine_context_blit(This, (struct NineUnknown *)dst, 1744b8e80941Smrg (struct NineUnknown *)src, &blit); 1745b8e80941Smrg } else { 1746b8e80941Smrg assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 && 1747b8e80941Smrg blit.src.box.x >= 0 && blit.src.box.y >= 0 && 1748b8e80941Smrg blit.dst.box.x + blit.dst.box.width <= dst->desc.Width && 1749b8e80941Smrg blit.src.box.x + blit.src.box.width <= src->desc.Width && 1750b8e80941Smrg blit.dst.box.y + blit.dst.box.height <= dst->desc.Height && 1751b8e80941Smrg blit.src.box.y + blit.src.box.height <= src->desc.Height); 1752b8e80941Smrg /* Or drivers might crash ... */ 1753b8e80941Smrg DBG("Using resource_copy_region.\n"); 1754b8e80941Smrg nine_context_resource_copy_region(This, (struct NineUnknown *)dst, 1755b8e80941Smrg (struct NineUnknown *)src, 1756b8e80941Smrg blit.dst.resource, blit.dst.level, 1757b8e80941Smrg &blit.dst.box, 1758b8e80941Smrg blit.src.resource, blit.src.level, 1759b8e80941Smrg &blit.src.box); 1760b8e80941Smrg } 1761b8e80941Smrg 1762b8e80941Smrg /* Communicate the container it needs to update sublevels - if apply */ 1763b8e80941Smrg NineSurface9_MarkContainerDirty(dst); 1764b8e80941Smrg 1765b8e80941Smrg return D3D_OK; 1766b8e80941Smrg} 1767b8e80941Smrg 1768b8e80941SmrgHRESULT NINE_WINAPI 1769b8e80941SmrgNineDevice9_ColorFill( struct NineDevice9 *This, 1770b8e80941Smrg IDirect3DSurface9 *pSurface, 1771b8e80941Smrg const RECT *pRect, 1772b8e80941Smrg D3DCOLOR color ) 1773b8e80941Smrg{ 1774b8e80941Smrg struct NineSurface9 *surf = NineSurface9(pSurface); 1775b8e80941Smrg unsigned x, y, w, h; 1776b8e80941Smrg 1777b8e80941Smrg DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This, 1778b8e80941Smrg pSurface, pRect, color); 1779b8e80941Smrg if (pRect) 1780b8e80941Smrg DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top, 1781b8e80941Smrg pRect->right, pRect->bottom); 1782b8e80941Smrg 1783b8e80941Smrg user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1784b8e80941Smrg 1785b8e80941Smrg user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) || 1786b8e80941Smrg NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL); 1787b8e80941Smrg 1788b8e80941Smrg user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK); 1789b8e80941Smrg 1790b8e80941Smrg if (pRect) { 1791b8e80941Smrg x = pRect->left; 1792b8e80941Smrg y = pRect->top; 1793b8e80941Smrg w = pRect->right - pRect->left; 1794b8e80941Smrg h = pRect->bottom - pRect->top; 1795b8e80941Smrg /* Wine tests: */ 1796b8e80941Smrg if (compressed_format(surf->desc.Format)) { 1797b8e80941Smrg const unsigned bw = util_format_get_blockwidth(surf->base.info.format); 1798b8e80941Smrg const unsigned bh = util_format_get_blockheight(surf->base.info.format); 1799b8e80941Smrg 1800b8e80941Smrg user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh), 1801b8e80941Smrg D3DERR_INVALIDCALL); 1802b8e80941Smrg } 1803b8e80941Smrg } else{ 1804b8e80941Smrg x = 0; 1805b8e80941Smrg y = 0; 1806b8e80941Smrg w = surf->desc.Width; 1807b8e80941Smrg h = surf->desc.Height; 1808b8e80941Smrg } 1809b8e80941Smrg 1810b8e80941Smrg if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) { 1811b8e80941Smrg nine_context_clear_render_target(This, surf, color, x, y, w, h); 1812b8e80941Smrg } else { 1813b8e80941Smrg D3DLOCKED_RECT lock; 1814b8e80941Smrg union util_color uc; 1815b8e80941Smrg HRESULT hr; 1816b8e80941Smrg /* XXX: lock pRect and fix util_fill_rect */ 1817b8e80941Smrg hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD); 1818b8e80941Smrg if (FAILED(hr)) 1819b8e80941Smrg return hr; 1820b8e80941Smrg util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24, 1821b8e80941Smrg surf->base.info.format, &uc); 1822b8e80941Smrg util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch, 1823b8e80941Smrg x, y, w, h, &uc); 1824b8e80941Smrg NineSurface9_UnlockRect(surf); 1825b8e80941Smrg } 1826b8e80941Smrg 1827b8e80941Smrg return D3D_OK; 1828b8e80941Smrg} 1829b8e80941Smrg 1830b8e80941SmrgHRESULT NINE_WINAPI 1831b8e80941SmrgNineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, 1832b8e80941Smrg UINT Width, 1833b8e80941Smrg UINT Height, 1834b8e80941Smrg D3DFORMAT Format, 1835b8e80941Smrg D3DPOOL Pool, 1836b8e80941Smrg IDirect3DSurface9 **ppSurface, 1837b8e80941Smrg HANDLE *pSharedHandle ) 1838b8e80941Smrg{ 1839b8e80941Smrg HRESULT hr; 1840b8e80941Smrg 1841b8e80941Smrg DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u " 1842b8e80941Smrg "ppSurface=%p pSharedHandle=%p\n", This, 1843b8e80941Smrg Width, Height, d3dformat_to_string(Format), Format, Pool, 1844b8e80941Smrg ppSurface, pSharedHandle); 1845b8e80941Smrg 1846b8e80941Smrg *ppSurface = NULL; 1847b8e80941Smrg user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT 1848b8e80941Smrg || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1849b8e80941Smrg user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 1850b8e80941Smrg 1851b8e80941Smrg /* Can be used with StretchRect and ColorFill. It's also always lockable. 1852b8e80941Smrg */ 1853b8e80941Smrg hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height, 1854b8e80941Smrg Format, 1855b8e80941Smrg D3DMULTISAMPLE_NONE, 0, 1856b8e80941Smrg TRUE, 1857b8e80941Smrg ppSurface, pSharedHandle); 1858b8e80941Smrg if (FAILED(hr)) 1859b8e80941Smrg DBG("Failed to create surface.\n"); 1860b8e80941Smrg return hr; 1861b8e80941Smrg} 1862b8e80941Smrg 1863b8e80941SmrgHRESULT NINE_WINAPI 1864b8e80941SmrgNineDevice9_SetRenderTarget( struct NineDevice9 *This, 1865b8e80941Smrg DWORD RenderTargetIndex, 1866b8e80941Smrg IDirect3DSurface9 *pRenderTarget ) 1867b8e80941Smrg{ 1868b8e80941Smrg struct NineSurface9 *rt = NineSurface9(pRenderTarget); 1869b8e80941Smrg const unsigned i = RenderTargetIndex; 1870b8e80941Smrg 1871b8e80941Smrg DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This, 1872b8e80941Smrg RenderTargetIndex, pRenderTarget); 1873b8e80941Smrg 1874b8e80941Smrg user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 1875b8e80941Smrg user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL); 1876b8e80941Smrg user_assert(!pRenderTarget || 1877b8e80941Smrg rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL); 1878b8e80941Smrg 1879b8e80941Smrg if (i == 0) { 1880b8e80941Smrg This->state.viewport.X = 0; 1881b8e80941Smrg This->state.viewport.Y = 0; 1882b8e80941Smrg This->state.viewport.Width = rt->desc.Width; 1883b8e80941Smrg This->state.viewport.Height = rt->desc.Height; 1884b8e80941Smrg This->state.viewport.MinZ = 0.0f; 1885b8e80941Smrg This->state.viewport.MaxZ = 1.0f; 1886b8e80941Smrg 1887b8e80941Smrg This->state.scissor.minx = 0; 1888b8e80941Smrg This->state.scissor.miny = 0; 1889b8e80941Smrg This->state.scissor.maxx = rt->desc.Width; 1890b8e80941Smrg This->state.scissor.maxy = rt->desc.Height; 1891b8e80941Smrg } 1892b8e80941Smrg 1893b8e80941Smrg if (This->state.rt[i] != NineSurface9(pRenderTarget)) 1894b8e80941Smrg nine_bind(&This->state.rt[i], pRenderTarget); 1895b8e80941Smrg 1896b8e80941Smrg nine_context_set_render_target(This, i, rt); 1897b8e80941Smrg return D3D_OK; 1898b8e80941Smrg} 1899b8e80941Smrg 1900b8e80941SmrgHRESULT NINE_WINAPI 1901b8e80941SmrgNineDevice9_GetRenderTarget( struct NineDevice9 *This, 1902b8e80941Smrg DWORD RenderTargetIndex, 1903b8e80941Smrg IDirect3DSurface9 **ppRenderTarget ) 1904b8e80941Smrg{ 1905b8e80941Smrg const unsigned i = RenderTargetIndex; 1906b8e80941Smrg 1907b8e80941Smrg user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 1908b8e80941Smrg user_assert(ppRenderTarget, D3DERR_INVALIDCALL); 1909b8e80941Smrg 1910b8e80941Smrg *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i]; 1911b8e80941Smrg if (!This->state.rt[i]) 1912b8e80941Smrg return D3DERR_NOTFOUND; 1913b8e80941Smrg 1914b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->state.rt[i])); 1915b8e80941Smrg return D3D_OK; 1916b8e80941Smrg} 1917b8e80941Smrg 1918b8e80941SmrgHRESULT NINE_WINAPI 1919b8e80941SmrgNineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, 1920b8e80941Smrg IDirect3DSurface9 *pNewZStencil ) 1921b8e80941Smrg{ 1922b8e80941Smrg struct NineSurface9 *ds = NineSurface9(pNewZStencil); 1923b8e80941Smrg DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil); 1924b8e80941Smrg 1925b8e80941Smrg if (This->state.ds != ds) { 1926b8e80941Smrg nine_bind(&This->state.ds, ds); 1927b8e80941Smrg nine_context_set_depth_stencil(This, ds); 1928b8e80941Smrg } 1929b8e80941Smrg return D3D_OK; 1930b8e80941Smrg} 1931b8e80941Smrg 1932b8e80941SmrgHRESULT NINE_WINAPI 1933b8e80941SmrgNineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, 1934b8e80941Smrg IDirect3DSurface9 **ppZStencilSurface ) 1935b8e80941Smrg{ 1936b8e80941Smrg user_assert(ppZStencilSurface, D3DERR_INVALIDCALL); 1937b8e80941Smrg 1938b8e80941Smrg *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds; 1939b8e80941Smrg if (!This->state.ds) 1940b8e80941Smrg return D3DERR_NOTFOUND; 1941b8e80941Smrg 1942b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->state.ds)); 1943b8e80941Smrg return D3D_OK; 1944b8e80941Smrg} 1945b8e80941Smrg 1946b8e80941SmrgHRESULT NINE_WINAPI 1947b8e80941SmrgNineDevice9_BeginScene( struct NineDevice9 *This ) 1948b8e80941Smrg{ 1949b8e80941Smrg DBG("This=%p\n", This); 1950b8e80941Smrg user_assert(!This->in_scene, D3DERR_INVALIDCALL); 1951b8e80941Smrg This->in_scene = TRUE; 1952b8e80941Smrg /* Do we want to do anything else here ? */ 1953b8e80941Smrg return D3D_OK; 1954b8e80941Smrg} 1955b8e80941Smrg 1956b8e80941SmrgHRESULT NINE_WINAPI 1957b8e80941SmrgNineDevice9_EndScene( struct NineDevice9 *This ) 1958b8e80941Smrg{ 1959b8e80941Smrg DBG("This=%p\n", This); 1960b8e80941Smrg user_assert(This->in_scene, D3DERR_INVALIDCALL); 1961b8e80941Smrg This->in_scene = FALSE; 1962b8e80941Smrg return D3D_OK; 1963b8e80941Smrg} 1964b8e80941Smrg 1965b8e80941SmrgHRESULT NINE_WINAPI 1966b8e80941SmrgNineDevice9_Clear( struct NineDevice9 *This, 1967b8e80941Smrg DWORD Count, 1968b8e80941Smrg const D3DRECT *pRects, 1969b8e80941Smrg DWORD Flags, 1970b8e80941Smrg D3DCOLOR Color, 1971b8e80941Smrg float Z, 1972b8e80941Smrg DWORD Stencil ) 1973b8e80941Smrg{ 1974b8e80941Smrg struct NineSurface9 *zsbuf_surf = This->state.ds; 1975b8e80941Smrg 1976b8e80941Smrg DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", 1977b8e80941Smrg This, Count, pRects, Flags, Color, Z, Stencil); 1978b8e80941Smrg 1979b8e80941Smrg user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL), 1980b8e80941Smrg D3DERR_INVALIDCALL); 1981b8e80941Smrg user_assert(!(Flags & D3DCLEAR_STENCIL) || 1982b8e80941Smrg (zsbuf_surf && 1983b8e80941Smrg util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)), 1984b8e80941Smrg D3DERR_INVALIDCALL); 1985b8e80941Smrg#ifdef NINE_STRICT 1986b8e80941Smrg user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL); 1987b8e80941Smrg#else 1988b8e80941Smrg user_warn((pRects && !Count) || (!pRects && Count)); 1989b8e80941Smrg if (pRects && !Count) 1990b8e80941Smrg return D3D_OK; 1991b8e80941Smrg if (!pRects) 1992b8e80941Smrg Count = 0; 1993b8e80941Smrg#endif 1994b8e80941Smrg 1995b8e80941Smrg nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil); 1996b8e80941Smrg return D3D_OK; 1997b8e80941Smrg} 1998b8e80941Smrg 1999b8e80941Smrgstatic void 2000b8e80941Smrgnine_D3DMATRIX_print(const D3DMATRIX *M) 2001b8e80941Smrg{ 2002b8e80941Smrg DBG("\n(%f %f %f %f)\n" 2003b8e80941Smrg "(%f %f %f %f)\n" 2004b8e80941Smrg "(%f %f %f %f)\n" 2005b8e80941Smrg "(%f %f %f %f)\n", 2006b8e80941Smrg M->m[0][0], M->m[0][1], M->m[0][2], M->m[0][3], 2007b8e80941Smrg M->m[1][0], M->m[1][1], M->m[1][2], M->m[1][3], 2008b8e80941Smrg M->m[2][0], M->m[2][1], M->m[2][2], M->m[2][3], 2009b8e80941Smrg M->m[3][0], M->m[3][1], M->m[3][2], M->m[3][3]); 2010b8e80941Smrg} 2011b8e80941Smrg 2012b8e80941SmrgHRESULT NINE_WINAPI 2013b8e80941SmrgNineDevice9_SetTransform( struct NineDevice9 *This, 2014b8e80941Smrg D3DTRANSFORMSTATETYPE State, 2015b8e80941Smrg const D3DMATRIX *pMatrix ) 2016b8e80941Smrg{ 2017b8e80941Smrg struct nine_state *state = This->update; 2018b8e80941Smrg D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); 2019b8e80941Smrg 2020b8e80941Smrg DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 2021b8e80941Smrg 2022b8e80941Smrg user_assert(M, D3DERR_INVALIDCALL); 2023b8e80941Smrg nine_D3DMATRIX_print(pMatrix); 2024b8e80941Smrg 2025b8e80941Smrg *M = *pMatrix; 2026b8e80941Smrg if (unlikely(This->is_recording)) { 2027b8e80941Smrg state->ff.changed.transform[State / 32] |= 1 << (State % 32); 2028b8e80941Smrg state->changed.group |= NINE_STATE_FF_VSTRANSF; 2029b8e80941Smrg } else 2030b8e80941Smrg nine_context_set_transform(This, State, pMatrix); 2031b8e80941Smrg 2032b8e80941Smrg return D3D_OK; 2033b8e80941Smrg} 2034b8e80941Smrg 2035b8e80941SmrgHRESULT NINE_WINAPI 2036b8e80941SmrgNineDevice9_GetTransform( struct NineDevice9 *This, 2037b8e80941Smrg D3DTRANSFORMSTATETYPE State, 2038b8e80941Smrg D3DMATRIX *pMatrix ) 2039b8e80941Smrg{ 2040b8e80941Smrg D3DMATRIX *M = nine_state_access_transform(&This->state.ff, State, FALSE); 2041b8e80941Smrg user_assert(M, D3DERR_INVALIDCALL); 2042b8e80941Smrg *pMatrix = *M; 2043b8e80941Smrg return D3D_OK; 2044b8e80941Smrg} 2045b8e80941Smrg 2046b8e80941SmrgHRESULT NINE_WINAPI 2047b8e80941SmrgNineDevice9_MultiplyTransform( struct NineDevice9 *This, 2048b8e80941Smrg D3DTRANSFORMSTATETYPE State, 2049b8e80941Smrg const D3DMATRIX *pMatrix ) 2050b8e80941Smrg{ 2051b8e80941Smrg struct nine_state *state = This->update; 2052b8e80941Smrg D3DMATRIX T; 2053b8e80941Smrg D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE); 2054b8e80941Smrg 2055b8e80941Smrg DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 2056b8e80941Smrg 2057b8e80941Smrg user_assert(M, D3DERR_INVALIDCALL); 2058b8e80941Smrg 2059b8e80941Smrg nine_d3d_matrix_matrix_mul(&T, pMatrix, M); 2060b8e80941Smrg return NineDevice9_SetTransform(This, State, &T); 2061b8e80941Smrg} 2062b8e80941Smrg 2063b8e80941SmrgHRESULT NINE_WINAPI 2064b8e80941SmrgNineDevice9_SetViewport( struct NineDevice9 *This, 2065b8e80941Smrg const D3DVIEWPORT9 *pViewport ) 2066b8e80941Smrg{ 2067b8e80941Smrg struct nine_state *state = This->update; 2068b8e80941Smrg 2069b8e80941Smrg DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n", 2070b8e80941Smrg pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, 2071b8e80941Smrg pViewport->MinZ, pViewport->MaxZ); 2072b8e80941Smrg 2073b8e80941Smrg state->viewport = *pViewport; 2074b8e80941Smrg nine_context_set_viewport(This, pViewport); 2075b8e80941Smrg 2076b8e80941Smrg return D3D_OK; 2077b8e80941Smrg} 2078b8e80941Smrg 2079b8e80941SmrgHRESULT NINE_WINAPI 2080b8e80941SmrgNineDevice9_GetViewport( struct NineDevice9 *This, 2081b8e80941Smrg D3DVIEWPORT9 *pViewport ) 2082b8e80941Smrg{ 2083b8e80941Smrg *pViewport = This->state.viewport; 2084b8e80941Smrg return D3D_OK; 2085b8e80941Smrg} 2086b8e80941Smrg 2087b8e80941SmrgHRESULT NINE_WINAPI 2088b8e80941SmrgNineDevice9_SetMaterial( struct NineDevice9 *This, 2089b8e80941Smrg const D3DMATERIAL9 *pMaterial ) 2090b8e80941Smrg{ 2091b8e80941Smrg struct nine_state *state = This->update; 2092b8e80941Smrg 2093b8e80941Smrg DBG("This=%p pMaterial=%p\n", This, pMaterial); 2094b8e80941Smrg if (pMaterial) 2095b8e80941Smrg nine_dump_D3DMATERIAL9(DBG_FF, pMaterial); 2096b8e80941Smrg 2097b8e80941Smrg user_assert(pMaterial, E_POINTER); 2098b8e80941Smrg 2099b8e80941Smrg state->ff.material = *pMaterial; 2100b8e80941Smrg if (unlikely(This->is_recording)) 2101b8e80941Smrg state->changed.group |= NINE_STATE_FF_MATERIAL; 2102b8e80941Smrg else 2103b8e80941Smrg nine_context_set_material(This, pMaterial); 2104b8e80941Smrg 2105b8e80941Smrg return D3D_OK; 2106b8e80941Smrg} 2107b8e80941Smrg 2108b8e80941SmrgHRESULT NINE_WINAPI 2109b8e80941SmrgNineDevice9_GetMaterial( struct NineDevice9 *This, 2110b8e80941Smrg D3DMATERIAL9 *pMaterial ) 2111b8e80941Smrg{ 2112b8e80941Smrg user_assert(pMaterial, E_POINTER); 2113b8e80941Smrg *pMaterial = This->state.ff.material; 2114b8e80941Smrg return D3D_OK; 2115b8e80941Smrg} 2116b8e80941Smrg 2117b8e80941SmrgHRESULT NINE_WINAPI 2118b8e80941SmrgNineDevice9_SetLight( struct NineDevice9 *This, 2119b8e80941Smrg DWORD Index, 2120b8e80941Smrg const D3DLIGHT9 *pLight ) 2121b8e80941Smrg{ 2122b8e80941Smrg struct nine_state *state = This->update; 2123b8e80941Smrg HRESULT hr; 2124b8e80941Smrg 2125b8e80941Smrg DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight); 2126b8e80941Smrg if (pLight) 2127b8e80941Smrg nine_dump_D3DLIGHT9(DBG_FF, pLight); 2128b8e80941Smrg 2129b8e80941Smrg user_assert(pLight, D3DERR_INVALIDCALL); 2130b8e80941Smrg user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL); 2131b8e80941Smrg 2132b8e80941Smrg user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */ 2133b8e80941Smrg 2134b8e80941Smrg hr = nine_state_set_light(&state->ff, Index, pLight); 2135b8e80941Smrg if (hr != D3D_OK) 2136b8e80941Smrg return hr; 2137b8e80941Smrg 2138b8e80941Smrg if (pLight->Type != D3DLIGHT_DIRECTIONAL && 2139b8e80941Smrg pLight->Attenuation0 == 0.0f && 2140b8e80941Smrg pLight->Attenuation1 == 0.0f && 2141b8e80941Smrg pLight->Attenuation2 == 0.0f) { 2142b8e80941Smrg DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n"); 2143b8e80941Smrg } 2144b8e80941Smrg 2145b8e80941Smrg if (unlikely(This->is_recording)) 2146b8e80941Smrg state->changed.group |= NINE_STATE_FF_LIGHTING; 2147b8e80941Smrg else 2148b8e80941Smrg nine_context_set_light(This, Index, pLight); 2149b8e80941Smrg 2150b8e80941Smrg return D3D_OK; 2151b8e80941Smrg} 2152b8e80941Smrg 2153b8e80941SmrgHRESULT NINE_WINAPI 2154b8e80941SmrgNineDevice9_GetLight( struct NineDevice9 *This, 2155b8e80941Smrg DWORD Index, 2156b8e80941Smrg D3DLIGHT9 *pLight ) 2157b8e80941Smrg{ 2158b8e80941Smrg const struct nine_state *state = &This->state; 2159b8e80941Smrg 2160b8e80941Smrg user_assert(pLight, D3DERR_INVALIDCALL); 2161b8e80941Smrg user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 2162b8e80941Smrg user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 2163b8e80941Smrg D3DERR_INVALIDCALL); 2164b8e80941Smrg 2165b8e80941Smrg *pLight = state->ff.light[Index]; 2166b8e80941Smrg 2167b8e80941Smrg return D3D_OK; 2168b8e80941Smrg} 2169b8e80941Smrg 2170b8e80941SmrgHRESULT NINE_WINAPI 2171b8e80941SmrgNineDevice9_LightEnable( struct NineDevice9 *This, 2172b8e80941Smrg DWORD Index, 2173b8e80941Smrg BOOL Enable ) 2174b8e80941Smrg{ 2175b8e80941Smrg struct nine_state *state = This->update; 2176b8e80941Smrg 2177b8e80941Smrg DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable); 2178b8e80941Smrg 2179b8e80941Smrg if (Index >= state->ff.num_lights || 2180b8e80941Smrg state->ff.light[Index].Type == NINED3DLIGHT_INVALID) { 2181b8e80941Smrg /* This should create a default light. */ 2182b8e80941Smrg D3DLIGHT9 light; 2183b8e80941Smrg memset(&light, 0, sizeof(light)); 2184b8e80941Smrg light.Type = D3DLIGHT_DIRECTIONAL; 2185b8e80941Smrg light.Diffuse.r = 1.0f; 2186b8e80941Smrg light.Diffuse.g = 1.0f; 2187b8e80941Smrg light.Diffuse.b = 1.0f; 2188b8e80941Smrg light.Direction.z = 1.0f; 2189b8e80941Smrg NineDevice9_SetLight(This, Index, &light); 2190b8e80941Smrg } 2191b8e80941Smrg 2192b8e80941Smrg nine_state_light_enable(&state->ff, Index, Enable); 2193b8e80941Smrg if (likely(!This->is_recording)) 2194b8e80941Smrg nine_context_light_enable(This, Index, Enable); 2195b8e80941Smrg else 2196b8e80941Smrg state->changed.group |= NINE_STATE_FF_LIGHTING; 2197b8e80941Smrg 2198b8e80941Smrg return D3D_OK; 2199b8e80941Smrg} 2200b8e80941Smrg 2201b8e80941SmrgHRESULT NINE_WINAPI 2202b8e80941SmrgNineDevice9_GetLightEnable( struct NineDevice9 *This, 2203b8e80941Smrg DWORD Index, 2204b8e80941Smrg BOOL *pEnable ) 2205b8e80941Smrg{ 2206b8e80941Smrg const struct nine_state *state = &This->state; 2207b8e80941Smrg unsigned i; 2208b8e80941Smrg 2209b8e80941Smrg user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 2210b8e80941Smrg user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 2211b8e80941Smrg D3DERR_INVALIDCALL); 2212b8e80941Smrg 2213b8e80941Smrg for (i = 0; i < state->ff.num_lights_active; ++i) 2214b8e80941Smrg if (state->ff.active_light[i] == Index) 2215b8e80941Smrg break; 2216b8e80941Smrg 2217b8e80941Smrg *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine 2218b8e80941Smrg 2219b8e80941Smrg return D3D_OK; 2220b8e80941Smrg} 2221b8e80941Smrg 2222b8e80941SmrgHRESULT NINE_WINAPI 2223b8e80941SmrgNineDevice9_SetClipPlane( struct NineDevice9 *This, 2224b8e80941Smrg DWORD Index, 2225b8e80941Smrg const float *pPlane ) 2226b8e80941Smrg{ 2227b8e80941Smrg struct nine_state *state = This->update; 2228b8e80941Smrg 2229b8e80941Smrg user_assert(pPlane, D3DERR_INVALIDCALL); 2230b8e80941Smrg 2231b8e80941Smrg DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index, 2232b8e80941Smrg pPlane[0], pPlane[1], 2233b8e80941Smrg pPlane[2], pPlane[3]); 2234b8e80941Smrg 2235b8e80941Smrg user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 2236b8e80941Smrg 2237b8e80941Smrg memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0])); 2238b8e80941Smrg if (unlikely(This->is_recording)) 2239b8e80941Smrg state->changed.ucp |= 1 << Index; 2240b8e80941Smrg else 2241b8e80941Smrg nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane); 2242b8e80941Smrg 2243b8e80941Smrg return D3D_OK; 2244b8e80941Smrg} 2245b8e80941Smrg 2246b8e80941SmrgHRESULT NINE_WINAPI 2247b8e80941SmrgNineDevice9_GetClipPlane( struct NineDevice9 *This, 2248b8e80941Smrg DWORD Index, 2249b8e80941Smrg float *pPlane ) 2250b8e80941Smrg{ 2251b8e80941Smrg const struct nine_state *state = &This->state; 2252b8e80941Smrg 2253b8e80941Smrg user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 2254b8e80941Smrg 2255b8e80941Smrg memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0])); 2256b8e80941Smrg return D3D_OK; 2257b8e80941Smrg} 2258b8e80941Smrg 2259b8e80941SmrgHRESULT NINE_WINAPI 2260b8e80941SmrgNineDevice9_SetRenderState( struct NineDevice9 *This, 2261b8e80941Smrg D3DRENDERSTATETYPE State, 2262b8e80941Smrg DWORD Value ) 2263b8e80941Smrg{ 2264b8e80941Smrg struct nine_state *state = This->update; 2265b8e80941Smrg 2266b8e80941Smrg DBG("This=%p State=%u(%s) Value=%08x\n", This, 2267b8e80941Smrg State, nine_d3drs_to_string(State), Value); 2268b8e80941Smrg 2269b8e80941Smrg user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); 2270b8e80941Smrg 2271b8e80941Smrg if (unlikely(This->is_recording)) { 2272b8e80941Smrg state->rs_advertised[State] = Value; 2273b8e80941Smrg /* only need to record changed render states for stateblocks */ 2274b8e80941Smrg state->changed.rs[State / 32] |= 1 << (State % 32); 2275b8e80941Smrg return D3D_OK; 2276b8e80941Smrg } 2277b8e80941Smrg 2278b8e80941Smrg if (state->rs_advertised[State] == Value) 2279b8e80941Smrg return D3D_OK; 2280b8e80941Smrg 2281b8e80941Smrg state->rs_advertised[State] = Value; 2282b8e80941Smrg nine_context_set_render_state(This, State, Value); 2283b8e80941Smrg 2284b8e80941Smrg return D3D_OK; 2285b8e80941Smrg} 2286b8e80941Smrg 2287b8e80941SmrgHRESULT NINE_WINAPI 2288b8e80941SmrgNineDevice9_GetRenderState( struct NineDevice9 *This, 2289b8e80941Smrg D3DRENDERSTATETYPE State, 2290b8e80941Smrg DWORD *pValue ) 2291b8e80941Smrg{ 2292b8e80941Smrg user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL); 2293b8e80941Smrg 2294b8e80941Smrg *pValue = This->state.rs_advertised[State]; 2295b8e80941Smrg return D3D_OK; 2296b8e80941Smrg} 2297b8e80941Smrg 2298b8e80941SmrgHRESULT NINE_WINAPI 2299b8e80941SmrgNineDevice9_CreateStateBlock( struct NineDevice9 *This, 2300b8e80941Smrg D3DSTATEBLOCKTYPE Type, 2301b8e80941Smrg IDirect3DStateBlock9 **ppSB ) 2302b8e80941Smrg{ 2303b8e80941Smrg struct NineStateBlock9 *nsb; 2304b8e80941Smrg struct nine_state *dst; 2305b8e80941Smrg HRESULT hr; 2306b8e80941Smrg enum nine_stateblock_type type; 2307b8e80941Smrg unsigned s; 2308b8e80941Smrg 2309b8e80941Smrg DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB); 2310b8e80941Smrg 2311b8e80941Smrg user_assert(Type == D3DSBT_ALL || 2312b8e80941Smrg Type == D3DSBT_VERTEXSTATE || 2313b8e80941Smrg Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL); 2314b8e80941Smrg 2315b8e80941Smrg switch (Type) { 2316b8e80941Smrg case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break; 2317b8e80941Smrg case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break; 2318b8e80941Smrg default: 2319b8e80941Smrg type = NINESBT_ALL; 2320b8e80941Smrg break; 2321b8e80941Smrg } 2322b8e80941Smrg 2323b8e80941Smrg hr = NineStateBlock9_new(This, &nsb, type); 2324b8e80941Smrg if (FAILED(hr)) 2325b8e80941Smrg return hr; 2326b8e80941Smrg *ppSB = (IDirect3DStateBlock9 *)nsb; 2327b8e80941Smrg dst = &nsb->state; 2328b8e80941Smrg 2329b8e80941Smrg dst->changed.group = NINE_STATE_SAMPLER; 2330b8e80941Smrg 2331b8e80941Smrg if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) { 2332b8e80941Smrg dst->changed.group |= 2333b8e80941Smrg NINE_STATE_FF_LIGHTING | 2334b8e80941Smrg NINE_STATE_VS | NINE_STATE_VS_CONST | 2335b8e80941Smrg NINE_STATE_VDECL; 2336b8e80941Smrg /* TODO: texture/sampler state */ 2337b8e80941Smrg memcpy(dst->changed.rs, 2338b8e80941Smrg nine_render_states_vertex, sizeof(dst->changed.rs)); 2339b8e80941Smrg nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f, 2340b8e80941Smrg &This->range_pool); 2341b8e80941Smrg nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I, 2342b8e80941Smrg &This->range_pool); 2343b8e80941Smrg nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B, 2344b8e80941Smrg &This->range_pool); 2345b8e80941Smrg for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 2346b8e80941Smrg dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET; 2347b8e80941Smrg if (This->state.ff.num_lights) { 2348b8e80941Smrg dst->ff.num_lights = This->state.ff.num_lights; 2349b8e80941Smrg /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so 2350b8e80941Smrg * all currently existing lights will be captured 2351b8e80941Smrg */ 2352b8e80941Smrg dst->ff.light = CALLOC(This->state.ff.num_lights, 2353b8e80941Smrg sizeof(D3DLIGHT9)); 2354b8e80941Smrg if (!dst->ff.light) { 2355b8e80941Smrg nine_bind(ppSB, NULL); 2356b8e80941Smrg return E_OUTOFMEMORY; 2357b8e80941Smrg } 2358b8e80941Smrg } 2359b8e80941Smrg } 2360b8e80941Smrg if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) { 2361b8e80941Smrg dst->changed.group |= 2362b8e80941Smrg NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_FF_PS_CONSTS; 2363b8e80941Smrg memcpy(dst->changed.rs, 2364b8e80941Smrg nine_render_states_pixel, sizeof(dst->changed.rs)); 2365b8e80941Smrg nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f, 2366b8e80941Smrg &This->range_pool); 2367b8e80941Smrg dst->changed.ps_const_i = 0xffff; 2368b8e80941Smrg dst->changed.ps_const_b = 0xffff; 2369b8e80941Smrg for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 2370b8e80941Smrg dst->changed.sampler[s] |= 0x1ffe; 2371b8e80941Smrg for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) { 2372b8e80941Smrg dst->ff.changed.tex_stage[s][0] |= 0xffffffff; 2373b8e80941Smrg dst->ff.changed.tex_stage[s][1] |= 0xffffffff; 2374b8e80941Smrg } 2375b8e80941Smrg } 2376b8e80941Smrg if (Type == D3DSBT_ALL) { 2377b8e80941Smrg dst->changed.group |= 2378b8e80941Smrg NINE_STATE_VIEWPORT | 2379b8e80941Smrg NINE_STATE_SCISSOR | 2380b8e80941Smrg NINE_STATE_IDXBUF | 2381b8e80941Smrg NINE_STATE_FF_MATERIAL | 2382b8e80941Smrg NINE_STATE_FF_VSTRANSF; 2383b8e80941Smrg memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t)); 2384b8e80941Smrg dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1; 2385b8e80941Smrg dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; 2386b8e80941Smrg dst->changed.stream_freq = dst->changed.vtxbuf; 2387b8e80941Smrg dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; 2388b8e80941Smrg dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1; 2389b8e80941Smrg /* The doc says the projection, world, view and texture matrices 2390b8e80941Smrg * are saved, which would translate to: 2391b8e80941Smrg * dst->ff.changed.transform[0] = 0x00FF000C; 2392b8e80941Smrg * dst->ff.changed.transform[D3DTS_WORLD / 32] |= 1 << (D3DTS_WORLD % 32); 2393b8e80941Smrg * However we assume they meant save everything (which is basically just the 2394b8e80941Smrg * above plus the other world matrices). 2395b8e80941Smrg */ 2396b8e80941Smrg dst->ff.changed.transform[0] = 0x00FF000C; 2397b8e80941Smrg for (s = 0; s < 8; s++) 2398b8e80941Smrg dst->ff.changed.transform[8+s] = ~0; 2399b8e80941Smrg } 2400b8e80941Smrg NineStateBlock9_Capture(NineStateBlock9(*ppSB)); 2401b8e80941Smrg 2402b8e80941Smrg /* TODO: fixed function state */ 2403b8e80941Smrg 2404b8e80941Smrg return D3D_OK; 2405b8e80941Smrg} 2406b8e80941Smrg 2407b8e80941SmrgHRESULT NINE_WINAPI 2408b8e80941SmrgNineDevice9_BeginStateBlock( struct NineDevice9 *This ) 2409b8e80941Smrg{ 2410b8e80941Smrg HRESULT hr; 2411b8e80941Smrg 2412b8e80941Smrg DBG("This=%p\n", This); 2413b8e80941Smrg 2414b8e80941Smrg user_assert(!This->record, D3DERR_INVALIDCALL); 2415b8e80941Smrg 2416b8e80941Smrg hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM); 2417b8e80941Smrg if (FAILED(hr)) 2418b8e80941Smrg return hr; 2419b8e80941Smrg NineUnknown_ConvertRefToBind(NineUnknown(This->record)); 2420b8e80941Smrg 2421b8e80941Smrg This->update = &This->record->state; 2422b8e80941Smrg This->is_recording = TRUE; 2423b8e80941Smrg 2424b8e80941Smrg return D3D_OK; 2425b8e80941Smrg} 2426b8e80941Smrg 2427b8e80941SmrgHRESULT NINE_WINAPI 2428b8e80941SmrgNineDevice9_EndStateBlock( struct NineDevice9 *This, 2429b8e80941Smrg IDirect3DStateBlock9 **ppSB ) 2430b8e80941Smrg{ 2431b8e80941Smrg DBG("This=%p ppSB=%p\n", This, ppSB); 2432b8e80941Smrg 2433b8e80941Smrg user_assert(This->record, D3DERR_INVALIDCALL); 2434b8e80941Smrg 2435b8e80941Smrg This->update = &This->state; 2436b8e80941Smrg This->is_recording = FALSE; 2437b8e80941Smrg 2438b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->record)); 2439b8e80941Smrg *ppSB = (IDirect3DStateBlock9 *)This->record; 2440b8e80941Smrg NineUnknown_Unbind(NineUnknown(This->record)); 2441b8e80941Smrg This->record = NULL; 2442b8e80941Smrg 2443b8e80941Smrg return D3D_OK; 2444b8e80941Smrg} 2445b8e80941Smrg 2446b8e80941SmrgHRESULT NINE_WINAPI 2447b8e80941SmrgNineDevice9_SetClipStatus( struct NineDevice9 *This, 2448b8e80941Smrg const D3DCLIPSTATUS9 *pClipStatus ) 2449b8e80941Smrg{ 2450b8e80941Smrg STUB(D3DERR_INVALIDCALL); 2451b8e80941Smrg} 2452b8e80941Smrg 2453b8e80941SmrgHRESULT NINE_WINAPI 2454b8e80941SmrgNineDevice9_GetClipStatus( struct NineDevice9 *This, 2455b8e80941Smrg D3DCLIPSTATUS9 *pClipStatus ) 2456b8e80941Smrg{ 2457b8e80941Smrg STUB(D3DERR_INVALIDCALL); 2458b8e80941Smrg} 2459b8e80941Smrg 2460b8e80941SmrgHRESULT NINE_WINAPI 2461b8e80941SmrgNineDevice9_GetTexture( struct NineDevice9 *This, 2462b8e80941Smrg DWORD Stage, 2463b8e80941Smrg IDirect3DBaseTexture9 **ppTexture ) 2464b8e80941Smrg{ 2465b8e80941Smrg user_assert(Stage < NINE_MAX_SAMPLERS_PS || 2466b8e80941Smrg Stage == D3DDMAPSAMPLER || 2467b8e80941Smrg (Stage >= D3DVERTEXTEXTURESAMPLER0 && 2468b8e80941Smrg Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2469b8e80941Smrg user_assert(ppTexture, D3DERR_INVALIDCALL); 2470b8e80941Smrg 2471b8e80941Smrg if (Stage >= D3DDMAPSAMPLER) 2472b8e80941Smrg Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2473b8e80941Smrg 2474b8e80941Smrg *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage]; 2475b8e80941Smrg 2476b8e80941Smrg if (This->state.texture[Stage]) 2477b8e80941Smrg NineUnknown_AddRef(NineUnknown(This->state.texture[Stage])); 2478b8e80941Smrg return D3D_OK; 2479b8e80941Smrg} 2480b8e80941Smrg 2481b8e80941SmrgHRESULT NINE_WINAPI 2482b8e80941SmrgNineDevice9_SetTexture( struct NineDevice9 *This, 2483b8e80941Smrg DWORD Stage, 2484b8e80941Smrg IDirect3DBaseTexture9 *pTexture ) 2485b8e80941Smrg{ 2486b8e80941Smrg struct nine_state *state = This->update; 2487b8e80941Smrg struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture); 2488b8e80941Smrg struct NineBaseTexture9 *old; 2489b8e80941Smrg 2490b8e80941Smrg DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture); 2491b8e80941Smrg 2492b8e80941Smrg user_assert(Stage < NINE_MAX_SAMPLERS_PS || 2493b8e80941Smrg Stage == D3DDMAPSAMPLER || 2494b8e80941Smrg (Stage >= D3DVERTEXTEXTURESAMPLER0 && 2495b8e80941Smrg Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2496b8e80941Smrg user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH && 2497b8e80941Smrg tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL); 2498b8e80941Smrg 2499b8e80941Smrg if (Stage >= D3DDMAPSAMPLER) 2500b8e80941Smrg Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2501b8e80941Smrg 2502b8e80941Smrg if (This->is_recording) { 2503b8e80941Smrg state->changed.texture |= 1 << Stage; 2504b8e80941Smrg nine_bind(&state->texture[Stage], pTexture); 2505b8e80941Smrg return D3D_OK; 2506b8e80941Smrg } 2507b8e80941Smrg 2508b8e80941Smrg old = state->texture[Stage]; 2509b8e80941Smrg if (old == tex) 2510b8e80941Smrg return D3D_OK; 2511b8e80941Smrg 2512b8e80941Smrg NineBindTextureToDevice(This, &state->texture[Stage], tex); 2513b8e80941Smrg 2514b8e80941Smrg nine_context_set_texture(This, Stage, tex); 2515b8e80941Smrg 2516b8e80941Smrg return D3D_OK; 2517b8e80941Smrg} 2518b8e80941Smrg 2519b8e80941SmrgHRESULT NINE_WINAPI 2520b8e80941SmrgNineDevice9_GetTextureStageState( struct NineDevice9 *This, 2521b8e80941Smrg DWORD Stage, 2522b8e80941Smrg D3DTEXTURESTAGESTATETYPE Type, 2523b8e80941Smrg DWORD *pValue ) 2524b8e80941Smrg{ 2525b8e80941Smrg const struct nine_state *state = &This->state; 2526b8e80941Smrg 2527b8e80941Smrg user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); 2528b8e80941Smrg user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 2529b8e80941Smrg 2530b8e80941Smrg *pValue = state->ff.tex_stage[Stage][Type]; 2531b8e80941Smrg 2532b8e80941Smrg return D3D_OK; 2533b8e80941Smrg} 2534b8e80941Smrg 2535b8e80941SmrgHRESULT NINE_WINAPI 2536b8e80941SmrgNineDevice9_SetTextureStageState( struct NineDevice9 *This, 2537b8e80941Smrg DWORD Stage, 2538b8e80941Smrg D3DTEXTURESTAGESTATETYPE Type, 2539b8e80941Smrg DWORD Value ) 2540b8e80941Smrg{ 2541b8e80941Smrg struct nine_state *state = This->update; 2542b8e80941Smrg 2543b8e80941Smrg DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value); 2544b8e80941Smrg nine_dump_D3DTSS_value(DBG_FF, Type, Value); 2545b8e80941Smrg 2546b8e80941Smrg user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL); 2547b8e80941Smrg user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 2548b8e80941Smrg 2549b8e80941Smrg state->ff.tex_stage[Stage][Type] = Value; 2550b8e80941Smrg 2551b8e80941Smrg if (unlikely(This->is_recording)) { 2552b8e80941Smrg state->changed.group |= NINE_STATE_FF_PS_CONSTS; 2553b8e80941Smrg state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); 2554b8e80941Smrg } else 2555b8e80941Smrg nine_context_set_texture_stage_state(This, Stage, Type, Value); 2556b8e80941Smrg 2557b8e80941Smrg return D3D_OK; 2558b8e80941Smrg} 2559b8e80941Smrg 2560b8e80941SmrgHRESULT NINE_WINAPI 2561b8e80941SmrgNineDevice9_GetSamplerState( struct NineDevice9 *This, 2562b8e80941Smrg DWORD Sampler, 2563b8e80941Smrg D3DSAMPLERSTATETYPE Type, 2564b8e80941Smrg DWORD *pValue ) 2565b8e80941Smrg{ 2566b8e80941Smrg user_assert(Sampler < NINE_MAX_SAMPLERS_PS || 2567b8e80941Smrg Sampler == D3DDMAPSAMPLER || 2568b8e80941Smrg (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 2569b8e80941Smrg Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2570b8e80941Smrg 2571b8e80941Smrg if (Sampler >= D3DDMAPSAMPLER) 2572b8e80941Smrg Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2573b8e80941Smrg 2574b8e80941Smrg *pValue = This->state.samp_advertised[Sampler][Type]; 2575b8e80941Smrg return D3D_OK; 2576b8e80941Smrg} 2577b8e80941Smrg 2578b8e80941SmrgHRESULT NINE_WINAPI 2579b8e80941SmrgNineDevice9_SetSamplerState( struct NineDevice9 *This, 2580b8e80941Smrg DWORD Sampler, 2581b8e80941Smrg D3DSAMPLERSTATETYPE Type, 2582b8e80941Smrg DWORD Value ) 2583b8e80941Smrg{ 2584b8e80941Smrg struct nine_state *state = This->update; 2585b8e80941Smrg 2586b8e80941Smrg DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This, 2587b8e80941Smrg Sampler, nine_D3DSAMP_to_str(Type), Value); 2588b8e80941Smrg 2589b8e80941Smrg user_assert(Sampler < NINE_MAX_SAMPLERS_PS || 2590b8e80941Smrg Sampler == D3DDMAPSAMPLER || 2591b8e80941Smrg (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 2592b8e80941Smrg Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2593b8e80941Smrg 2594b8e80941Smrg if (Sampler >= D3DDMAPSAMPLER) 2595b8e80941Smrg Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2596b8e80941Smrg 2597b8e80941Smrg if (unlikely(This->is_recording)) { 2598b8e80941Smrg state->samp_advertised[Sampler][Type] = Value; 2599b8e80941Smrg state->changed.group |= NINE_STATE_SAMPLER; 2600b8e80941Smrg state->changed.sampler[Sampler] |= 1 << Type; 2601b8e80941Smrg return D3D_OK; 2602b8e80941Smrg } 2603b8e80941Smrg 2604b8e80941Smrg if (state->samp_advertised[Sampler][Type] == Value) 2605b8e80941Smrg return D3D_OK; 2606b8e80941Smrg 2607b8e80941Smrg state->samp_advertised[Sampler][Type] = Value; 2608b8e80941Smrg nine_context_set_sampler_state(This, Sampler, Type, Value); 2609b8e80941Smrg 2610b8e80941Smrg return D3D_OK; 2611b8e80941Smrg} 2612b8e80941Smrg 2613b8e80941SmrgHRESULT NINE_WINAPI 2614b8e80941SmrgNineDevice9_ValidateDevice( struct NineDevice9 *This, 2615b8e80941Smrg DWORD *pNumPasses ) 2616b8e80941Smrg{ 2617b8e80941Smrg const struct nine_state *state = &This->state; 2618b8e80941Smrg unsigned i; 2619b8e80941Smrg unsigned w = 0, h = 0; 2620b8e80941Smrg 2621b8e80941Smrg DBG("This=%p pNumPasses=%p\n", This, pNumPasses); 2622b8e80941Smrg 2623b8e80941Smrg for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) { 2624b8e80941Smrg if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE || 2625b8e80941Smrg state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE) 2626b8e80941Smrg return D3DERR_UNSUPPORTEDTEXTUREFILTER; 2627b8e80941Smrg } 2628b8e80941Smrg 2629b8e80941Smrg for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { 2630b8e80941Smrg if (!state->rt[i]) 2631b8e80941Smrg continue; 2632b8e80941Smrg if (w == 0) { 2633b8e80941Smrg w = state->rt[i]->desc.Width; 2634b8e80941Smrg h = state->rt[i]->desc.Height; 2635b8e80941Smrg } else 2636b8e80941Smrg if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) { 2637b8e80941Smrg return D3DERR_CONFLICTINGRENDERSTATE; 2638b8e80941Smrg } 2639b8e80941Smrg } 2640b8e80941Smrg if (state->ds && 2641b8e80941Smrg (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) { 2642b8e80941Smrg if (w != 0 && 2643b8e80941Smrg (state->ds->desc.Width != w || state->ds->desc.Height != h)) 2644b8e80941Smrg return D3DERR_CONFLICTINGRENDERSTATE; 2645b8e80941Smrg } 2646b8e80941Smrg 2647b8e80941Smrg if (pNumPasses) 2648b8e80941Smrg *pNumPasses = 1; 2649b8e80941Smrg 2650b8e80941Smrg return D3D_OK; 2651b8e80941Smrg} 2652b8e80941Smrg 2653b8e80941SmrgHRESULT NINE_WINAPI 2654b8e80941SmrgNineDevice9_SetPaletteEntries( struct NineDevice9 *This, 2655b8e80941Smrg UINT PaletteNumber, 2656b8e80941Smrg const PALETTEENTRY *pEntries ) 2657b8e80941Smrg{ 2658b8e80941Smrg STUB(D3D_OK); /* like wine */ 2659b8e80941Smrg} 2660b8e80941Smrg 2661b8e80941SmrgHRESULT NINE_WINAPI 2662b8e80941SmrgNineDevice9_GetPaletteEntries( struct NineDevice9 *This, 2663b8e80941Smrg UINT PaletteNumber, 2664b8e80941Smrg PALETTEENTRY *pEntries ) 2665b8e80941Smrg{ 2666b8e80941Smrg STUB(D3DERR_INVALIDCALL); 2667b8e80941Smrg} 2668b8e80941Smrg 2669b8e80941SmrgHRESULT NINE_WINAPI 2670b8e80941SmrgNineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, 2671b8e80941Smrg UINT PaletteNumber ) 2672b8e80941Smrg{ 2673b8e80941Smrg STUB(D3D_OK); /* like wine */ 2674b8e80941Smrg} 2675b8e80941Smrg 2676b8e80941SmrgHRESULT NINE_WINAPI 2677b8e80941SmrgNineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, 2678b8e80941Smrg UINT *PaletteNumber ) 2679b8e80941Smrg{ 2680b8e80941Smrg STUB(D3DERR_INVALIDCALL); 2681b8e80941Smrg} 2682b8e80941Smrg 2683b8e80941SmrgHRESULT NINE_WINAPI 2684b8e80941SmrgNineDevice9_SetScissorRect( struct NineDevice9 *This, 2685b8e80941Smrg const RECT *pRect ) 2686b8e80941Smrg{ 2687b8e80941Smrg struct nine_state *state = This->update; 2688b8e80941Smrg 2689b8e80941Smrg DBG("x=(%u..%u) y=(%u..%u)\n", 2690b8e80941Smrg pRect->left, pRect->top, pRect->right, pRect->bottom); 2691b8e80941Smrg 2692b8e80941Smrg state->scissor.minx = pRect->left; 2693b8e80941Smrg state->scissor.miny = pRect->top; 2694b8e80941Smrg state->scissor.maxx = pRect->right; 2695b8e80941Smrg state->scissor.maxy = pRect->bottom; 2696b8e80941Smrg 2697b8e80941Smrg if (unlikely(This->is_recording)) 2698b8e80941Smrg state->changed.group |= NINE_STATE_SCISSOR; 2699b8e80941Smrg else 2700b8e80941Smrg nine_context_set_scissor(This, &state->scissor); 2701b8e80941Smrg 2702b8e80941Smrg return D3D_OK; 2703b8e80941Smrg} 2704b8e80941Smrg 2705b8e80941SmrgHRESULT NINE_WINAPI 2706b8e80941SmrgNineDevice9_GetScissorRect( struct NineDevice9 *This, 2707b8e80941Smrg RECT *pRect ) 2708b8e80941Smrg{ 2709b8e80941Smrg pRect->left = This->state.scissor.minx; 2710b8e80941Smrg pRect->top = This->state.scissor.miny; 2711b8e80941Smrg pRect->right = This->state.scissor.maxx; 2712b8e80941Smrg pRect->bottom = This->state.scissor.maxy; 2713b8e80941Smrg 2714b8e80941Smrg return D3D_OK; 2715b8e80941Smrg} 2716b8e80941Smrg 2717b8e80941SmrgHRESULT NINE_WINAPI 2718b8e80941SmrgNineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, 2719b8e80941Smrg BOOL bSoftware ) 2720b8e80941Smrg{ 2721b8e80941Smrg if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) { 2722b8e80941Smrg This->swvp = bSoftware; 2723b8e80941Smrg nine_context_set_swvp(This, bSoftware); 2724b8e80941Smrg return D3D_OK; 2725b8e80941Smrg } else 2726b8e80941Smrg return D3D_OK; /* msdn seems to indicate INVALIDCALL, but at least Halo expects OK */ 2727b8e80941Smrg} 2728b8e80941Smrg 2729b8e80941SmrgBOOL NINE_WINAPI 2730b8e80941SmrgNineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) 2731b8e80941Smrg{ 2732b8e80941Smrg return This->swvp; 2733b8e80941Smrg} 2734b8e80941Smrg 2735b8e80941SmrgHRESULT NINE_WINAPI 2736b8e80941SmrgNineDevice9_SetNPatchMode( struct NineDevice9 *This, 2737b8e80941Smrg float nSegments ) 2738b8e80941Smrg{ 2739b8e80941Smrg return D3D_OK; /* Nothing to do because we don't advertise NPatch support */ 2740b8e80941Smrg} 2741b8e80941Smrg 2742b8e80941Smrgfloat NINE_WINAPI 2743b8e80941SmrgNineDevice9_GetNPatchMode( struct NineDevice9 *This ) 2744b8e80941Smrg{ 2745b8e80941Smrg STUB(0); 2746b8e80941Smrg} 2747b8e80941Smrg 2748b8e80941Smrg/* TODO: only go through dirty textures */ 2749b8e80941Smrgstatic void 2750b8e80941Smrgvalidate_textures(struct NineDevice9 *device) 2751b8e80941Smrg{ 2752b8e80941Smrg struct NineBaseTexture9 *tex, *ptr; 2753b8e80941Smrg LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) { 2754b8e80941Smrg list_delinit(&tex->list); 2755b8e80941Smrg NineBaseTexture9_Validate(tex); 2756b8e80941Smrg } 2757b8e80941Smrg} 2758b8e80941Smrg 2759b8e80941Smrgstatic void 2760b8e80941Smrgupdate_managed_buffers(struct NineDevice9 *device) 2761b8e80941Smrg{ 2762b8e80941Smrg struct NineBuffer9 *buf, *ptr; 2763b8e80941Smrg LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) { 2764b8e80941Smrg list_delinit(&buf->managed.list); 2765b8e80941Smrg NineBuffer9_Upload(buf); 2766b8e80941Smrg } 2767b8e80941Smrg} 2768b8e80941Smrg 2769b8e80941Smrgstatic void 2770b8e80941SmrgNineBeforeDraw( struct NineDevice9 *This ) 2771b8e80941Smrg{ 2772b8e80941Smrg /* Upload Managed dirty content */ 2773b8e80941Smrg validate_textures(This); /* may clobber state */ 2774b8e80941Smrg update_managed_buffers(This); 2775b8e80941Smrg} 2776b8e80941Smrg 2777b8e80941Smrgstatic void 2778b8e80941SmrgNineAfterDraw( struct NineDevice9 *This ) 2779b8e80941Smrg{ 2780b8e80941Smrg unsigned i; 2781b8e80941Smrg struct nine_state *state = &This->state; 2782b8e80941Smrg unsigned ps_mask = state->ps ? state->ps->rt_mask : 1; 2783b8e80941Smrg 2784b8e80941Smrg /* Flag render-targets with autogenmipmap for mipmap regeneration */ 2785b8e80941Smrg for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { 2786b8e80941Smrg struct NineSurface9 *rt = state->rt[i]; 2787b8e80941Smrg 2788b8e80941Smrg if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) && 2789b8e80941Smrg rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) { 2790b8e80941Smrg assert(rt->texture == D3DRTYPE_TEXTURE || 2791b8e80941Smrg rt->texture == D3DRTYPE_CUBETEXTURE); 2792b8e80941Smrg NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE; 2793b8e80941Smrg } 2794b8e80941Smrg } 2795b8e80941Smrg} 2796b8e80941Smrg 2797b8e80941SmrgHRESULT NINE_WINAPI 2798b8e80941SmrgNineDevice9_DrawPrimitive( struct NineDevice9 *This, 2799b8e80941Smrg D3DPRIMITIVETYPE PrimitiveType, 2800b8e80941Smrg UINT StartVertex, 2801b8e80941Smrg UINT PrimitiveCount ) 2802b8e80941Smrg{ 2803b8e80941Smrg DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n", 2804b8e80941Smrg This, PrimitiveType, StartVertex, PrimitiveCount); 2805b8e80941Smrg 2806b8e80941Smrg NineBeforeDraw(This); 2807b8e80941Smrg nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount); 2808b8e80941Smrg NineAfterDraw(This); 2809b8e80941Smrg 2810b8e80941Smrg return D3D_OK; 2811b8e80941Smrg} 2812b8e80941Smrg 2813b8e80941SmrgHRESULT NINE_WINAPI 2814b8e80941SmrgNineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, 2815b8e80941Smrg D3DPRIMITIVETYPE PrimitiveType, 2816b8e80941Smrg INT BaseVertexIndex, 2817b8e80941Smrg UINT MinVertexIndex, 2818b8e80941Smrg UINT NumVertices, 2819b8e80941Smrg UINT StartIndex, 2820b8e80941Smrg UINT PrimitiveCount ) 2821b8e80941Smrg{ 2822b8e80941Smrg DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u " 2823b8e80941Smrg "NumVertices %u, StartIndex %u, PrimitiveCount %u\n", 2824b8e80941Smrg This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, 2825b8e80941Smrg StartIndex, PrimitiveCount); 2826b8e80941Smrg 2827b8e80941Smrg user_assert(This->state.idxbuf, D3DERR_INVALIDCALL); 2828b8e80941Smrg user_assert(This->state.vdecl, D3DERR_INVALIDCALL); 2829b8e80941Smrg 2830b8e80941Smrg NineBeforeDraw(This); 2831b8e80941Smrg nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex, 2832b8e80941Smrg MinVertexIndex, NumVertices, StartIndex, 2833b8e80941Smrg PrimitiveCount); 2834b8e80941Smrg NineAfterDraw(This); 2835b8e80941Smrg 2836b8e80941Smrg return D3D_OK; 2837b8e80941Smrg} 2838b8e80941Smrg 2839b8e80941SmrgHRESULT NINE_WINAPI 2840b8e80941SmrgNineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, 2841b8e80941Smrg D3DPRIMITIVETYPE PrimitiveType, 2842b8e80941Smrg UINT PrimitiveCount, 2843b8e80941Smrg const void *pVertexStreamZeroData, 2844b8e80941Smrg UINT VertexStreamZeroStride ) 2845b8e80941Smrg{ 2846b8e80941Smrg struct pipe_vertex_buffer vtxbuf; 2847b8e80941Smrg 2848b8e80941Smrg DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n", 2849b8e80941Smrg This, PrimitiveType, PrimitiveCount, 2850b8e80941Smrg pVertexStreamZeroData, VertexStreamZeroStride); 2851b8e80941Smrg 2852b8e80941Smrg user_assert(pVertexStreamZeroData && VertexStreamZeroStride, 2853b8e80941Smrg D3DERR_INVALIDCALL); 2854b8e80941Smrg user_assert(PrimitiveCount, D3D_OK); 2855b8e80941Smrg 2856b8e80941Smrg vtxbuf.stride = VertexStreamZeroStride; 2857b8e80941Smrg vtxbuf.buffer_offset = 0; 2858b8e80941Smrg vtxbuf.is_user_buffer = true; 2859b8e80941Smrg vtxbuf.buffer.user = pVertexStreamZeroData; 2860b8e80941Smrg 2861b8e80941Smrg if (!This->driver_caps.user_vbufs) { 2862b8e80941Smrg vtxbuf.is_user_buffer = false; 2863b8e80941Smrg vtxbuf.buffer.resource = NULL; 2864b8e80941Smrg u_upload_data(This->vertex_uploader, 2865b8e80941Smrg 0, 2866b8e80941Smrg (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */ 2867b8e80941Smrg 4, 2868b8e80941Smrg pVertexStreamZeroData, 2869b8e80941Smrg &vtxbuf.buffer_offset, 2870b8e80941Smrg &vtxbuf.buffer.resource); 2871b8e80941Smrg u_upload_unmap(This->vertex_uploader); 2872b8e80941Smrg } 2873b8e80941Smrg 2874b8e80941Smrg NineBeforeDraw(This); 2875b8e80941Smrg nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf); 2876b8e80941Smrg NineAfterDraw(This); 2877b8e80941Smrg 2878b8e80941Smrg pipe_vertex_buffer_unreference(&vtxbuf); 2879b8e80941Smrg 2880b8e80941Smrg NineDevice9_PauseRecording(This); 2881b8e80941Smrg NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); 2882b8e80941Smrg NineDevice9_ResumeRecording(This); 2883b8e80941Smrg 2884b8e80941Smrg return D3D_OK; 2885b8e80941Smrg} 2886b8e80941Smrg 2887b8e80941SmrgHRESULT NINE_WINAPI 2888b8e80941SmrgNineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, 2889b8e80941Smrg D3DPRIMITIVETYPE PrimitiveType, 2890b8e80941Smrg UINT MinVertexIndex, 2891b8e80941Smrg UINT NumVertices, 2892b8e80941Smrg UINT PrimitiveCount, 2893b8e80941Smrg const void *pIndexData, 2894b8e80941Smrg D3DFORMAT IndexDataFormat, 2895b8e80941Smrg const void *pVertexStreamZeroData, 2896b8e80941Smrg UINT VertexStreamZeroStride ) 2897b8e80941Smrg{ 2898b8e80941Smrg struct pipe_vertex_buffer vbuf; 2899b8e80941Smrg 2900b8e80941Smrg DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u " 2901b8e80941Smrg "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u " 2902b8e80941Smrg "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n", 2903b8e80941Smrg This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, 2904b8e80941Smrg pIndexData, IndexDataFormat, 2905b8e80941Smrg pVertexStreamZeroData, VertexStreamZeroStride); 2906b8e80941Smrg 2907b8e80941Smrg user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL); 2908b8e80941Smrg user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL); 2909b8e80941Smrg user_assert(IndexDataFormat == D3DFMT_INDEX16 || 2910b8e80941Smrg IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL); 2911b8e80941Smrg user_assert(PrimitiveCount, D3D_OK); 2912b8e80941Smrg 2913b8e80941Smrg vbuf.stride = VertexStreamZeroStride; 2914b8e80941Smrg vbuf.buffer_offset = 0; 2915b8e80941Smrg vbuf.is_user_buffer = true; 2916b8e80941Smrg vbuf.buffer.user = pVertexStreamZeroData; 2917b8e80941Smrg 2918b8e80941Smrg unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4; 2919b8e80941Smrg struct pipe_resource *ibuf = NULL; 2920b8e80941Smrg 2921b8e80941Smrg if (!This->driver_caps.user_vbufs) { 2922b8e80941Smrg const unsigned base = MinVertexIndex * VertexStreamZeroStride; 2923b8e80941Smrg vbuf.is_user_buffer = false; 2924b8e80941Smrg vbuf.buffer.resource = NULL; 2925b8e80941Smrg u_upload_data(This->vertex_uploader, 2926b8e80941Smrg base, 2927b8e80941Smrg NumVertices * VertexStreamZeroStride, /* XXX */ 2928b8e80941Smrg 4, 2929b8e80941Smrg (const uint8_t *)pVertexStreamZeroData + base, 2930b8e80941Smrg &vbuf.buffer_offset, 2931b8e80941Smrg &vbuf.buffer.resource); 2932b8e80941Smrg u_upload_unmap(This->vertex_uploader); 2933b8e80941Smrg /* Won't be used: */ 2934b8e80941Smrg vbuf.buffer_offset -= base; 2935b8e80941Smrg } 2936b8e80941Smrg 2937b8e80941Smrg unsigned index_offset = 0; 2938b8e80941Smrg if (This->csmt_active) { 2939b8e80941Smrg u_upload_data(This->pipe_secondary->stream_uploader, 2940b8e80941Smrg 0, 2941b8e80941Smrg (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size, 2942b8e80941Smrg 4, 2943b8e80941Smrg pIndexData, 2944b8e80941Smrg &index_offset, 2945b8e80941Smrg &ibuf); 2946b8e80941Smrg u_upload_unmap(This->pipe_secondary->stream_uploader); 2947b8e80941Smrg } 2948b8e80941Smrg 2949b8e80941Smrg NineBeforeDraw(This); 2950b8e80941Smrg nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType, 2951b8e80941Smrg MinVertexIndex, 2952b8e80941Smrg NumVertices, 2953b8e80941Smrg PrimitiveCount, 2954b8e80941Smrg &vbuf, 2955b8e80941Smrg ibuf, 2956b8e80941Smrg ibuf ? NULL : (void*)pIndexData, 2957b8e80941Smrg index_offset, 2958b8e80941Smrg index_size); 2959b8e80941Smrg NineAfterDraw(This); 2960b8e80941Smrg 2961b8e80941Smrg pipe_vertex_buffer_unreference(&vbuf); 2962b8e80941Smrg pipe_resource_reference(&ibuf, NULL); 2963b8e80941Smrg 2964b8e80941Smrg NineDevice9_PauseRecording(This); 2965b8e80941Smrg NineDevice9_SetIndices(This, NULL); 2966b8e80941Smrg NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); 2967b8e80941Smrg NineDevice9_ResumeRecording(This); 2968b8e80941Smrg 2969b8e80941Smrg return D3D_OK; 2970b8e80941Smrg} 2971b8e80941Smrg 2972b8e80941SmrgHRESULT NINE_WINAPI 2973b8e80941SmrgNineDevice9_ProcessVertices( struct NineDevice9 *This, 2974b8e80941Smrg UINT SrcStartIndex, 2975b8e80941Smrg UINT DestIndex, 2976b8e80941Smrg UINT VertexCount, 2977b8e80941Smrg IDirect3DVertexBuffer9 *pDestBuffer, 2978b8e80941Smrg IDirect3DVertexDeclaration9 *pVertexDecl, 2979b8e80941Smrg DWORD Flags ) 2980b8e80941Smrg{ 2981b8e80941Smrg struct pipe_screen *screen_sw = This->screen_sw; 2982b8e80941Smrg struct pipe_context *pipe_sw = This->pipe_sw; 2983b8e80941Smrg struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl); 2984b8e80941Smrg struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer); 2985b8e80941Smrg struct NineVertexShader9 *vs; 2986b8e80941Smrg struct pipe_resource *resource; 2987b8e80941Smrg struct pipe_transfer *transfer = NULL; 2988b8e80941Smrg struct pipe_stream_output_info so; 2989b8e80941Smrg struct pipe_stream_output_target *target; 2990b8e80941Smrg struct pipe_draw_info draw; 2991b8e80941Smrg struct pipe_box box; 2992b8e80941Smrg bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t); 2993b8e80941Smrg unsigned offsets[1] = {0}; 2994b8e80941Smrg HRESULT hr; 2995b8e80941Smrg unsigned buffer_size; 2996b8e80941Smrg void *map; 2997b8e80941Smrg 2998b8e80941Smrg DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u " 2999b8e80941Smrg "pDestBuffer=%p pVertexDecl=%p Flags=%d\n", 3000b8e80941Smrg This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, 3001b8e80941Smrg pVertexDecl, Flags); 3002b8e80941Smrg 3003b8e80941Smrg if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) { 3004b8e80941Smrg DBG("ProcessVertices not supported\n"); 3005b8e80941Smrg return D3DERR_INVALIDCALL; 3006b8e80941Smrg } 3007b8e80941Smrg 3008b8e80941Smrg 3009b8e80941Smrg vs = programmable_vs ? This->state.vs : This->ff.vs; 3010b8e80941Smrg /* Note: version is 0 for ff */ 3011b8e80941Smrg user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF), 3012b8e80941Smrg D3DERR_INVALIDCALL); 3013b8e80941Smrg if (!vdecl) { 3014b8e80941Smrg DWORD FVF = dst->desc.FVF; 3015b8e80941Smrg vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); 3016b8e80941Smrg if (!vdecl) { 3017b8e80941Smrg hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); 3018b8e80941Smrg if (FAILED(hr)) 3019b8e80941Smrg return hr; 3020b8e80941Smrg vdecl->fvf = FVF; 3021b8e80941Smrg util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl); 3022b8e80941Smrg NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); 3023b8e80941Smrg } 3024b8e80941Smrg } 3025b8e80941Smrg 3026b8e80941Smrg /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags 3027b8e80941Smrg * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular 3028b8e80941Smrg * if not set, everything from src will be used, and dst 3029b8e80941Smrg * must match exactly the ff vs outputs. 3030b8e80941Smrg * TODO: Handle all the checks, etc for ff */ 3031b8e80941Smrg user_assert(vdecl->position_t || programmable_vs, 3032b8e80941Smrg D3DERR_INVALIDCALL); 3033b8e80941Smrg 3034b8e80941Smrg /* TODO: Support vs < 3 and ff */ 3035b8e80941Smrg user_assert(vs->byte_code.version == 0x30, 3036b8e80941Smrg D3DERR_INVALIDCALL); 3037b8e80941Smrg /* TODO: Not hardcode the constant buffers for swvp */ 3038b8e80941Smrg user_assert(This->may_swvp, 3039b8e80941Smrg D3DERR_INVALIDCALL); 3040b8e80941Smrg 3041b8e80941Smrg nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so); 3042b8e80941Smrg 3043b8e80941Smrg buffer_size = VertexCount * so.stride[0] * 4; 3044b8e80941Smrg { 3045b8e80941Smrg struct pipe_resource templ; 3046b8e80941Smrg 3047b8e80941Smrg memset(&templ, 0, sizeof(templ)); 3048b8e80941Smrg templ.target = PIPE_BUFFER; 3049b8e80941Smrg templ.format = PIPE_FORMAT_R8_UNORM; 3050b8e80941Smrg templ.width0 = buffer_size; 3051b8e80941Smrg templ.flags = 0; 3052b8e80941Smrg templ.bind = PIPE_BIND_STREAM_OUTPUT; 3053b8e80941Smrg templ.usage = PIPE_USAGE_STREAM; 3054b8e80941Smrg templ.height0 = templ.depth0 = templ.array_size = 1; 3055b8e80941Smrg templ.last_level = templ.nr_samples = templ.nr_storage_samples = 0; 3056b8e80941Smrg 3057b8e80941Smrg resource = screen_sw->resource_create(screen_sw, &templ); 3058b8e80941Smrg if (!resource) 3059b8e80941Smrg return E_OUTOFMEMORY; 3060b8e80941Smrg } 3061b8e80941Smrg target = pipe_sw->create_stream_output_target(pipe_sw, resource, 3062b8e80941Smrg 0, buffer_size); 3063b8e80941Smrg if (!target) { 3064b8e80941Smrg pipe_resource_reference(&resource, NULL); 3065b8e80941Smrg return D3DERR_DRIVERINTERNALERROR; 3066b8e80941Smrg } 3067b8e80941Smrg 3068b8e80941Smrg draw.mode = PIPE_PRIM_POINTS; 3069b8e80941Smrg draw.count = VertexCount; 3070b8e80941Smrg draw.start_instance = 0; 3071b8e80941Smrg draw.primitive_restart = FALSE; 3072b8e80941Smrg draw.restart_index = 0; 3073b8e80941Smrg draw.count_from_stream_output = NULL; 3074b8e80941Smrg draw.indirect = NULL; 3075b8e80941Smrg draw.instance_count = 1; 3076b8e80941Smrg draw.index_size = 0; 3077b8e80941Smrg draw.start = 0; 3078b8e80941Smrg draw.index_bias = 0; 3079b8e80941Smrg draw.min_index = 0; 3080b8e80941Smrg draw.max_index = VertexCount - 1; 3081b8e80941Smrg 3082b8e80941Smrg 3083b8e80941Smrg pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets); 3084b8e80941Smrg 3085b8e80941Smrg pipe_sw->draw_vbo(pipe_sw, &draw); 3086b8e80941Smrg 3087b8e80941Smrg pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0); 3088b8e80941Smrg pipe_sw->stream_output_target_destroy(pipe_sw, target); 3089b8e80941Smrg 3090b8e80941Smrg u_box_1d(0, VertexCount * so.stride[0] * 4, &box); 3091b8e80941Smrg map = pipe_sw->transfer_map(pipe_sw, resource, 0, PIPE_TRANSFER_READ, &box, 3092b8e80941Smrg &transfer); 3093b8e80941Smrg if (!map) { 3094b8e80941Smrg hr = D3DERR_DRIVERINTERNALERROR; 3095b8e80941Smrg goto out; 3096b8e80941Smrg } 3097b8e80941Smrg 3098b8e80941Smrg hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl, 3099b8e80941Smrg dst, DestIndex, VertexCount, 3100b8e80941Smrg map, &so); 3101b8e80941Smrg if (transfer) 3102b8e80941Smrg pipe_sw->transfer_unmap(pipe_sw, transfer); 3103b8e80941Smrg 3104b8e80941Smrgout: 3105b8e80941Smrg nine_state_after_draw_sw(This); 3106b8e80941Smrg pipe_resource_reference(&resource, NULL); 3107b8e80941Smrg return hr; 3108b8e80941Smrg} 3109b8e80941Smrg 3110b8e80941SmrgHRESULT NINE_WINAPI 3111b8e80941SmrgNineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, 3112b8e80941Smrg const D3DVERTEXELEMENT9 *pVertexElements, 3113b8e80941Smrg IDirect3DVertexDeclaration9 **ppDecl ) 3114b8e80941Smrg{ 3115b8e80941Smrg struct NineVertexDeclaration9 *vdecl; 3116b8e80941Smrg 3117b8e80941Smrg DBG("This=%p pVertexElements=%p ppDecl=%p\n", 3118b8e80941Smrg This, pVertexElements, ppDecl); 3119b8e80941Smrg 3120b8e80941Smrg HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl); 3121b8e80941Smrg if (SUCCEEDED(hr)) 3122b8e80941Smrg *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl; 3123b8e80941Smrg 3124b8e80941Smrg return hr; 3125b8e80941Smrg} 3126b8e80941Smrg 3127b8e80941SmrgHRESULT NINE_WINAPI 3128b8e80941SmrgNineDevice9_SetVertexDeclaration( struct NineDevice9 *This, 3129b8e80941Smrg IDirect3DVertexDeclaration9 *pDecl ) 3130b8e80941Smrg{ 3131b8e80941Smrg struct nine_state *state = This->update; 3132b8e80941Smrg struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl); 3133b8e80941Smrg 3134b8e80941Smrg DBG("This=%p pDecl=%p\n", This, pDecl); 3135b8e80941Smrg 3136b8e80941Smrg if (unlikely(This->is_recording)) { 3137b8e80941Smrg nine_bind(&state->vdecl, vdecl); 3138b8e80941Smrg state->changed.group |= NINE_STATE_VDECL; 3139b8e80941Smrg return D3D_OK; 3140b8e80941Smrg } 3141b8e80941Smrg 3142b8e80941Smrg if (state->vdecl == vdecl) 3143b8e80941Smrg return D3D_OK; 3144b8e80941Smrg 3145b8e80941Smrg nine_bind(&state->vdecl, vdecl); 3146b8e80941Smrg 3147b8e80941Smrg nine_context_set_vertex_declaration(This, vdecl); 3148b8e80941Smrg 3149b8e80941Smrg return D3D_OK; 3150b8e80941Smrg} 3151b8e80941Smrg 3152b8e80941SmrgHRESULT NINE_WINAPI 3153b8e80941SmrgNineDevice9_GetVertexDeclaration( struct NineDevice9 *This, 3154b8e80941Smrg IDirect3DVertexDeclaration9 **ppDecl ) 3155b8e80941Smrg{ 3156b8e80941Smrg user_assert(ppDecl, D3DERR_INVALIDCALL); 3157b8e80941Smrg 3158b8e80941Smrg *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl; 3159b8e80941Smrg if (*ppDecl) 3160b8e80941Smrg NineUnknown_AddRef(NineUnknown(*ppDecl)); 3161b8e80941Smrg return D3D_OK; 3162b8e80941Smrg} 3163b8e80941Smrg 3164b8e80941SmrgHRESULT NINE_WINAPI 3165b8e80941SmrgNineDevice9_SetFVF( struct NineDevice9 *This, 3166b8e80941Smrg DWORD FVF ) 3167b8e80941Smrg{ 3168b8e80941Smrg struct NineVertexDeclaration9 *vdecl; 3169b8e80941Smrg HRESULT hr; 3170b8e80941Smrg 3171b8e80941Smrg DBG("FVF = %08x\n", FVF); 3172b8e80941Smrg if (!FVF) 3173b8e80941Smrg return D3D_OK; /* like wine */ 3174b8e80941Smrg 3175b8e80941Smrg vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); 3176b8e80941Smrg if (!vdecl) { 3177b8e80941Smrg hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); 3178b8e80941Smrg if (FAILED(hr)) 3179b8e80941Smrg return hr; 3180b8e80941Smrg vdecl->fvf = FVF; 3181b8e80941Smrg util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl); 3182b8e80941Smrg NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); 3183b8e80941Smrg } 3184b8e80941Smrg return NineDevice9_SetVertexDeclaration( 3185b8e80941Smrg This, (IDirect3DVertexDeclaration9 *)vdecl); 3186b8e80941Smrg} 3187b8e80941Smrg 3188b8e80941SmrgHRESULT NINE_WINAPI 3189b8e80941SmrgNineDevice9_GetFVF( struct NineDevice9 *This, 3190b8e80941Smrg DWORD *pFVF ) 3191b8e80941Smrg{ 3192b8e80941Smrg *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0; 3193b8e80941Smrg return D3D_OK; 3194b8e80941Smrg} 3195b8e80941Smrg 3196b8e80941SmrgHRESULT NINE_WINAPI 3197b8e80941SmrgNineDevice9_CreateVertexShader( struct NineDevice9 *This, 3198b8e80941Smrg const DWORD *pFunction, 3199b8e80941Smrg IDirect3DVertexShader9 **ppShader ) 3200b8e80941Smrg{ 3201b8e80941Smrg struct NineVertexShader9 *vs; 3202b8e80941Smrg HRESULT hr; 3203b8e80941Smrg 3204b8e80941Smrg DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 3205b8e80941Smrg 3206b8e80941Smrg hr = NineVertexShader9_new(This, &vs, pFunction, NULL); 3207b8e80941Smrg if (FAILED(hr)) 3208b8e80941Smrg return hr; 3209b8e80941Smrg *ppShader = (IDirect3DVertexShader9 *)vs; 3210b8e80941Smrg return D3D_OK; 3211b8e80941Smrg} 3212b8e80941Smrg 3213b8e80941SmrgHRESULT NINE_WINAPI 3214b8e80941SmrgNineDevice9_SetVertexShader( struct NineDevice9 *This, 3215b8e80941Smrg IDirect3DVertexShader9 *pShader ) 3216b8e80941Smrg{ 3217b8e80941Smrg struct nine_state *state = This->update; 3218b8e80941Smrg struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader; 3219b8e80941Smrg 3220b8e80941Smrg DBG("This=%p pShader=%p\n", This, pShader); 3221b8e80941Smrg 3222b8e80941Smrg if (unlikely(This->is_recording)) { 3223b8e80941Smrg nine_bind(&state->vs, vs_shader); 3224b8e80941Smrg state->changed.group |= NINE_STATE_VS; 3225b8e80941Smrg return D3D_OK; 3226b8e80941Smrg } 3227b8e80941Smrg 3228b8e80941Smrg if (state->vs == vs_shader) 3229b8e80941Smrg return D3D_OK; 3230b8e80941Smrg 3231b8e80941Smrg nine_bind(&state->vs, vs_shader); 3232b8e80941Smrg 3233b8e80941Smrg nine_context_set_vertex_shader(This, vs_shader); 3234b8e80941Smrg 3235b8e80941Smrg return D3D_OK; 3236b8e80941Smrg} 3237b8e80941Smrg 3238b8e80941SmrgHRESULT NINE_WINAPI 3239b8e80941SmrgNineDevice9_GetVertexShader( struct NineDevice9 *This, 3240b8e80941Smrg IDirect3DVertexShader9 **ppShader ) 3241b8e80941Smrg{ 3242b8e80941Smrg user_assert(ppShader, D3DERR_INVALIDCALL); 3243b8e80941Smrg nine_reference_set(ppShader, This->state.vs); 3244b8e80941Smrg return D3D_OK; 3245b8e80941Smrg} 3246b8e80941Smrg 3247b8e80941SmrgHRESULT NINE_WINAPI 3248b8e80941SmrgNineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, 3249b8e80941Smrg UINT StartRegister, 3250b8e80941Smrg const float *pConstantData, 3251b8e80941Smrg UINT Vector4fCount ) 3252b8e80941Smrg{ 3253b8e80941Smrg struct nine_state *state = This->update; 3254b8e80941Smrg float *vs_const_f = state->vs_const_f; 3255b8e80941Smrg 3256b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 3257b8e80941Smrg This, StartRegister, pConstantData, Vector4fCount); 3258b8e80941Smrg 3259b8e80941Smrg user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 3260b8e80941Smrg user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 3261b8e80941Smrg 3262b8e80941Smrg if (!Vector4fCount) 3263b8e80941Smrg return D3D_OK; 3264b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3265b8e80941Smrg 3266b8e80941Smrg if (unlikely(This->is_recording)) { 3267b8e80941Smrg memcpy(&vs_const_f[StartRegister * 4], 3268b8e80941Smrg pConstantData, 3269b8e80941Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 3270b8e80941Smrg 3271b8e80941Smrg nine_ranges_insert(&state->changed.vs_const_f, 3272b8e80941Smrg StartRegister, StartRegister + Vector4fCount, 3273b8e80941Smrg &This->range_pool); 3274b8e80941Smrg 3275b8e80941Smrg state->changed.group |= NINE_STATE_VS_CONST; 3276b8e80941Smrg 3277b8e80941Smrg return D3D_OK; 3278b8e80941Smrg } 3279b8e80941Smrg 3280b8e80941Smrg if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData, 3281b8e80941Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0]))) 3282b8e80941Smrg return D3D_OK; 3283b8e80941Smrg 3284b8e80941Smrg memcpy(&vs_const_f[StartRegister * 4], 3285b8e80941Smrg pConstantData, 3286b8e80941Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 3287b8e80941Smrg 3288b8e80941Smrg nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData, 3289b8e80941Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0]), 3290b8e80941Smrg Vector4fCount); 3291b8e80941Smrg 3292b8e80941Smrg return D3D_OK; 3293b8e80941Smrg} 3294b8e80941Smrg 3295b8e80941SmrgHRESULT NINE_WINAPI 3296b8e80941SmrgNineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, 3297b8e80941Smrg UINT StartRegister, 3298b8e80941Smrg float *pConstantData, 3299b8e80941Smrg UINT Vector4fCount ) 3300b8e80941Smrg{ 3301b8e80941Smrg const struct nine_state *state = &This->state; 3302b8e80941Smrg 3303b8e80941Smrg user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 3304b8e80941Smrg user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 3305b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3306b8e80941Smrg 3307b8e80941Smrg memcpy(pConstantData, 3308b8e80941Smrg &state->vs_const_f[StartRegister * 4], 3309b8e80941Smrg Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 3310b8e80941Smrg 3311b8e80941Smrg return D3D_OK; 3312b8e80941Smrg} 3313b8e80941Smrg 3314b8e80941SmrgHRESULT NINE_WINAPI 3315b8e80941SmrgNineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, 3316b8e80941Smrg UINT StartRegister, 3317b8e80941Smrg const int *pConstantData, 3318b8e80941Smrg UINT Vector4iCount ) 3319b8e80941Smrg{ 3320b8e80941Smrg struct nine_state *state = This->update; 3321b8e80941Smrg int i; 3322b8e80941Smrg 3323b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 3324b8e80941Smrg This, StartRegister, pConstantData, Vector4iCount); 3325b8e80941Smrg 3326b8e80941Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 3327b8e80941Smrg D3DERR_INVALIDCALL); 3328b8e80941Smrg user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 3329b8e80941Smrg D3DERR_INVALIDCALL); 3330b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3331b8e80941Smrg 3332b8e80941Smrg if (This->driver_caps.vs_integer) { 3333b8e80941Smrg if (!This->is_recording) { 3334b8e80941Smrg if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData, 3335b8e80941Smrg Vector4iCount * sizeof(int[4]))) 3336b8e80941Smrg return D3D_OK; 3337b8e80941Smrg } 3338b8e80941Smrg memcpy(&state->vs_const_i[4 * StartRegister], 3339b8e80941Smrg pConstantData, 3340b8e80941Smrg Vector4iCount * sizeof(int[4])); 3341b8e80941Smrg } else { 3342b8e80941Smrg for (i = 0; i < Vector4iCount; i++) { 3343b8e80941Smrg state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i])); 3344b8e80941Smrg state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1])); 3345b8e80941Smrg state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2])); 3346b8e80941Smrg state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3])); 3347b8e80941Smrg } 3348b8e80941Smrg } 3349b8e80941Smrg 3350b8e80941Smrg if (unlikely(This->is_recording)) { 3351b8e80941Smrg nine_ranges_insert(&state->changed.vs_const_i, 3352b8e80941Smrg StartRegister, StartRegister + Vector4iCount, 3353b8e80941Smrg &This->range_pool); 3354b8e80941Smrg state->changed.group |= NINE_STATE_VS_CONST; 3355b8e80941Smrg } else 3356b8e80941Smrg nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData, 3357b8e80941Smrg Vector4iCount * sizeof(int[4]), Vector4iCount); 3358b8e80941Smrg 3359b8e80941Smrg return D3D_OK; 3360b8e80941Smrg} 3361b8e80941Smrg 3362b8e80941SmrgHRESULT NINE_WINAPI 3363b8e80941SmrgNineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, 3364b8e80941Smrg UINT StartRegister, 3365b8e80941Smrg int *pConstantData, 3366b8e80941Smrg UINT Vector4iCount ) 3367b8e80941Smrg{ 3368b8e80941Smrg const struct nine_state *state = &This->state; 3369b8e80941Smrg int i; 3370b8e80941Smrg 3371b8e80941Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 3372b8e80941Smrg D3DERR_INVALIDCALL); 3373b8e80941Smrg user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I), 3374b8e80941Smrg D3DERR_INVALIDCALL); 3375b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3376b8e80941Smrg 3377b8e80941Smrg if (This->driver_caps.vs_integer) { 3378b8e80941Smrg memcpy(pConstantData, 3379b8e80941Smrg &state->vs_const_i[4 * StartRegister], 3380b8e80941Smrg Vector4iCount * sizeof(int[4])); 3381b8e80941Smrg } else { 3382b8e80941Smrg for (i = 0; i < Vector4iCount; i++) { 3383b8e80941Smrg pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]); 3384b8e80941Smrg pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]); 3385b8e80941Smrg pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]); 3386b8e80941Smrg pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]); 3387b8e80941Smrg } 3388b8e80941Smrg } 3389b8e80941Smrg 3390b8e80941Smrg return D3D_OK; 3391b8e80941Smrg} 3392b8e80941Smrg 3393b8e80941SmrgHRESULT NINE_WINAPI 3394b8e80941SmrgNineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, 3395b8e80941Smrg UINT StartRegister, 3396b8e80941Smrg const BOOL *pConstantData, 3397b8e80941Smrg UINT BoolCount ) 3398b8e80941Smrg{ 3399b8e80941Smrg struct nine_state *state = This->update; 3400b8e80941Smrg int i; 3401b8e80941Smrg uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); 3402b8e80941Smrg 3403b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 3404b8e80941Smrg This, StartRegister, pConstantData, BoolCount); 3405b8e80941Smrg 3406b8e80941Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 3407b8e80941Smrg D3DERR_INVALIDCALL); 3408b8e80941Smrg user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 3409b8e80941Smrg D3DERR_INVALIDCALL); 3410b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3411b8e80941Smrg 3412b8e80941Smrg if (!This->is_recording) { 3413b8e80941Smrg bool noChange = true; 3414b8e80941Smrg for (i = 0; i < BoolCount; i++) { 3415b8e80941Smrg if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i]) 3416b8e80941Smrg noChange = false; 3417b8e80941Smrg } 3418b8e80941Smrg if (noChange) 3419b8e80941Smrg return D3D_OK; 3420b8e80941Smrg } 3421b8e80941Smrg 3422b8e80941Smrg for (i = 0; i < BoolCount; i++) 3423b8e80941Smrg state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 3424b8e80941Smrg 3425b8e80941Smrg if (unlikely(This->is_recording)) { 3426b8e80941Smrg nine_ranges_insert(&state->changed.vs_const_b, 3427b8e80941Smrg StartRegister, StartRegister + BoolCount, 3428b8e80941Smrg &This->range_pool); 3429b8e80941Smrg state->changed.group |= NINE_STATE_VS_CONST; 3430b8e80941Smrg } else 3431b8e80941Smrg nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData, 3432b8e80941Smrg sizeof(BOOL) * BoolCount, BoolCount); 3433b8e80941Smrg 3434b8e80941Smrg return D3D_OK; 3435b8e80941Smrg} 3436b8e80941Smrg 3437b8e80941SmrgHRESULT NINE_WINAPI 3438b8e80941SmrgNineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, 3439b8e80941Smrg UINT StartRegister, 3440b8e80941Smrg BOOL *pConstantData, 3441b8e80941Smrg UINT BoolCount ) 3442b8e80941Smrg{ 3443b8e80941Smrg const struct nine_state *state = &This->state; 3444b8e80941Smrg int i; 3445b8e80941Smrg 3446b8e80941Smrg user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 3447b8e80941Smrg D3DERR_INVALIDCALL); 3448b8e80941Smrg user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B), 3449b8e80941Smrg D3DERR_INVALIDCALL); 3450b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3451b8e80941Smrg 3452b8e80941Smrg for (i = 0; i < BoolCount; i++) 3453b8e80941Smrg pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE; 3454b8e80941Smrg 3455b8e80941Smrg return D3D_OK; 3456b8e80941Smrg} 3457b8e80941Smrg 3458b8e80941SmrgHRESULT NINE_WINAPI 3459b8e80941SmrgNineDevice9_SetStreamSource( struct NineDevice9 *This, 3460b8e80941Smrg UINT StreamNumber, 3461b8e80941Smrg IDirect3DVertexBuffer9 *pStreamData, 3462b8e80941Smrg UINT OffsetInBytes, 3463b8e80941Smrg UINT Stride ) 3464b8e80941Smrg{ 3465b8e80941Smrg struct nine_state *state = This->update; 3466b8e80941Smrg struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData); 3467b8e80941Smrg const unsigned i = StreamNumber; 3468b8e80941Smrg 3469b8e80941Smrg DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n", 3470b8e80941Smrg This, StreamNumber, pStreamData, OffsetInBytes, Stride); 3471b8e80941Smrg 3472b8e80941Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3473b8e80941Smrg user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL); 3474b8e80941Smrg 3475b8e80941Smrg if (unlikely(This->is_recording)) { 3476b8e80941Smrg nine_bind(&state->stream[i], pStreamData); 3477b8e80941Smrg state->changed.vtxbuf |= 1 << StreamNumber; 3478b8e80941Smrg state->vtxbuf[i].stride = Stride; 3479b8e80941Smrg state->vtxbuf[i].buffer_offset = OffsetInBytes; 3480b8e80941Smrg return D3D_OK; 3481b8e80941Smrg } 3482b8e80941Smrg 3483b8e80941Smrg if (state->stream[i] == NineVertexBuffer9(pStreamData) && 3484b8e80941Smrg state->vtxbuf[i].stride == Stride && 3485b8e80941Smrg state->vtxbuf[i].buffer_offset == OffsetInBytes) 3486b8e80941Smrg return D3D_OK; 3487b8e80941Smrg 3488b8e80941Smrg state->vtxbuf[i].stride = Stride; 3489b8e80941Smrg state->vtxbuf[i].buffer_offset = OffsetInBytes; 3490b8e80941Smrg 3491b8e80941Smrg NineBindBufferToDevice(This, 3492b8e80941Smrg (struct NineBuffer9 **)&state->stream[i], 3493b8e80941Smrg (struct NineBuffer9 *)pVBuf9); 3494b8e80941Smrg 3495b8e80941Smrg nine_context_set_stream_source(This, 3496b8e80941Smrg StreamNumber, 3497b8e80941Smrg pVBuf9, 3498b8e80941Smrg OffsetInBytes, 3499b8e80941Smrg Stride); 3500b8e80941Smrg 3501b8e80941Smrg return D3D_OK; 3502b8e80941Smrg} 3503b8e80941Smrg 3504b8e80941SmrgHRESULT NINE_WINAPI 3505b8e80941SmrgNineDevice9_GetStreamSource( struct NineDevice9 *This, 3506b8e80941Smrg UINT StreamNumber, 3507b8e80941Smrg IDirect3DVertexBuffer9 **ppStreamData, 3508b8e80941Smrg UINT *pOffsetInBytes, 3509b8e80941Smrg UINT *pStride ) 3510b8e80941Smrg{ 3511b8e80941Smrg const struct nine_state *state = &This->state; 3512b8e80941Smrg const unsigned i = StreamNumber; 3513b8e80941Smrg 3514b8e80941Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3515b8e80941Smrg user_assert(ppStreamData, D3DERR_INVALIDCALL); 3516b8e80941Smrg 3517b8e80941Smrg nine_reference_set(ppStreamData, state->stream[i]); 3518b8e80941Smrg *pStride = state->vtxbuf[i].stride; 3519b8e80941Smrg *pOffsetInBytes = state->vtxbuf[i].buffer_offset; 3520b8e80941Smrg 3521b8e80941Smrg return D3D_OK; 3522b8e80941Smrg} 3523b8e80941Smrg 3524b8e80941SmrgHRESULT NINE_WINAPI 3525b8e80941SmrgNineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, 3526b8e80941Smrg UINT StreamNumber, 3527b8e80941Smrg UINT Setting ) 3528b8e80941Smrg{ 3529b8e80941Smrg struct nine_state *state = This->update; 3530b8e80941Smrg /* const UINT freq = Setting & 0x7FFFFF; */ 3531b8e80941Smrg 3532b8e80941Smrg DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This, 3533b8e80941Smrg StreamNumber, Setting); 3534b8e80941Smrg 3535b8e80941Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3536b8e80941Smrg user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA), 3537b8e80941Smrg D3DERR_INVALIDCALL); 3538b8e80941Smrg user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) && 3539b8e80941Smrg (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL); 3540b8e80941Smrg user_assert(Setting, D3DERR_INVALIDCALL); 3541b8e80941Smrg 3542b8e80941Smrg if (unlikely(This->is_recording)) { 3543b8e80941Smrg state->stream_freq[StreamNumber] = Setting; 3544b8e80941Smrg state->changed.stream_freq |= 1 << StreamNumber; 3545b8e80941Smrg return D3D_OK; 3546b8e80941Smrg } 3547b8e80941Smrg 3548b8e80941Smrg if (state->stream_freq[StreamNumber] == Setting) 3549b8e80941Smrg return D3D_OK; 3550b8e80941Smrg 3551b8e80941Smrg state->stream_freq[StreamNumber] = Setting; 3552b8e80941Smrg 3553b8e80941Smrg nine_context_set_stream_source_freq(This, StreamNumber, Setting); 3554b8e80941Smrg return D3D_OK; 3555b8e80941Smrg} 3556b8e80941Smrg 3557b8e80941SmrgHRESULT NINE_WINAPI 3558b8e80941SmrgNineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, 3559b8e80941Smrg UINT StreamNumber, 3560b8e80941Smrg UINT *pSetting ) 3561b8e80941Smrg{ 3562b8e80941Smrg user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3563b8e80941Smrg *pSetting = This->state.stream_freq[StreamNumber]; 3564b8e80941Smrg return D3D_OK; 3565b8e80941Smrg} 3566b8e80941Smrg 3567b8e80941SmrgHRESULT NINE_WINAPI 3568b8e80941SmrgNineDevice9_SetIndices( struct NineDevice9 *This, 3569b8e80941Smrg IDirect3DIndexBuffer9 *pIndexData ) 3570b8e80941Smrg{ 3571b8e80941Smrg struct nine_state *state = This->update; 3572b8e80941Smrg struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData); 3573b8e80941Smrg 3574b8e80941Smrg DBG("This=%p pIndexData=%p\n", This, pIndexData); 3575b8e80941Smrg 3576b8e80941Smrg if (unlikely(This->is_recording)) { 3577b8e80941Smrg nine_bind(&state->idxbuf, idxbuf); 3578b8e80941Smrg state->changed.group |= NINE_STATE_IDXBUF; 3579b8e80941Smrg return D3D_OK; 3580b8e80941Smrg } 3581b8e80941Smrg 3582b8e80941Smrg if (state->idxbuf == idxbuf) 3583b8e80941Smrg return D3D_OK; 3584b8e80941Smrg 3585b8e80941Smrg NineBindBufferToDevice(This, 3586b8e80941Smrg (struct NineBuffer9 **)&state->idxbuf, 3587b8e80941Smrg (struct NineBuffer9 *)idxbuf); 3588b8e80941Smrg 3589b8e80941Smrg nine_context_set_indices(This, idxbuf); 3590b8e80941Smrg 3591b8e80941Smrg return D3D_OK; 3592b8e80941Smrg} 3593b8e80941Smrg 3594b8e80941Smrg/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense 3595b8e80941Smrg * here because it's an argument passed to the Draw calls. 3596b8e80941Smrg */ 3597b8e80941SmrgHRESULT NINE_WINAPI 3598b8e80941SmrgNineDevice9_GetIndices( struct NineDevice9 *This, 3599b8e80941Smrg IDirect3DIndexBuffer9 **ppIndexData) 3600b8e80941Smrg{ 3601b8e80941Smrg user_assert(ppIndexData, D3DERR_INVALIDCALL); 3602b8e80941Smrg nine_reference_set(ppIndexData, This->state.idxbuf); 3603b8e80941Smrg return D3D_OK; 3604b8e80941Smrg} 3605b8e80941Smrg 3606b8e80941SmrgHRESULT NINE_WINAPI 3607b8e80941SmrgNineDevice9_CreatePixelShader( struct NineDevice9 *This, 3608b8e80941Smrg const DWORD *pFunction, 3609b8e80941Smrg IDirect3DPixelShader9 **ppShader ) 3610b8e80941Smrg{ 3611b8e80941Smrg struct NinePixelShader9 *ps; 3612b8e80941Smrg HRESULT hr; 3613b8e80941Smrg 3614b8e80941Smrg DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 3615b8e80941Smrg 3616b8e80941Smrg hr = NinePixelShader9_new(This, &ps, pFunction, NULL); 3617b8e80941Smrg if (FAILED(hr)) 3618b8e80941Smrg return hr; 3619b8e80941Smrg *ppShader = (IDirect3DPixelShader9 *)ps; 3620b8e80941Smrg return D3D_OK; 3621b8e80941Smrg} 3622b8e80941Smrg 3623b8e80941SmrgHRESULT NINE_WINAPI 3624b8e80941SmrgNineDevice9_SetPixelShader( struct NineDevice9 *This, 3625b8e80941Smrg IDirect3DPixelShader9 *pShader ) 3626b8e80941Smrg{ 3627b8e80941Smrg struct nine_state *state = This->update; 3628b8e80941Smrg struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader; 3629b8e80941Smrg 3630b8e80941Smrg DBG("This=%p pShader=%p\n", This, pShader); 3631b8e80941Smrg 3632b8e80941Smrg if (unlikely(This->is_recording)) { 3633b8e80941Smrg nine_bind(&state->ps, pShader); 3634b8e80941Smrg state->changed.group |= NINE_STATE_PS; 3635b8e80941Smrg return D3D_OK; 3636b8e80941Smrg } 3637b8e80941Smrg 3638b8e80941Smrg if (state->ps == ps) 3639b8e80941Smrg return D3D_OK; 3640b8e80941Smrg 3641b8e80941Smrg nine_bind(&state->ps, ps); 3642b8e80941Smrg 3643b8e80941Smrg nine_context_set_pixel_shader(This, ps); 3644b8e80941Smrg 3645b8e80941Smrg return D3D_OK; 3646b8e80941Smrg} 3647b8e80941Smrg 3648b8e80941SmrgHRESULT NINE_WINAPI 3649b8e80941SmrgNineDevice9_GetPixelShader( struct NineDevice9 *This, 3650b8e80941Smrg IDirect3DPixelShader9 **ppShader ) 3651b8e80941Smrg{ 3652b8e80941Smrg user_assert(ppShader, D3DERR_INVALIDCALL); 3653b8e80941Smrg nine_reference_set(ppShader, This->state.ps); 3654b8e80941Smrg return D3D_OK; 3655b8e80941Smrg} 3656b8e80941Smrg 3657b8e80941SmrgHRESULT NINE_WINAPI 3658b8e80941SmrgNineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, 3659b8e80941Smrg UINT StartRegister, 3660b8e80941Smrg const float *pConstantData, 3661b8e80941Smrg UINT Vector4fCount ) 3662b8e80941Smrg{ 3663b8e80941Smrg struct nine_state *state = This->update; 3664b8e80941Smrg 3665b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 3666b8e80941Smrg This, StartRegister, pConstantData, Vector4fCount); 3667b8e80941Smrg 3668b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 3669b8e80941Smrg user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 3670b8e80941Smrg 3671b8e80941Smrg if (!Vector4fCount) 3672b8e80941Smrg return D3D_OK; 3673b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3674b8e80941Smrg 3675b8e80941Smrg if (unlikely(This->is_recording)) { 3676b8e80941Smrg memcpy(&state->ps_const_f[StartRegister * 4], 3677b8e80941Smrg pConstantData, 3678b8e80941Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 3679b8e80941Smrg 3680b8e80941Smrg nine_ranges_insert(&state->changed.ps_const_f, 3681b8e80941Smrg StartRegister, StartRegister + Vector4fCount, 3682b8e80941Smrg &This->range_pool); 3683b8e80941Smrg 3684b8e80941Smrg state->changed.group |= NINE_STATE_PS_CONST; 3685b8e80941Smrg return D3D_OK; 3686b8e80941Smrg } 3687b8e80941Smrg 3688b8e80941Smrg if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData, 3689b8e80941Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0]))) 3690b8e80941Smrg return D3D_OK; 3691b8e80941Smrg 3692b8e80941Smrg memcpy(&state->ps_const_f[StartRegister * 4], 3693b8e80941Smrg pConstantData, 3694b8e80941Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 3695b8e80941Smrg 3696b8e80941Smrg nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData, 3697b8e80941Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0]), 3698b8e80941Smrg Vector4fCount); 3699b8e80941Smrg 3700b8e80941Smrg return D3D_OK; 3701b8e80941Smrg} 3702b8e80941Smrg 3703b8e80941SmrgHRESULT NINE_WINAPI 3704b8e80941SmrgNineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, 3705b8e80941Smrg UINT StartRegister, 3706b8e80941Smrg float *pConstantData, 3707b8e80941Smrg UINT Vector4fCount ) 3708b8e80941Smrg{ 3709b8e80941Smrg const struct nine_state *state = &This->state; 3710b8e80941Smrg 3711b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 3712b8e80941Smrg user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL); 3713b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3714b8e80941Smrg 3715b8e80941Smrg memcpy(pConstantData, 3716b8e80941Smrg &state->ps_const_f[StartRegister * 4], 3717b8e80941Smrg Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 3718b8e80941Smrg 3719b8e80941Smrg return D3D_OK; 3720b8e80941Smrg} 3721b8e80941Smrg 3722b8e80941SmrgHRESULT NINE_WINAPI 3723b8e80941SmrgNineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, 3724b8e80941Smrg UINT StartRegister, 3725b8e80941Smrg const int *pConstantData, 3726b8e80941Smrg UINT Vector4iCount ) 3727b8e80941Smrg{ 3728b8e80941Smrg struct nine_state *state = This->update; 3729b8e80941Smrg int i; 3730b8e80941Smrg 3731b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 3732b8e80941Smrg This, StartRegister, pConstantData, Vector4iCount); 3733b8e80941Smrg 3734b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3735b8e80941Smrg user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3736b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3737b8e80941Smrg 3738b8e80941Smrg if (This->driver_caps.ps_integer) { 3739b8e80941Smrg if (!This->is_recording) { 3740b8e80941Smrg if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData, 3741b8e80941Smrg Vector4iCount * sizeof(state->ps_const_i[0]))) 3742b8e80941Smrg return D3D_OK; 3743b8e80941Smrg } 3744b8e80941Smrg memcpy(&state->ps_const_i[StartRegister][0], 3745b8e80941Smrg pConstantData, 3746b8e80941Smrg Vector4iCount * sizeof(state->ps_const_i[0])); 3747b8e80941Smrg } else { 3748b8e80941Smrg for (i = 0; i < Vector4iCount; i++) { 3749b8e80941Smrg state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); 3750b8e80941Smrg state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); 3751b8e80941Smrg state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); 3752b8e80941Smrg state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); 3753b8e80941Smrg } 3754b8e80941Smrg } 3755b8e80941Smrg 3756b8e80941Smrg if (unlikely(This->is_recording)) { 3757b8e80941Smrg state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; 3758b8e80941Smrg state->changed.group |= NINE_STATE_PS_CONST; 3759b8e80941Smrg } else 3760b8e80941Smrg nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData, 3761b8e80941Smrg sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount); 3762b8e80941Smrg 3763b8e80941Smrg return D3D_OK; 3764b8e80941Smrg} 3765b8e80941Smrg 3766b8e80941SmrgHRESULT NINE_WINAPI 3767b8e80941SmrgNineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, 3768b8e80941Smrg UINT StartRegister, 3769b8e80941Smrg int *pConstantData, 3770b8e80941Smrg UINT Vector4iCount ) 3771b8e80941Smrg{ 3772b8e80941Smrg const struct nine_state *state = &This->state; 3773b8e80941Smrg int i; 3774b8e80941Smrg 3775b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3776b8e80941Smrg user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3777b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3778b8e80941Smrg 3779b8e80941Smrg if (This->driver_caps.ps_integer) { 3780b8e80941Smrg memcpy(pConstantData, 3781b8e80941Smrg &state->ps_const_i[StartRegister][0], 3782b8e80941Smrg Vector4iCount * sizeof(state->ps_const_i[0])); 3783b8e80941Smrg } else { 3784b8e80941Smrg for (i = 0; i < Vector4iCount; i++) { 3785b8e80941Smrg pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]); 3786b8e80941Smrg pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]); 3787b8e80941Smrg pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]); 3788b8e80941Smrg pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]); 3789b8e80941Smrg } 3790b8e80941Smrg } 3791b8e80941Smrg 3792b8e80941Smrg return D3D_OK; 3793b8e80941Smrg} 3794b8e80941Smrg 3795b8e80941SmrgHRESULT NINE_WINAPI 3796b8e80941SmrgNineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, 3797b8e80941Smrg UINT StartRegister, 3798b8e80941Smrg const BOOL *pConstantData, 3799b8e80941Smrg UINT BoolCount ) 3800b8e80941Smrg{ 3801b8e80941Smrg struct nine_state *state = This->update; 3802b8e80941Smrg int i; 3803b8e80941Smrg uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); 3804b8e80941Smrg 3805b8e80941Smrg DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 3806b8e80941Smrg This, StartRegister, pConstantData, BoolCount); 3807b8e80941Smrg 3808b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3809b8e80941Smrg user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3810b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3811b8e80941Smrg 3812b8e80941Smrg if (!This->is_recording) { 3813b8e80941Smrg bool noChange = true; 3814b8e80941Smrg for (i = 0; i < BoolCount; i++) { 3815b8e80941Smrg if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i]) 3816b8e80941Smrg noChange = false; 3817b8e80941Smrg } 3818b8e80941Smrg if (noChange) 3819b8e80941Smrg return D3D_OK; 3820b8e80941Smrg } 3821b8e80941Smrg 3822b8e80941Smrg for (i = 0; i < BoolCount; i++) 3823b8e80941Smrg state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 3824b8e80941Smrg 3825b8e80941Smrg if (unlikely(This->is_recording)) { 3826b8e80941Smrg state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister; 3827b8e80941Smrg state->changed.group |= NINE_STATE_PS_CONST; 3828b8e80941Smrg } else 3829b8e80941Smrg nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData, 3830b8e80941Smrg sizeof(BOOL) * BoolCount, BoolCount); 3831b8e80941Smrg 3832b8e80941Smrg return D3D_OK; 3833b8e80941Smrg} 3834b8e80941Smrg 3835b8e80941SmrgHRESULT NINE_WINAPI 3836b8e80941SmrgNineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, 3837b8e80941Smrg UINT StartRegister, 3838b8e80941Smrg BOOL *pConstantData, 3839b8e80941Smrg UINT BoolCount ) 3840b8e80941Smrg{ 3841b8e80941Smrg const struct nine_state *state = &This->state; 3842b8e80941Smrg int i; 3843b8e80941Smrg 3844b8e80941Smrg user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3845b8e80941Smrg user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3846b8e80941Smrg user_assert(pConstantData, D3DERR_INVALIDCALL); 3847b8e80941Smrg 3848b8e80941Smrg for (i = 0; i < BoolCount; i++) 3849b8e80941Smrg pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE; 3850b8e80941Smrg 3851b8e80941Smrg return D3D_OK; 3852b8e80941Smrg} 3853b8e80941Smrg 3854b8e80941SmrgHRESULT NINE_WINAPI 3855b8e80941SmrgNineDevice9_DrawRectPatch( struct NineDevice9 *This, 3856b8e80941Smrg UINT Handle, 3857b8e80941Smrg const float *pNumSegs, 3858b8e80941Smrg const D3DRECTPATCH_INFO *pRectPatchInfo ) 3859b8e80941Smrg{ 3860b8e80941Smrg STUB(D3DERR_INVALIDCALL); 3861b8e80941Smrg} 3862b8e80941Smrg 3863b8e80941SmrgHRESULT NINE_WINAPI 3864b8e80941SmrgNineDevice9_DrawTriPatch( struct NineDevice9 *This, 3865b8e80941Smrg UINT Handle, 3866b8e80941Smrg const float *pNumSegs, 3867b8e80941Smrg const D3DTRIPATCH_INFO *pTriPatchInfo ) 3868b8e80941Smrg{ 3869b8e80941Smrg STUB(D3DERR_INVALIDCALL); 3870b8e80941Smrg} 3871b8e80941Smrg 3872b8e80941SmrgHRESULT NINE_WINAPI 3873b8e80941SmrgNineDevice9_DeletePatch( struct NineDevice9 *This, 3874b8e80941Smrg UINT Handle ) 3875b8e80941Smrg{ 3876b8e80941Smrg STUB(D3DERR_INVALIDCALL); 3877b8e80941Smrg} 3878b8e80941Smrg 3879b8e80941SmrgHRESULT NINE_WINAPI 3880b8e80941SmrgNineDevice9_CreateQuery( struct NineDevice9 *This, 3881b8e80941Smrg D3DQUERYTYPE Type, 3882b8e80941Smrg IDirect3DQuery9 **ppQuery ) 3883b8e80941Smrg{ 3884b8e80941Smrg struct NineQuery9 *query; 3885b8e80941Smrg HRESULT hr; 3886b8e80941Smrg 3887b8e80941Smrg DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery); 3888b8e80941Smrg 3889b8e80941Smrg hr = nine_is_query_supported(This->screen, Type); 3890b8e80941Smrg if (!ppQuery || hr != D3D_OK) 3891b8e80941Smrg return hr; 3892b8e80941Smrg 3893b8e80941Smrg hr = NineQuery9_new(This, &query, Type); 3894b8e80941Smrg if (FAILED(hr)) 3895b8e80941Smrg return hr; 3896b8e80941Smrg *ppQuery = (IDirect3DQuery9 *)query; 3897b8e80941Smrg return D3D_OK; 3898b8e80941Smrg} 3899b8e80941Smrg 3900b8e80941SmrgIDirect3DDevice9Vtbl NineDevice9_vtable = { 3901b8e80941Smrg (void *)NineUnknown_QueryInterface, 3902b8e80941Smrg (void *)NineUnknown_AddRef, 3903b8e80941Smrg (void *)NineUnknown_Release, 3904b8e80941Smrg (void *)NineDevice9_TestCooperativeLevel, 3905b8e80941Smrg (void *)NineDevice9_GetAvailableTextureMem, 3906b8e80941Smrg (void *)NineDevice9_EvictManagedResources, 3907b8e80941Smrg (void *)NineDevice9_GetDirect3D, 3908b8e80941Smrg (void *)NineDevice9_GetDeviceCaps, 3909b8e80941Smrg (void *)NineDevice9_GetDisplayMode, 3910b8e80941Smrg (void *)NineDevice9_GetCreationParameters, 3911b8e80941Smrg (void *)NineDevice9_SetCursorProperties, 3912b8e80941Smrg (void *)NineDevice9_SetCursorPosition, 3913b8e80941Smrg (void *)NineDevice9_ShowCursor, 3914b8e80941Smrg (void *)NineDevice9_CreateAdditionalSwapChain, 3915b8e80941Smrg (void *)NineDevice9_GetSwapChain, 3916b8e80941Smrg (void *)NineDevice9_GetNumberOfSwapChains, 3917b8e80941Smrg (void *)NineDevice9_Reset, 3918b8e80941Smrg (void *)NineDevice9_Present, 3919b8e80941Smrg (void *)NineDevice9_GetBackBuffer, 3920b8e80941Smrg (void *)NineDevice9_GetRasterStatus, 3921b8e80941Smrg (void *)NineDevice9_SetDialogBoxMode, 3922b8e80941Smrg (void *)NineDevice9_SetGammaRamp, 3923b8e80941Smrg (void *)NineDevice9_GetGammaRamp, 3924b8e80941Smrg (void *)NineDevice9_CreateTexture, 3925b8e80941Smrg (void *)NineDevice9_CreateVolumeTexture, 3926b8e80941Smrg (void *)NineDevice9_CreateCubeTexture, 3927b8e80941Smrg (void *)NineDevice9_CreateVertexBuffer, 3928b8e80941Smrg (void *)NineDevice9_CreateIndexBuffer, 3929b8e80941Smrg (void *)NineDevice9_CreateRenderTarget, 3930b8e80941Smrg (void *)NineDevice9_CreateDepthStencilSurface, 3931b8e80941Smrg (void *)NineDevice9_UpdateSurface, 3932b8e80941Smrg (void *)NineDevice9_UpdateTexture, 3933b8e80941Smrg (void *)NineDevice9_GetRenderTargetData, 3934b8e80941Smrg (void *)NineDevice9_GetFrontBufferData, 3935b8e80941Smrg (void *)NineDevice9_StretchRect, 3936b8e80941Smrg (void *)NineDevice9_ColorFill, 3937b8e80941Smrg (void *)NineDevice9_CreateOffscreenPlainSurface, 3938b8e80941Smrg (void *)NineDevice9_SetRenderTarget, 3939b8e80941Smrg (void *)NineDevice9_GetRenderTarget, 3940b8e80941Smrg (void *)NineDevice9_SetDepthStencilSurface, 3941b8e80941Smrg (void *)NineDevice9_GetDepthStencilSurface, 3942b8e80941Smrg (void *)NineDevice9_BeginScene, 3943b8e80941Smrg (void *)NineDevice9_EndScene, 3944b8e80941Smrg (void *)NineDevice9_Clear, 3945b8e80941Smrg (void *)NineDevice9_SetTransform, 3946b8e80941Smrg (void *)NineDevice9_GetTransform, 3947b8e80941Smrg (void *)NineDevice9_MultiplyTransform, 3948b8e80941Smrg (void *)NineDevice9_SetViewport, 3949b8e80941Smrg (void *)NineDevice9_GetViewport, 3950b8e80941Smrg (void *)NineDevice9_SetMaterial, 3951b8e80941Smrg (void *)NineDevice9_GetMaterial, 3952b8e80941Smrg (void *)NineDevice9_SetLight, 3953b8e80941Smrg (void *)NineDevice9_GetLight, 3954b8e80941Smrg (void *)NineDevice9_LightEnable, 3955b8e80941Smrg (void *)NineDevice9_GetLightEnable, 3956b8e80941Smrg (void *)NineDevice9_SetClipPlane, 3957b8e80941Smrg (void *)NineDevice9_GetClipPlane, 3958b8e80941Smrg (void *)NineDevice9_SetRenderState, 3959b8e80941Smrg (void *)NineDevice9_GetRenderState, 3960b8e80941Smrg (void *)NineDevice9_CreateStateBlock, 3961b8e80941Smrg (void *)NineDevice9_BeginStateBlock, 3962b8e80941Smrg (void *)NineDevice9_EndStateBlock, 3963b8e80941Smrg (void *)NineDevice9_SetClipStatus, 3964b8e80941Smrg (void *)NineDevice9_GetClipStatus, 3965b8e80941Smrg (void *)NineDevice9_GetTexture, 3966b8e80941Smrg (void *)NineDevice9_SetTexture, 3967b8e80941Smrg (void *)NineDevice9_GetTextureStageState, 3968b8e80941Smrg (void *)NineDevice9_SetTextureStageState, 3969b8e80941Smrg (void *)NineDevice9_GetSamplerState, 3970b8e80941Smrg (void *)NineDevice9_SetSamplerState, 3971b8e80941Smrg (void *)NineDevice9_ValidateDevice, 3972b8e80941Smrg (void *)NineDevice9_SetPaletteEntries, 3973b8e80941Smrg (void *)NineDevice9_GetPaletteEntries, 3974b8e80941Smrg (void *)NineDevice9_SetCurrentTexturePalette, 3975b8e80941Smrg (void *)NineDevice9_GetCurrentTexturePalette, 3976b8e80941Smrg (void *)NineDevice9_SetScissorRect, 3977b8e80941Smrg (void *)NineDevice9_GetScissorRect, 3978b8e80941Smrg (void *)NineDevice9_SetSoftwareVertexProcessing, 3979b8e80941Smrg (void *)NineDevice9_GetSoftwareVertexProcessing, 3980b8e80941Smrg (void *)NineDevice9_SetNPatchMode, 3981b8e80941Smrg (void *)NineDevice9_GetNPatchMode, 3982b8e80941Smrg (void *)NineDevice9_DrawPrimitive, 3983b8e80941Smrg (void *)NineDevice9_DrawIndexedPrimitive, 3984b8e80941Smrg (void *)NineDevice9_DrawPrimitiveUP, 3985b8e80941Smrg (void *)NineDevice9_DrawIndexedPrimitiveUP, 3986b8e80941Smrg (void *)NineDevice9_ProcessVertices, 3987b8e80941Smrg (void *)NineDevice9_CreateVertexDeclaration, 3988b8e80941Smrg (void *)NineDevice9_SetVertexDeclaration, 3989b8e80941Smrg (void *)NineDevice9_GetVertexDeclaration, 3990b8e80941Smrg (void *)NineDevice9_SetFVF, 3991b8e80941Smrg (void *)NineDevice9_GetFVF, 3992b8e80941Smrg (void *)NineDevice9_CreateVertexShader, 3993b8e80941Smrg (void *)NineDevice9_SetVertexShader, 3994b8e80941Smrg (void *)NineDevice9_GetVertexShader, 3995b8e80941Smrg (void *)NineDevice9_SetVertexShaderConstantF, 3996b8e80941Smrg (void *)NineDevice9_GetVertexShaderConstantF, 3997b8e80941Smrg (void *)NineDevice9_SetVertexShaderConstantI, 3998b8e80941Smrg (void *)NineDevice9_GetVertexShaderConstantI, 3999b8e80941Smrg (void *)NineDevice9_SetVertexShaderConstantB, 4000b8e80941Smrg (void *)NineDevice9_GetVertexShaderConstantB, 4001b8e80941Smrg (void *)NineDevice9_SetStreamSource, 4002b8e80941Smrg (void *)NineDevice9_GetStreamSource, 4003b8e80941Smrg (void *)NineDevice9_SetStreamSourceFreq, 4004b8e80941Smrg (void *)NineDevice9_GetStreamSourceFreq, 4005b8e80941Smrg (void *)NineDevice9_SetIndices, 4006b8e80941Smrg (void *)NineDevice9_GetIndices, 4007b8e80941Smrg (void *)NineDevice9_CreatePixelShader, 4008b8e80941Smrg (void *)NineDevice9_SetPixelShader, 4009b8e80941Smrg (void *)NineDevice9_GetPixelShader, 4010b8e80941Smrg (void *)NineDevice9_SetPixelShaderConstantF, 4011b8e80941Smrg (void *)NineDevice9_GetPixelShaderConstantF, 4012b8e80941Smrg (void *)NineDevice9_SetPixelShaderConstantI, 4013b8e80941Smrg (void *)NineDevice9_GetPixelShaderConstantI, 4014b8e80941Smrg (void *)NineDevice9_SetPixelShaderConstantB, 4015b8e80941Smrg (void *)NineDevice9_GetPixelShaderConstantB, 4016b8e80941Smrg (void *)NineDevice9_DrawRectPatch, 4017b8e80941Smrg (void *)NineDevice9_DrawTriPatch, 4018b8e80941Smrg (void *)NineDevice9_DeletePatch, 4019b8e80941Smrg (void *)NineDevice9_CreateQuery 4020b8e80941Smrg}; 4021b8e80941Smrg 4022b8e80941Smrgstatic const GUID *NineDevice9_IIDs[] = { 4023b8e80941Smrg &IID_IDirect3DDevice9, 4024b8e80941Smrg &IID_IUnknown, 4025b8e80941Smrg NULL 4026b8e80941Smrg}; 4027b8e80941Smrg 4028b8e80941SmrgHRESULT 4029b8e80941SmrgNineDevice9_new( struct pipe_screen *pScreen, 4030b8e80941Smrg D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 4031b8e80941Smrg D3DCAPS9 *pCaps, 4032b8e80941Smrg D3DPRESENT_PARAMETERS *pPresentationParameters, 4033b8e80941Smrg IDirect3D9 *pD3D9, 4034b8e80941Smrg ID3DPresentGroup *pPresentationGroup, 4035b8e80941Smrg struct d3dadapter9_context *pCTX, 4036b8e80941Smrg boolean ex, 4037b8e80941Smrg D3DDISPLAYMODEEX *pFullscreenDisplayMode, 4038b8e80941Smrg struct NineDevice9 **ppOut, 4039b8e80941Smrg int minorVersionNum ) 4040b8e80941Smrg{ 4041b8e80941Smrg BOOL lock; 4042b8e80941Smrg lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); 4043b8e80941Smrg 4044b8e80941Smrg NINE_NEW(Device9, ppOut, lock, /* args */ 4045b8e80941Smrg pScreen, pCreationParameters, pCaps, 4046b8e80941Smrg pPresentationParameters, pD3D9, pPresentationGroup, pCTX, 4047b8e80941Smrg ex, pFullscreenDisplayMode, minorVersionNum ); 4048b8e80941Smrg} 4049