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