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