device9.c revision 65ca8e4b3d6903ef086b81a5bf94688898290c4f
1/* 2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 23#include "device9.h" 24#include "stateblock9.h" 25#include "surface9.h" 26#include "swapchain9.h" 27#include "swapchain9ex.h" 28#include "indexbuffer9.h" 29#include "vertexbuffer9.h" 30#include "vertexdeclaration9.h" 31#include "vertexshader9.h" 32#include "pixelshader9.h" 33#include "query9.h" 34#include "texture9.h" 35#include "cubetexture9.h" 36#include "volumetexture9.h" 37#include "nine_helpers.h" 38#include "nine_pipe.h" 39#include "nine_ff.h" 40#include "nine_dump.h" 41 42#include "pipe/p_screen.h" 43#include "pipe/p_context.h" 44#include "util/u_math.h" 45#include "util/u_inlines.h" 46#include "util/u_hash_table.h" 47#include "util/u_format.h" 48#include "util/u_surface.h" 49#include "util/u_upload_mgr.h" 50#include "hud/hud_context.h" 51 52#include "cso_cache/cso_context.h" 53 54#define DBG_CHANNEL DBG_DEVICE 55 56static void 57NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset ) 58{ 59 struct NineSurface9 *refSurf = NULL; 60 61 DBG("This=%p is_reset=%d\n", This, (int) is_reset); 62 63 assert(!This->is_recording); 64 65 nine_state_set_defaults(This, &This->caps, is_reset); 66 67 This->state.viewport.X = 0; 68 This->state.viewport.Y = 0; 69 This->state.viewport.Width = 0; 70 This->state.viewport.Height = 0; 71 72 This->state.scissor.minx = 0; 73 This->state.scissor.miny = 0; 74 This->state.scissor.maxx = 0xffff; 75 This->state.scissor.maxy = 0xffff; 76 77 if (This->nswapchains && This->swapchains[0]->params.BackBufferCount) 78 refSurf = This->swapchains[0]->buffers[0]; 79 80 if (refSurf) { 81 This->state.viewport.Width = refSurf->desc.Width; 82 This->state.viewport.Height = refSurf->desc.Height; 83 This->state.scissor.maxx = refSurf->desc.Width; 84 This->state.scissor.maxy = refSurf->desc.Height; 85 } 86 87 if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) 88 This->state.rs[D3DRS_ZENABLE] = TRUE; 89 if (This->state.rs[D3DRS_ZENABLE]) 90 NineDevice9_SetDepthStencilSurface( 91 This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf); 92} 93 94void 95NineDevice9_RestoreNonCSOState( struct NineDevice9 *This, unsigned mask ) 96{ 97 struct pipe_context *pipe = This->pipe; 98 99 DBG("This=%p mask=%u\n", This, mask); 100 101 if (mask & 0x1) { 102 struct pipe_constant_buffer cb; 103 cb.buffer_offset = 0; 104 105 if (This->prefer_user_constbuf) { 106 cb.buffer = NULL; 107 cb.user_buffer = This->state.vs_const_f; 108 } else { 109 cb.buffer = This->constbuf_vs; 110 cb.user_buffer = NULL; 111 } 112 cb.buffer_size = This->vs_const_size; 113 pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &cb); 114 115 if (This->prefer_user_constbuf) { 116 cb.user_buffer = This->state.ps_const_f; 117 } else { 118 cb.buffer = This->constbuf_ps; 119 } 120 cb.buffer_size = This->ps_const_size; 121 pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &cb); 122 } 123 124 if (mask & 0x2) { 125 struct pipe_poly_stipple stipple; 126 memset(&stipple, ~0, sizeof(stipple)); 127 pipe->set_polygon_stipple(pipe, &stipple); 128 } 129 130 This->state.changed.group = NINE_STATE_ALL; 131 This->state.changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; 132 This->state.changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; 133 This->state.changed.texture = NINE_PS_SAMPLERS_MASK | NINE_VS_SAMPLERS_MASK; 134} 135 136#define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n) 137HRESULT 138NineDevice9_ctor( struct NineDevice9 *This, 139 struct NineUnknownParams *pParams, 140 struct pipe_screen *pScreen, 141 D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 142 D3DCAPS9 *pCaps, 143 D3DPRESENT_PARAMETERS *pPresentationParameters, 144 IDirect3D9 *pD3D9, 145 ID3DPresentGroup *pPresentationGroup, 146 struct d3dadapter9_context *pCTX, 147 boolean ex, 148 D3DDISPLAYMODEEX *pFullscreenDisplayMode ) 149{ 150 unsigned i; 151 HRESULT hr = NineUnknown_ctor(&This->base, pParams); 152 153 DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p " 154 "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n", 155 This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9, 156 pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode); 157 158 if (FAILED(hr)) { return hr; } 159 160 list_inithead(&This->update_textures); 161 162 This->screen = pScreen; 163 This->caps = *pCaps; 164 This->d3d9 = pD3D9; 165 This->params = *pCreationParameters; 166 This->ex = ex; 167 This->present = pPresentationGroup; 168 IDirect3D9_AddRef(This->d3d9); 169 ID3DPresentGroup_AddRef(This->present); 170 171 This->pipe = This->screen->context_create(This->screen, NULL); 172 if (!This->pipe) { return E_OUTOFMEMORY; } /* guess */ 173 174 This->cso = cso_create_context(This->pipe); 175 if (!This->cso) { return E_OUTOFMEMORY; } /* also a guess */ 176 177 /* Create first, it messes up our state. */ 178 This->hud = hud_create(This->pipe, This->cso); /* NULL result is fine */ 179 180 /* create implicit swapchains */ 181 This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present); 182 This->swapchains = CALLOC(This->nswapchains, 183 sizeof(struct NineSwapChain9 *)); 184 if (!This->swapchains) { return E_OUTOFMEMORY; } 185 186 for (i = 0; i < This->nswapchains; ++i) { 187 ID3DPresent *present; 188 189 hr = ID3DPresentGroup_GetPresent(This->present, i, &present); 190 if (FAILED(hr)) 191 return hr; 192 193 if (ex) { 194 D3DDISPLAYMODEEX *mode = NULL; 195 struct NineSwapChain9Ex **ret = 196 (struct NineSwapChain9Ex **)&This->swapchains[i]; 197 198 if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]); 199 /* when this is a Device9Ex, it should create SwapChain9Exs */ 200 hr = NineSwapChain9Ex_new(This, TRUE, present, 201 &pPresentationParameters[i], pCTX, 202 This->params.hFocusWindow, mode, ret); 203 } else { 204 hr = NineSwapChain9_new(This, TRUE, present, 205 &pPresentationParameters[i], pCTX, 206 This->params.hFocusWindow, 207 &This->swapchains[i]); 208 } 209 210 ID3DPresent_Release(present); 211 if (FAILED(hr)) 212 return hr; 213 NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i])); 214 215 hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0, 216 D3DBACKBUFFER_TYPE_MONO, 217 (IDirect3DSurface9 **) 218 &This->state.rt[i]); 219 if (FAILED(hr)) 220 return hr; 221 NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i])); 222 } 223 224 This->cursor.software = FALSE; 225 This->cursor.hotspot.x = -1; 226 This->cursor.hotspot.y = -1; 227 { 228 struct pipe_resource tmpl; 229 tmpl.target = PIPE_TEXTURE_2D; 230 tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM; 231 tmpl.width0 = 64; 232 tmpl.height0 = 64; 233 tmpl.depth0 = 1; 234 tmpl.array_size = 1; 235 tmpl.last_level = 0; 236 tmpl.nr_samples = 0; 237 tmpl.usage = PIPE_USAGE_DEFAULT; 238 tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW; 239 tmpl.flags = 0; 240 241 This->cursor.image = pScreen->resource_create(pScreen, &tmpl); 242 if (!This->cursor.image) 243 return D3DERR_OUTOFVIDEOMEMORY; 244 } 245 246 /* Create constant buffers. */ 247 { 248 struct pipe_resource tmpl; 249 unsigned max_const_vs, max_const_ps; 250 251 /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots, 252 * we have to take in some more slots for int and bool*/ 253 max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, 254 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) / 255 sizeof(float[4]), 256 NINE_MAX_CONST_ALL); 257 /* ps 3.0: 224 float constants. All cards supported support at least 258 * 256 constants for ps */ 259 max_const_ps = 224 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 260 261 This->max_vs_const_f = max_const_vs - 262 (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 263 This->max_ps_const_f = max_const_ps - 264 (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4); 265 266 This->vs_const_size = max_const_vs * sizeof(float[4]); 267 This->ps_const_size = max_const_ps * sizeof(float[4]); 268 /* Include space for I,B constants for user constbuf. */ 269 This->state.vs_const_f = CALLOC(This->vs_const_size, 1); 270 This->state.ps_const_f = CALLOC(This->ps_const_size, 1); 271 This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1); 272 if (!This->state.vs_const_f || !This->state.ps_const_f || 273 !This->state.vs_lconstf_temp) 274 return E_OUTOFMEMORY; 275 276 if (strstr(pScreen->get_name(pScreen), "AMD") || 277 strstr(pScreen->get_name(pScreen), "ATI")) 278 This->prefer_user_constbuf = TRUE; 279 280 tmpl.target = PIPE_BUFFER; 281 tmpl.format = PIPE_FORMAT_R8_UNORM; 282 tmpl.height0 = 1; 283 tmpl.depth0 = 1; 284 tmpl.array_size = 1; 285 tmpl.last_level = 0; 286 tmpl.nr_samples = 0; 287 tmpl.usage = PIPE_USAGE_DYNAMIC; 288 tmpl.bind = PIPE_BIND_CONSTANT_BUFFER; 289 tmpl.flags = 0; 290 291 tmpl.width0 = This->vs_const_size; 292 This->constbuf_vs = pScreen->resource_create(pScreen, &tmpl); 293 294 tmpl.width0 = This->ps_const_size; 295 This->constbuf_ps = pScreen->resource_create(pScreen, &tmpl); 296 297 if (!This->constbuf_vs || !This->constbuf_ps) 298 return E_OUTOFMEMORY; 299 } 300 301 /* Allocate upload helper for drivers that suck (from st pov ;). */ 302 { 303 unsigned bind = 0; 304 305 This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS); 306 This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS); 307 308 if (!This->driver_caps.user_vbufs) bind |= PIPE_BIND_VERTEX_BUFFER; 309 if (!This->driver_caps.user_ibufs) bind |= PIPE_BIND_INDEX_BUFFER; 310 if (bind) 311 This->upload = u_upload_create(This->pipe, 1 << 20, 4, bind); 312 } 313 314 This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION); 315 This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS); 316 This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS); 317 318 nine_ff_init(This); /* initialize fixed function code */ 319 320 NineDevice9_SetDefaultState(This, FALSE); 321 NineDevice9_RestoreNonCSOState(This, ~0); 322 323 This->update = &This->state; 324 nine_update_state(This, ~0); 325 326 ID3DPresentGroup_Release(This->present); 327 328 return D3D_OK; 329} 330#undef GET_PCAP 331 332void 333NineDevice9_dtor( struct NineDevice9 *This ) 334{ 335 unsigned i; 336 337 DBG("This=%p\n", This); 338 339 if (This->pipe && This->cso) 340 nine_pipe_context_clear(This); 341 nine_ff_fini(This); 342 nine_state_clear(&This->state, TRUE); 343 344 if (This->upload) 345 u_upload_destroy(This->upload); 346 347 nine_bind(&This->record, NULL); 348 349 pipe_resource_reference(&This->constbuf_vs, NULL); 350 pipe_resource_reference(&This->constbuf_ps, NULL); 351 FREE(This->state.vs_const_f); 352 FREE(This->state.ps_const_f); 353 FREE(This->state.vs_lconstf_temp); 354 355 if (This->swapchains) { 356 for (i = 0; i < This->nswapchains; ++i) 357 NineUnknown_Unbind(NineUnknown(This->swapchains[i])); 358 FREE(This->swapchains); 359 } 360 361 /* state stuff */ 362 if (This->pipe) { 363 if (This->cso) { 364 cso_destroy_context(This->cso); 365 } 366 if (This->pipe->destroy) { This->pipe->destroy(This->pipe); } 367 } 368 369 if (This->present) { ID3DPresentGroup_Release(This->present); } 370 if (This->d3d9) { IDirect3D9_Release(This->d3d9); } 371 372 NineUnknown_dtor(&This->base); 373} 374 375struct pipe_screen * 376NineDevice9_GetScreen( struct NineDevice9 *This ) 377{ 378 return This->screen; 379} 380 381struct pipe_context * 382NineDevice9_GetPipe( struct NineDevice9 *This ) 383{ 384 return This->pipe; 385} 386 387struct cso_context * 388NineDevice9_GetCSO( struct NineDevice9 *This ) 389{ 390 return This->cso; 391} 392 393const D3DCAPS9 * 394NineDevice9_GetCaps( struct NineDevice9 *This ) 395{ 396 return &This->caps; 397} 398 399static INLINE void 400NineDevice9_PauseRecording( struct NineDevice9 *This ) 401{ 402 if (This->record) { 403 This->update = &This->state; 404 This->is_recording = FALSE; 405 } 406} 407 408static INLINE void 409NineDevice9_ResumeRecording( struct NineDevice9 *This ) 410{ 411 if (This->record) { 412 This->update = &This->record->state; 413 This->is_recording = TRUE; 414 } 415} 416 417HRESULT WINAPI 418NineDevice9_TestCooperativeLevel( struct NineDevice9 *This ) 419{ 420 return D3D_OK; /* TODO */ 421} 422 423UINT WINAPI 424NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This ) 425{ 426 const unsigned mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY); 427 if (mem < 4096) 428 return mem << 20; 429 else 430 return UINT_MAX; 431} 432 433HRESULT WINAPI 434NineDevice9_EvictManagedResources( struct NineDevice9 *This ) 435{ 436 /* We don't really need to do anything here, but might want to free up 437 * the GPU virtual address space by killing pipe_resources. 438 */ 439 STUB(D3D_OK); 440} 441 442HRESULT WINAPI 443NineDevice9_GetDirect3D( struct NineDevice9 *This, 444 IDirect3D9 **ppD3D9 ) 445{ 446 user_assert(ppD3D9 != NULL, E_POINTER); 447 IDirect3D9_AddRef(This->d3d9); 448 *ppD3D9 = This->d3d9; 449 return D3D_OK; 450} 451 452HRESULT WINAPI 453NineDevice9_GetDeviceCaps( struct NineDevice9 *This, 454 D3DCAPS9 *pCaps ) 455{ 456 user_assert(pCaps != NULL, D3DERR_INVALIDCALL); 457 *pCaps = This->caps; 458 return D3D_OK; 459} 460 461HRESULT WINAPI 462NineDevice9_GetDisplayMode( struct NineDevice9 *This, 463 UINT iSwapChain, 464 D3DDISPLAYMODE *pMode ) 465{ 466 DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode); 467 468 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 469 470 return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode); 471} 472 473HRESULT WINAPI 474NineDevice9_GetCreationParameters( struct NineDevice9 *This, 475 D3DDEVICE_CREATION_PARAMETERS *pParameters ) 476{ 477 user_assert(pParameters != NULL, D3DERR_INVALIDCALL); 478 *pParameters = This->params; 479 return D3D_OK; 480} 481 482HRESULT WINAPI 483NineDevice9_SetCursorProperties( struct NineDevice9 *This, 484 UINT XHotSpot, 485 UINT YHotSpot, 486 IDirect3DSurface9 *pCursorBitmap ) 487{ 488 /* TODO: hardware cursor */ 489 struct NineSurface9 *surf = NineSurface9(pCursorBitmap); 490 struct pipe_context *pipe = This->pipe; 491 struct pipe_box box; 492 struct pipe_transfer *transfer; 493 void *ptr; 494 495 DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u " 496 "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap); 497 498 user_assert(pCursorBitmap, D3DERR_INVALIDCALL); 499 500 This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0); 501 This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0); 502 503 u_box_origin_2d(This->cursor.w, This->cursor.h, &box); 504 505 ptr = pipe->transfer_map(pipe, This->cursor.image, 0, 506 PIPE_TRANSFER_WRITE | 507 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, 508 &box, &transfer); 509 if (!ptr) 510 ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR); 511 512 This->cursor.hotspot.x = XHotSpot; 513 This->cursor.hotspot.y = YHotSpot; 514 515 /* Copy cursor image to internal storage. */ 516 { 517 D3DLOCKED_RECT lock; 518 HRESULT hr; 519 const struct util_format_description *sfmt = 520 util_format_description(surf->base.info.format); 521 assert(sfmt); 522 523 hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY); 524 if (FAILED(hr)) 525 ret_err("Failed to map cursor source image.\n", 526 D3DERR_DRIVERINTERNALERROR); 527 528 sfmt->unpack_rgba_8unorm(ptr, transfer->stride, 529 lock.pBits, lock.Pitch, 530 This->cursor.w, This->cursor.h); 531 532 if (!This->cursor.software && 533 This->cursor.w == 32 && This->cursor.h == 32) 534 ID3DPresent_SetCursor(This->swapchains[0]->present, 535 lock.pBits, &This->cursor.hotspot, 536 This->cursor.visible); 537 538 NineSurface9_UnlockRect(surf); 539 } 540 pipe->transfer_unmap(pipe, transfer); 541 542 return D3D_OK; 543} 544 545void WINAPI 546NineDevice9_SetCursorPosition( struct NineDevice9 *This, 547 int X, 548 int Y, 549 DWORD Flags ) 550{ 551 struct NineSwapChain9 *swap = This->swapchains[0]; 552 553 DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags); 554 555 This->cursor.pos.x = X; 556 This->cursor.pos.y = Y; 557 558 if (!This->cursor.software) 559 ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos); 560} 561 562BOOL WINAPI 563NineDevice9_ShowCursor( struct NineDevice9 *This, 564 BOOL bShow ) 565{ 566 BOOL old = This->cursor.visible; 567 568 DBG("This=%p bShow=%d\n", This, (int) bShow); 569 570 This->cursor.visible = bShow && (This->cursor.hotspot.x != -1); 571 if (!This->cursor.software) 572 ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow); 573 574 return old; 575} 576 577HRESULT WINAPI 578NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This, 579 D3DPRESENT_PARAMETERS *pPresentationParameters, 580 IDirect3DSwapChain9 **pSwapChain ) 581{ 582 struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0]; 583 ID3DPresent *present; 584 HRESULT hr; 585 586 DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n", 587 This, pPresentationParameters, pSwapChain); 588 589 user_assert(pPresentationParameters, D3DERR_INVALIDCALL); 590 591 hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present); 592 593 if (FAILED(hr)) 594 return hr; 595 596 hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters, 597 tmplt->actx, 598 tmplt->params.hDeviceWindow, 599 &swapchain); 600 if (FAILED(hr)) 601 return hr; 602 603 *pSwapChain = (IDirect3DSwapChain9 *)swapchain; 604 return D3D_OK; 605} 606 607HRESULT WINAPI 608NineDevice9_GetSwapChain( struct NineDevice9 *This, 609 UINT iSwapChain, 610 IDirect3DSwapChain9 **pSwapChain ) 611{ 612 user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL); 613 614 *pSwapChain = NULL; 615 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 616 617 NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain])); 618 *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain]; 619 620 return D3D_OK; 621} 622 623UINT WINAPI 624NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This ) 625{ 626 return This->nswapchains; 627} 628 629HRESULT WINAPI 630NineDevice9_Reset( struct NineDevice9 *This, 631 D3DPRESENT_PARAMETERS *pPresentationParameters ) 632{ 633 HRESULT hr = D3D_OK; 634 unsigned i; 635 636 DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters); 637 638 for (i = 0; i < This->nswapchains; ++i) { 639 D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i]; 640 hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL); 641 if (FAILED(hr)) 642 return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST; 643 } 644 645 nine_pipe_context_clear(This); 646 nine_state_clear(&This->state, TRUE); 647 648 NineDevice9_SetDefaultState(This, TRUE); 649 NineDevice9_SetRenderTarget( 650 This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]); 651 /* XXX: better use GetBackBuffer here ? */ 652 653 return hr; 654} 655 656HRESULT WINAPI 657NineDevice9_Present( struct NineDevice9 *This, 658 const RECT *pSourceRect, 659 const RECT *pDestRect, 660 HWND hDestWindowOverride, 661 const RGNDATA *pDirtyRegion ) 662{ 663 unsigned i; 664 HRESULT hr; 665 666 DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n", 667 This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); 668 669 /* XXX is this right? */ 670 for (i = 0; i < This->nswapchains; ++i) { 671 hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect, 672 hDestWindowOverride, pDirtyRegion, 0); 673 if (FAILED(hr)) { return hr; } 674 } 675 676 return D3D_OK; 677} 678 679HRESULT WINAPI 680NineDevice9_GetBackBuffer( struct NineDevice9 *This, 681 UINT iSwapChain, 682 UINT iBackBuffer, 683 D3DBACKBUFFER_TYPE Type, 684 IDirect3DSurface9 **ppBackBuffer ) 685{ 686 user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); 687 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 688 689 return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain], 690 iBackBuffer, Type, ppBackBuffer); 691} 692 693HRESULT WINAPI 694NineDevice9_GetRasterStatus( struct NineDevice9 *This, 695 UINT iSwapChain, 696 D3DRASTER_STATUS *pRasterStatus ) 697{ 698 user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL); 699 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 700 701 return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain], 702 pRasterStatus); 703} 704 705HRESULT WINAPI 706NineDevice9_SetDialogBoxMode( struct NineDevice9 *This, 707 BOOL bEnableDialogs ) 708{ 709 STUB(D3DERR_INVALIDCALL); 710} 711 712void WINAPI 713NineDevice9_SetGammaRamp( struct NineDevice9 *This, 714 UINT iSwapChain, 715 DWORD Flags, 716 const D3DGAMMARAMP *pRamp ) 717{ 718 DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This, 719 iSwapChain, Flags, pRamp); 720 721 user_warn(iSwapChain >= This->nswapchains); 722 user_warn(!pRamp); 723 724 if (pRamp && (iSwapChain < This->nswapchains)) { 725 struct NineSwapChain9 *swap = This->swapchains[iSwapChain]; 726 swap->gamma = *pRamp; 727 ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow); 728 } 729} 730 731void WINAPI 732NineDevice9_GetGammaRamp( struct NineDevice9 *This, 733 UINT iSwapChain, 734 D3DGAMMARAMP *pRamp ) 735{ 736 DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp); 737 738 user_warn(iSwapChain >= This->nswapchains); 739 user_warn(!pRamp); 740 741 if (pRamp && (iSwapChain < This->nswapchains)) 742 *pRamp = This->swapchains[iSwapChain]->gamma; 743} 744 745HRESULT WINAPI 746NineDevice9_CreateTexture( struct NineDevice9 *This, 747 UINT Width, 748 UINT Height, 749 UINT Levels, 750 DWORD Usage, 751 D3DFORMAT Format, 752 D3DPOOL Pool, 753 IDirect3DTexture9 **ppTexture, 754 HANDLE *pSharedHandle ) 755{ 756 struct NineTexture9 *tex; 757 HRESULT hr; 758 759 DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " 760 "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels, 761 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 762 nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle); 763 764 Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP | 765 D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 766 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI; 767 768 user_assert(Width && Height, D3DERR_INVALIDCALL); 769 user_assert(!pSharedHandle || This->ex, D3DERR_INVALIDCALL); 770 /* When is used shared handle, Pool must be 771 * SYSTEMMEM with Levels 1 or DEFAULT with any Levels */ 772 user_assert(!pSharedHandle || Pool != D3DPOOL_SYSTEMMEM || Levels == 1, 773 D3DERR_INVALIDCALL); 774 user_assert(!pSharedHandle || Pool == D3DPOOL_SYSTEMMEM || Pool == D3DPOOL_DEFAULT, 775 D3DERR_INVALIDCALL); 776 user_assert((Usage != D3DUSAGE_AUTOGENMIPMAP || Levels <= 1), D3DERR_INVALIDCALL); 777 778 hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool, 779 &tex, pSharedHandle); 780 if (SUCCEEDED(hr)) 781 *ppTexture = (IDirect3DTexture9 *)tex; 782 783 return hr; 784} 785 786HRESULT WINAPI 787NineDevice9_CreateVolumeTexture( struct NineDevice9 *This, 788 UINT Width, 789 UINT Height, 790 UINT Depth, 791 UINT Levels, 792 DWORD Usage, 793 D3DFORMAT Format, 794 D3DPOOL Pool, 795 IDirect3DVolumeTexture9 **ppVolumeTexture, 796 HANDLE *pSharedHandle ) 797{ 798 struct NineVolumeTexture9 *tex; 799 HRESULT hr; 800 801 DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s " 802 "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels, 803 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 804 nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle); 805 806 Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 807 D3DUSAGE_SOFTWAREPROCESSING; 808 809 user_assert(Width && Height && Depth, D3DERR_INVALIDCALL); 810 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 811 812 hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels, 813 Usage, Format, Pool, &tex, pSharedHandle); 814 if (SUCCEEDED(hr)) 815 *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex; 816 817 return hr; 818} 819 820HRESULT WINAPI 821NineDevice9_CreateCubeTexture( struct NineDevice9 *This, 822 UINT EdgeLength, 823 UINT Levels, 824 DWORD Usage, 825 D3DFORMAT Format, 826 D3DPOOL Pool, 827 IDirect3DCubeTexture9 **ppCubeTexture, 828 HANDLE *pSharedHandle ) 829{ 830 struct NineCubeTexture9 *tex; 831 HRESULT hr; 832 833 DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p " 834 "pSharedHandle=%p\n", This, EdgeLength, Levels, 835 nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), 836 nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle); 837 838 Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC | 839 D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET | 840 D3DUSAGE_SOFTWAREPROCESSING; 841 842 user_assert(EdgeLength, D3DERR_INVALIDCALL); 843 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 844 845 hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool, 846 &tex, pSharedHandle); 847 if (SUCCEEDED(hr)) 848 *ppCubeTexture = (IDirect3DCubeTexture9 *)tex; 849 850 return hr; 851} 852 853HRESULT WINAPI 854NineDevice9_CreateVertexBuffer( struct NineDevice9 *This, 855 UINT Length, 856 DWORD Usage, 857 DWORD FVF, 858 D3DPOOL Pool, 859 IDirect3DVertexBuffer9 **ppVertexBuffer, 860 HANDLE *pSharedHandle ) 861{ 862 struct NineVertexBuffer9 *buf; 863 HRESULT hr; 864 D3DVERTEXBUFFER_DESC desc; 865 866 DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n", 867 This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); 868 869 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 870 871 desc.Format = D3DFMT_VERTEXDATA; 872 desc.Type = D3DRTYPE_VERTEXBUFFER; 873 desc.Usage = Usage & 874 (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 875 D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 876 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI | 877 D3DUSAGE_WRITEONLY); 878 desc.Pool = Pool; 879 desc.Size = Length; 880 desc.FVF = FVF; 881 882 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 883 user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 884 885 hr = NineVertexBuffer9_new(This, &desc, &buf); 886 if (SUCCEEDED(hr)) 887 *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf; 888 return hr; 889} 890 891HRESULT WINAPI 892NineDevice9_CreateIndexBuffer( struct NineDevice9 *This, 893 UINT Length, 894 DWORD Usage, 895 D3DFORMAT Format, 896 D3DPOOL Pool, 897 IDirect3DIndexBuffer9 **ppIndexBuffer, 898 HANDLE *pSharedHandle ) 899{ 900 struct NineIndexBuffer9 *buf; 901 HRESULT hr; 902 D3DINDEXBUFFER_DESC desc; 903 904 DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p " 905 "pSharedHandle=%p\n", This, Length, Usage, 906 d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle); 907 908 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE); 909 910 desc.Format = Format; 911 desc.Type = D3DRTYPE_INDEXBUFFER; 912 desc.Usage = Usage & 913 (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | 914 D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | 915 D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY); 916 desc.Pool = Pool; 917 desc.Size = Length; 918 919 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 920 user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL); 921 922 hr = NineIndexBuffer9_new(This, &desc, &buf); 923 if (SUCCEEDED(hr)) 924 *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf; 925 return hr; 926} 927 928static HRESULT 929create_zs_or_rt_surface(struct NineDevice9 *This, 930 unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */ 931 D3DPOOL Pool, 932 UINT Width, UINT Height, 933 D3DFORMAT Format, 934 D3DMULTISAMPLE_TYPE MultiSample, 935 DWORD MultisampleQuality, 936 BOOL Discard_or_Lockable, 937 IDirect3DSurface9 **ppSurface, 938 HANDLE *pSharedHandle) 939{ 940 struct NineSurface9 *surface; 941 struct pipe_screen *screen = This->screen; 942 struct pipe_resource *resource = NULL; 943 HRESULT hr; 944 D3DSURFACE_DESC desc; 945 struct pipe_resource templ; 946 947 DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u " 948 "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n", 949 This, type, nine_D3DPOOL_to_str(Pool), Width, Height, 950 d3dformat_to_string(Format), MultiSample, MultisampleQuality, 951 Discard_or_Lockable, ppSurface, pSharedHandle); 952 953 if (pSharedHandle) 954 DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n"); 955 956 user_assert(Width && Height, D3DERR_INVALIDCALL); 957 user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 958 959 templ.target = PIPE_TEXTURE_2D; 960 templ.format = d3d9_to_pipe_format(Format); 961 templ.width0 = Width; 962 templ.height0 = Height; 963 templ.depth0 = 1; 964 templ.array_size = 1; 965 templ.last_level = 0; 966 templ.nr_samples = (unsigned)MultiSample; 967 templ.usage = PIPE_USAGE_DEFAULT; 968 templ.flags = 0; 969 templ.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ 970 switch (type) { 971 case 0: templ.bind |= PIPE_BIND_RENDER_TARGET; break; 972 case 1: templ.bind |= PIPE_BIND_DEPTH_STENCIL; break; 973 default: 974 assert(type == 2); 975 break; 976 } 977 978 desc.Format = Format; 979 desc.Type = D3DRTYPE_SURFACE; 980 desc.Usage = 0; 981 desc.Pool = Pool; 982 desc.MultiSampleType = MultiSample; 983 desc.MultiSampleQuality = MultisampleQuality; 984 desc.Width = Width; 985 desc.Height = Height; 986 switch (type) { 987 case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break; 988 case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break; 989 default: break; 990 } 991 992 if (Pool == D3DPOOL_DEFAULT && Format != D3DFMT_NULL) { 993 /* resource_create doesn't return an error code, so check format here */ 994 user_assert(CHECK_PIPE_RESOURCE_TEMPLATE(templ), D3DERR_INVALIDCALL); 995 resource = screen->resource_create(screen, &templ); 996 user_assert(resource, D3DERR_OUTOFVIDEOMEMORY); 997 if (Discard_or_Lockable && (desc.Usage & D3DUSAGE_RENDERTARGET)) 998 resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; 999 } else { 1000 resource = NULL; 1001 } 1002 hr = NineSurface9_new(This, NULL, resource, NULL, 0, 0, 0, &desc, &surface); 1003 pipe_resource_reference(&resource, NULL); 1004 1005 if (SUCCEEDED(hr)) 1006 *ppSurface = (IDirect3DSurface9 *)surface; 1007 return hr; 1008} 1009 1010HRESULT WINAPI 1011NineDevice9_CreateRenderTarget( struct NineDevice9 *This, 1012 UINT Width, 1013 UINT Height, 1014 D3DFORMAT Format, 1015 D3DMULTISAMPLE_TYPE MultiSample, 1016 DWORD MultisampleQuality, 1017 BOOL Lockable, 1018 IDirect3DSurface9 **ppSurface, 1019 HANDLE *pSharedHandle ) 1020{ 1021 return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT, 1022 Width, Height, Format, 1023 MultiSample, MultisampleQuality, 1024 Lockable, ppSurface, pSharedHandle); 1025} 1026 1027HRESULT WINAPI 1028NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This, 1029 UINT Width, 1030 UINT Height, 1031 D3DFORMAT Format, 1032 D3DMULTISAMPLE_TYPE MultiSample, 1033 DWORD MultisampleQuality, 1034 BOOL Discard, 1035 IDirect3DSurface9 **ppSurface, 1036 HANDLE *pSharedHandle ) 1037{ 1038 return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT, 1039 Width, Height, Format, 1040 MultiSample, MultisampleQuality, 1041 Discard, ppSurface, pSharedHandle); 1042} 1043 1044HRESULT WINAPI 1045NineDevice9_UpdateSurface( struct NineDevice9 *This, 1046 IDirect3DSurface9 *pSourceSurface, 1047 const RECT *pSourceRect, 1048 IDirect3DSurface9 *pDestinationSurface, 1049 const POINT *pDestPoint ) 1050{ 1051 struct NineSurface9 *dst = NineSurface9(pDestinationSurface); 1052 struct NineSurface9 *src = NineSurface9(pSourceSurface); 1053 1054 DBG("This=%p pSourceSurface=%p pDestinationSurface=%p " 1055 "pSourceRect=%p pDestPoint=%p\n", This, 1056 pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint); 1057 if (pSourceRect) 1058 DBG("pSourceRect = (%u,%u)-(%u,%u)\n", 1059 pSourceRect->left, pSourceRect->top, 1060 pSourceRect->right, pSourceRect->bottom); 1061 if (pDestPoint) 1062 DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y); 1063 1064 user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1065 user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1066 1067 user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 1068 user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL); 1069 1070 return NineSurface9_CopySurface(dst, src, pDestPoint, pSourceRect); 1071} 1072 1073HRESULT WINAPI 1074NineDevice9_UpdateTexture( struct NineDevice9 *This, 1075 IDirect3DBaseTexture9 *pSourceTexture, 1076 IDirect3DBaseTexture9 *pDestinationTexture ) 1077{ 1078 struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture); 1079 struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture); 1080 unsigned l, m; 1081 unsigned last_level = dstb->base.info.last_level; 1082 1083 DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This, 1084 pSourceTexture, pDestinationTexture); 1085 1086 user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL); 1087 1088 user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1089 user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1090 1091 if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) { 1092 /* Only the first level is updated, the others regenerated. */ 1093 last_level = 0; 1094 } else { 1095 user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); 1096 } 1097 1098 user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL); 1099 1100 /* TODO: We can restrict the update to the dirty portions of the source. 1101 * Yes, this seems silly, but it's what MSDN says ... 1102 */ 1103 1104 /* Find src level that matches dst level 0: */ 1105 user_assert(srcb->base.info.width0 >= dstb->base.info.width0 && 1106 srcb->base.info.height0 >= dstb->base.info.height0 && 1107 srcb->base.info.depth0 >= dstb->base.info.depth0, 1108 D3DERR_INVALIDCALL); 1109 for (m = 0; m <= srcb->base.info.last_level; ++m) { 1110 unsigned w = u_minify(srcb->base.info.width0, m); 1111 unsigned h = u_minify(srcb->base.info.height0, m); 1112 unsigned d = u_minify(srcb->base.info.depth0, m); 1113 1114 if (w == dstb->base.info.width0 && 1115 h == dstb->base.info.height0 && 1116 d == dstb->base.info.depth0) 1117 break; 1118 } 1119 user_assert(m <= srcb->base.info.last_level, D3DERR_INVALIDCALL); 1120 1121 last_level = MIN2(last_level, srcb->base.info.last_level - m); 1122 1123 if (dstb->base.type == D3DRTYPE_TEXTURE) { 1124 struct NineTexture9 *dst = NineTexture9(dstb); 1125 struct NineTexture9 *src = NineTexture9(srcb); 1126 1127 for (l = 0; l <= last_level; ++l, ++m) 1128 NineSurface9_CopySurface(dst->surfaces[l], 1129 src->surfaces[m], NULL, NULL); 1130 } else 1131 if (dstb->base.type == D3DRTYPE_CUBETEXTURE) { 1132 struct NineCubeTexture9 *dst = NineCubeTexture9(dstb); 1133 struct NineCubeTexture9 *src = NineCubeTexture9(srcb); 1134 unsigned z; 1135 1136 /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */ 1137 for (z = 0; z < 6; ++z) { 1138 for (l = 0; l <= last_level; ++l, ++m) { 1139 NineSurface9_CopySurface(dst->surfaces[l * 6 + z], 1140 src->surfaces[m * 6 + z], NULL, NULL); 1141 } 1142 m -= l; 1143 } 1144 } else 1145 if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) { 1146 struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb); 1147 struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb); 1148 1149 for (l = 0; l <= last_level; ++l, ++m) 1150 NineVolume9_CopyVolume(dst->volumes[l], 1151 src->volumes[m], 0, 0, 0, NULL); 1152 } else{ 1153 assert(!"invalid texture type"); 1154 } 1155 1156 if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) 1157 NineBaseTexture9_GenerateMipSubLevels(dstb); 1158 1159 return D3D_OK; 1160} 1161 1162HRESULT WINAPI 1163NineDevice9_GetRenderTargetData( struct NineDevice9 *This, 1164 IDirect3DSurface9 *pRenderTarget, 1165 IDirect3DSurface9 *pDestSurface ) 1166{ 1167 struct NineSurface9 *dst = NineSurface9(pDestSurface); 1168 struct NineSurface9 *src = NineSurface9(pRenderTarget); 1169 1170 DBG("This=%p pRenderTarget=%p pDestSurface=%p\n", 1171 This, pRenderTarget, pDestSurface); 1172 1173 user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1174 user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1175 1176 user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 1177 user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL); 1178 1179 return NineSurface9_CopySurface(dst, src, NULL, NULL); 1180} 1181 1182HRESULT WINAPI 1183NineDevice9_GetFrontBufferData( struct NineDevice9 *This, 1184 UINT iSwapChain, 1185 IDirect3DSurface9 *pDestSurface ) 1186{ 1187 DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This, 1188 iSwapChain, pDestSurface); 1189 1190 user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL); 1191 user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL); 1192 1193 return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain], 1194 pDestSurface); 1195} 1196 1197HRESULT WINAPI 1198NineDevice9_StretchRect( struct NineDevice9 *This, 1199 IDirect3DSurface9 *pSourceSurface, 1200 const RECT *pSourceRect, 1201 IDirect3DSurface9 *pDestSurface, 1202 const RECT *pDestRect, 1203 D3DTEXTUREFILTERTYPE Filter ) 1204{ 1205 struct pipe_screen *screen = This->screen; 1206 struct pipe_context *pipe = This->pipe; 1207 struct NineSurface9 *dst = NineSurface9(pDestSurface); 1208 struct NineSurface9 *src = NineSurface9(pSourceSurface); 1209 struct pipe_resource *dst_res = NineSurface9_GetResource(dst); 1210 struct pipe_resource *src_res = NineSurface9_GetResource(src); 1211 const boolean zs = util_format_is_depth_or_stencil(dst_res->format); 1212 struct pipe_blit_info blit; 1213 boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE; 1214 1215 DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p " 1216 "pDestRect=%p Filter=%u\n", 1217 This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); 1218 if (pSourceRect) 1219 DBG("pSourceRect=(%u,%u)-(%u,%u)\n", 1220 pSourceRect->left, pSourceRect->top, 1221 pSourceRect->right, pSourceRect->bottom); 1222 if (pDestRect) 1223 DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top, 1224 pDestRect->right, pDestRect->bottom); 1225 1226 user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL); 1227 user_assert(!zs || !pSourceRect || 1228 (pSourceRect->left == 0 && 1229 pSourceRect->top == 0 && 1230 pSourceRect->right == src->desc.Width && 1231 pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL); 1232 user_assert(!zs || !pDestRect || 1233 (pDestRect->left == 0 && 1234 pDestRect->top == 0 && 1235 pDestRect->right == dst->desc.Width && 1236 pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL); 1237 user_assert(!zs || 1238 (dst->desc.Width == src->desc.Width && 1239 dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL); 1240 user_assert(zs || !util_format_is_depth_or_stencil(src_res->format), 1241 D3DERR_INVALIDCALL); 1242 user_assert(!zs || dst->desc.Format == src->desc.Format, 1243 D3DERR_INVALIDCALL); 1244 user_assert(screen->is_format_supported(screen, src_res->format, 1245 src_res->target, 1246 src_res->nr_samples, 1247 PIPE_BIND_SAMPLER_VIEW), 1248 D3DERR_INVALIDCALL); 1249 user_assert(dst->base.pool == D3DPOOL_DEFAULT && 1250 src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1251 1252 /* We might want to permit these, but wine thinks we shouldn't. */ 1253 user_assert(!pDestRect || 1254 (pDestRect->left <= pDestRect->right && 1255 pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL); 1256 user_assert(!pSourceRect || 1257 (pSourceRect->left <= pSourceRect->right && 1258 pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL); 1259 1260 blit.dst.resource = dst_res; 1261 blit.dst.level = dst->level; 1262 blit.dst.box.z = dst->layer; 1263 blit.dst.box.depth = 1; 1264 blit.dst.format = dst_res->format; 1265 if (pDestRect) { 1266 flip_x = pDestRect->left > pDestRect->right; 1267 if (flip_x) { 1268 blit.dst.box.x = pDestRect->right; 1269 blit.dst.box.width = pDestRect->left - pDestRect->right; 1270 } else { 1271 blit.dst.box.x = pDestRect->left; 1272 blit.dst.box.width = pDestRect->right - pDestRect->left; 1273 } 1274 flip_y = pDestRect->top > pDestRect->bottom; 1275 if (flip_y) { 1276 blit.dst.box.y = pDestRect->bottom; 1277 blit.dst.box.height = pDestRect->top - pDestRect->bottom; 1278 } else { 1279 blit.dst.box.y = pDestRect->top; 1280 blit.dst.box.height = pDestRect->bottom - pDestRect->top; 1281 } 1282 } else { 1283 blit.dst.box.x = 0; 1284 blit.dst.box.y = 0; 1285 blit.dst.box.width = dst->desc.Width; 1286 blit.dst.box.height = dst->desc.Height; 1287 } 1288 blit.src.resource = src_res; 1289 blit.src.level = src->level; 1290 blit.src.box.z = src->layer; 1291 blit.src.box.depth = 1; 1292 blit.src.format = src_res->format; 1293 if (pSourceRect) { 1294 if (flip_x ^ (pSourceRect->left > pSourceRect->right)) { 1295 blit.src.box.x = pSourceRect->right; 1296 blit.src.box.width = pSourceRect->left - pSourceRect->right; 1297 } else { 1298 blit.src.box.x = pSourceRect->left; 1299 blit.src.box.width = pSourceRect->right - pSourceRect->left; 1300 } 1301 if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) { 1302 blit.src.box.y = pSourceRect->bottom; 1303 blit.src.box.height = pSourceRect->top - pSourceRect->bottom; 1304 } else { 1305 blit.src.box.y = pSourceRect->top; 1306 blit.src.box.height = pSourceRect->bottom - pSourceRect->top; 1307 } 1308 } else { 1309 blit.src.box.x = flip_x ? src->desc.Width : 0; 1310 blit.src.box.y = flip_y ? src->desc.Height : 0; 1311 blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width; 1312 blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height; 1313 } 1314 blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA; 1315 blit.filter = Filter == D3DTEXF_LINEAR ? 1316 PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST; 1317 blit.scissor_enable = FALSE; 1318 1319 /* If both of a src and dst dimension are negative, flip them. */ 1320 if (blit.dst.box.width < 0 && blit.src.box.width < 0) { 1321 blit.dst.box.width = -blit.dst.box.width; 1322 blit.src.box.width = -blit.src.box.width; 1323 } 1324 if (blit.dst.box.height < 0 && blit.src.box.height < 0) { 1325 blit.dst.box.height = -blit.dst.box.height; 1326 blit.src.box.height = -blit.src.box.height; 1327 } 1328 scaled = 1329 blit.dst.box.width != blit.src.box.width || 1330 blit.dst.box.height != blit.src.box.height; 1331 1332 user_assert(!scaled || dst != src, D3DERR_INVALIDCALL); 1333 user_assert(!scaled || 1334 !NineSurface9_IsOffscreenPlain(dst) || 1335 NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL); 1336 user_assert(!scaled || 1337 (!util_format_is_compressed(dst->base.info.format) && 1338 !util_format_is_compressed(src->base.info.format)), 1339 D3DERR_INVALIDCALL); 1340 1341 user_warn(src == dst && 1342 u_box_test_intersection_2d(&blit.src.box, &blit.dst.box)); 1343 1344 /* Check for clipping/clamping: */ 1345 { 1346 struct pipe_box box; 1347 int xy; 1348 1349 xy = u_box_clip_2d(&box, &blit.dst.box, 1350 dst->desc.Width, dst->desc.Height); 1351 if (xy < 0) 1352 return D3D_OK; 1353 if (xy == 0) 1354 xy = u_box_clip_2d(&box, &blit.src.box, 1355 src->desc.Width, src->desc.Height); 1356 clamped = !!xy; 1357 } 1358 1359 ms = (dst->desc.MultiSampleType | 1) != (src->desc.MultiSampleType | 1); 1360 1361 if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { 1362 DBG("using pipe->blit()\n"); 1363 /* TODO: software scaling */ 1364 user_assert(screen->is_format_supported(screen, dst_res->format, 1365 dst_res->target, 1366 dst_res->nr_samples, 1367 zs ? PIPE_BIND_DEPTH_STENCIL : 1368 PIPE_BIND_RENDER_TARGET), 1369 D3DERR_INVALIDCALL); 1370 1371 pipe->blit(pipe, &blit); 1372 } else { 1373 assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 && 1374 blit.src.box.x >= 0 && blit.src.box.y >= 0 && 1375 blit.dst.box.x + blit.dst.box.width <= dst->desc.Width && 1376 blit.src.box.x + blit.src.box.width <= src->desc.Width && 1377 blit.dst.box.y + blit.dst.box.height <= dst->desc.Height && 1378 blit.src.box.y + blit.src.box.height <= src->desc.Height); 1379 /* Or drivers might crash ... */ 1380 DBG("Using resource_copy_region.\n"); 1381 pipe->resource_copy_region(pipe, 1382 blit.dst.resource, blit.dst.level, 1383 blit.dst.box.x, blit.dst.box.y, blit.dst.box.z, 1384 blit.src.resource, blit.src.level, 1385 &blit.src.box); 1386 } 1387 1388 return D3D_OK; 1389} 1390 1391HRESULT WINAPI 1392NineDevice9_ColorFill( struct NineDevice9 *This, 1393 IDirect3DSurface9 *pSurface, 1394 const RECT *pRect, 1395 D3DCOLOR color ) 1396{ 1397 struct pipe_context *pipe = This->pipe; 1398 struct NineSurface9 *surf = NineSurface9(pSurface); 1399 struct pipe_surface *psurf; 1400 unsigned x, y, w, h; 1401 union pipe_color_union rgba; 1402 boolean fallback; 1403 1404 DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This, 1405 pSurface, pRect, color); 1406 if (pRect) 1407 DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top, 1408 pRect->right, pRect->bottom); 1409 1410 user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); 1411 1412 user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) || 1413 NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL); 1414 1415 if (pRect) { 1416 x = pRect->left; 1417 y = pRect->top; 1418 w = pRect->right - pRect->left; 1419 h = pRect->bottom - pRect->top; 1420 } else{ 1421 x = 0; 1422 y = 0; 1423 w = surf->desc.Width; 1424 h = surf->desc.Height; 1425 } 1426 d3dcolor_to_pipe_color_union(&rgba, color); 1427 1428 fallback = 1429 !This->screen->is_format_supported(This->screen, surf->base.info.format, 1430 surf->base.info.target, 1431 surf->base.info.nr_samples, 1432 PIPE_BIND_RENDER_TARGET); 1433 if (!fallback) { 1434 psurf = NineSurface9_GetSurface(surf, 0); 1435 if (!psurf) 1436 fallback = TRUE; 1437 } 1438 1439 if (!fallback) { 1440 pipe->clear_render_target(pipe, psurf, &rgba, x, y, w, h); 1441 } else { 1442 D3DLOCKED_RECT lock; 1443 union util_color uc; 1444 HRESULT hr; 1445 /* XXX: lock pRect and fix util_fill_rect */ 1446 hr = NineSurface9_LockRect(surf, &lock, NULL, 0); 1447 if (FAILED(hr)) 1448 return hr; 1449 util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24, 1450 surf->base.info.format, &uc); 1451 util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch, 1452 x, y, w, h, &uc); 1453 NineSurface9_UnlockRect(surf); 1454 } 1455 1456 return D3D_OK; 1457} 1458 1459HRESULT WINAPI 1460NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This, 1461 UINT Width, 1462 UINT Height, 1463 D3DFORMAT Format, 1464 D3DPOOL Pool, 1465 IDirect3DSurface9 **ppSurface, 1466 HANDLE *pSharedHandle ) 1467{ 1468 HRESULT hr; 1469 1470 DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u " 1471 "ppSurface=%p pSharedHandle=%p\n", This, 1472 Width, Height, d3dformat_to_string(Format), Format, Pool, 1473 ppSurface, pSharedHandle); 1474 1475 user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT 1476 || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 1477 user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL); 1478 1479 /* Can be used with StretchRect and ColorFill. It's also always lockable. 1480 */ 1481 hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height, 1482 Format, 1483 D3DMULTISAMPLE_NONE, 0, 1484 TRUE, 1485 ppSurface, pSharedHandle); 1486 if (FAILED(hr)) 1487 DBG("Failed to create surface.\n"); 1488 return hr; 1489} 1490 1491HRESULT WINAPI 1492NineDevice9_SetRenderTarget( struct NineDevice9 *This, 1493 DWORD RenderTargetIndex, 1494 IDirect3DSurface9 *pRenderTarget ) 1495{ 1496 struct NineSurface9 *rt = NineSurface9(pRenderTarget); 1497 const unsigned i = RenderTargetIndex; 1498 1499 DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This, 1500 RenderTargetIndex, pRenderTarget); 1501 1502 user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 1503 user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL); 1504 user_assert(!pRenderTarget || 1505 rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL); 1506 1507 if (i == 0) { 1508 This->state.viewport.X = 0; 1509 This->state.viewport.Y = 0; 1510 This->state.viewport.Width = rt->desc.Width; 1511 This->state.viewport.Height = rt->desc.Height; 1512 This->state.viewport.MinZ = 0.0f; 1513 This->state.viewport.MaxZ = 1.0f; 1514 1515 This->state.scissor.minx = 0; 1516 This->state.scissor.miny = 0; 1517 This->state.scissor.maxx = rt->desc.Width; 1518 This->state.scissor.maxy = rt->desc.Height; 1519 1520 This->state.changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR; 1521 } 1522 1523 if (This->state.rt[i] != NineSurface9(pRenderTarget)) { 1524 nine_bind(&This->state.rt[i], pRenderTarget); 1525 This->state.changed.group |= NINE_STATE_FB; 1526 } 1527 return D3D_OK; 1528} 1529 1530HRESULT WINAPI 1531NineDevice9_GetRenderTarget( struct NineDevice9 *This, 1532 DWORD RenderTargetIndex, 1533 IDirect3DSurface9 **ppRenderTarget ) 1534{ 1535 const unsigned i = RenderTargetIndex; 1536 1537 user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL); 1538 user_assert(ppRenderTarget, D3DERR_INVALIDCALL); 1539 1540 *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i]; 1541 if (!This->state.rt[i]) 1542 return D3DERR_NOTFOUND; 1543 1544 NineUnknown_AddRef(NineUnknown(This->state.rt[i])); 1545 return D3D_OK; 1546} 1547 1548HRESULT WINAPI 1549NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This, 1550 IDirect3DSurface9 *pNewZStencil ) 1551{ 1552 DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil); 1553 1554 if (This->state.ds != NineSurface9(pNewZStencil)) { 1555 nine_bind(&This->state.ds, pNewZStencil); 1556 This->state.changed.group |= NINE_STATE_FB; 1557 } 1558 return D3D_OK; 1559} 1560 1561HRESULT WINAPI 1562NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This, 1563 IDirect3DSurface9 **ppZStencilSurface ) 1564{ 1565 user_assert(ppZStencilSurface, D3DERR_INVALIDCALL); 1566 1567 *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds; 1568 if (!This->state.ds) 1569 return D3DERR_NOTFOUND; 1570 1571 NineUnknown_AddRef(NineUnknown(This->state.ds)); 1572 return D3D_OK; 1573} 1574 1575HRESULT WINAPI 1576NineDevice9_BeginScene( struct NineDevice9 *This ) 1577{ 1578 DBG("This=%p\n", This); 1579 user_assert(!This->in_scene, D3DERR_INVALIDCALL); 1580 This->in_scene = TRUE; 1581 /* Do we want to do anything else here ? */ 1582 return D3D_OK; 1583} 1584 1585HRESULT WINAPI 1586NineDevice9_EndScene( struct NineDevice9 *This ) 1587{ 1588 DBG("This=%p\n", This); 1589 user_assert(This->in_scene, D3DERR_INVALIDCALL); 1590 This->in_scene = FALSE; 1591 return D3D_OK; 1592} 1593 1594HRESULT WINAPI 1595NineDevice9_Clear( struct NineDevice9 *This, 1596 DWORD Count, 1597 const D3DRECT *pRects, 1598 DWORD Flags, 1599 D3DCOLOR Color, 1600 float Z, 1601 DWORD Stencil ) 1602{ 1603 struct pipe_context *pipe = This->pipe; 1604 struct NineSurface9 *zsbuf = This->state.ds; 1605 unsigned bufs = 0; 1606 unsigned r, i; 1607 union pipe_color_union rgba; 1608 D3DRECT rect; 1609 1610 DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", 1611 This, Count, pRects, Flags, Color, Z, Stencil); 1612 1613 user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL), 1614 D3DERR_INVALIDCALL); 1615 user_assert(!(Flags & D3DCLEAR_STENCIL) || 1616 (zsbuf && 1617 util_format_is_depth_and_stencil(zsbuf->base.info.format)), 1618 D3DERR_INVALIDCALL); 1619#ifdef NINE_STRICT 1620 user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL); 1621#else 1622 user_warn((pRects && !Count) || (!pRects && Count)); 1623 if (pRects && !Count) 1624 return D3D_OK; 1625 if (!pRects) 1626 Count = 0; 1627#endif 1628 1629 if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; 1630 if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; 1631 if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; 1632 if (!bufs) 1633 return D3D_OK; 1634 d3dcolor_to_pipe_color_union(&rgba, Color); 1635 1636 nine_update_state(This, NINE_STATE_FB); 1637 1638 rect.x1 = This->state.viewport.X; 1639 rect.y1 = This->state.viewport.Y; 1640 rect.x2 = This->state.viewport.Width + rect.x1; 1641 rect.y2 = This->state.viewport.Height + rect.y1; 1642 1643 /* Both rectangles apply, which is weird, but that's D3D9. */ 1644 if (This->state.rs[D3DRS_SCISSORTESTENABLE]) { 1645 rect.x1 = MAX2(rect.x1, This->state.scissor.minx); 1646 rect.y1 = MAX2(rect.y1, This->state.scissor.miny); 1647 rect.x2 = MIN2(rect.x2, This->state.scissor.maxx); 1648 rect.y2 = MIN2(rect.y2, This->state.scissor.maxy); 1649 } 1650 1651 if (Count) { 1652 /* Maybe apps like to specify a large rect ? */ 1653 if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && 1654 pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { 1655 DBG("First rect covers viewport.\n"); 1656 Count = 0; 1657 pRects = NULL; 1658 } 1659 } 1660 1661 if (rect.x1 >= This->state.fb.width || rect.y1 >= This->state.fb.height) 1662 return D3D_OK; 1663 if (!Count && 1664 rect.x1 == 0 && rect.x2 >= This->state.fb.width && 1665 rect.y1 == 0 && rect.y2 >= This->state.fb.height) { 1666 /* fast path, clears everything at once */ 1667 DBG("fast path\n"); 1668 pipe->clear(pipe, bufs, &rgba, Z, Stencil); 1669 return D3D_OK; 1670 } 1671 rect.x2 = MIN2(rect.x2, This->state.fb.width); 1672 rect.y2 = MIN2(rect.y2, This->state.fb.height); 1673 1674 if (!Count) { 1675 Count = 1; 1676 pRects = ▭ 1677 } 1678 1679 for (i = 0; (i < This->state.fb.nr_cbufs); ++i) { 1680 if (!This->state.fb.cbufs[i] || !(Flags & D3DCLEAR_TARGET)) 1681 continue; /* save space, compiler should hoist this */ 1682 for (r = 0; r < Count; ++r) { 1683 /* Don't trust users to pass these in the right order. */ 1684 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); 1685 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); 1686 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); 1687 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); 1688#ifndef NINE_LAX 1689 /* Drop negative rectangles (like wine expects). */ 1690 if (pRects[r].x1 > pRects[r].x2) continue; 1691 if (pRects[r].y1 > pRects[r].y2) continue; 1692#endif 1693 1694 x1 = MAX2(x1, rect.x1); 1695 y1 = MAX2(y1, rect.y1); 1696 x2 = MIN2(x2, rect.x2); 1697 y2 = MIN2(y2, rect.y2); 1698 1699 DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); 1700 pipe->clear_render_target(pipe, This->state.fb.cbufs[i], &rgba, 1701 x1, y1, x2 - x1, y2 - y1); 1702 } 1703 } 1704 if (!(Flags & NINED3DCLEAR_DEPTHSTENCIL)) 1705 return D3D_OK; 1706 1707 bufs &= PIPE_CLEAR_DEPTHSTENCIL; 1708 1709 for (r = 0; r < Count; ++r) { 1710 unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); 1711 unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); 1712 unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); 1713 unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); 1714#ifndef NINE_LAX 1715 /* Drop negative rectangles. */ 1716 if (pRects[r].x1 > pRects[r].x2) continue; 1717 if (pRects[r].y1 > pRects[r].y2) continue; 1718#endif 1719 1720 x1 = MIN2(x1, rect.x1); 1721 y1 = MIN2(y1, rect.y1); 1722 x2 = MIN2(x2, rect.x2); 1723 y2 = MIN2(y2, rect.y2); 1724 1725 pipe->clear_depth_stencil(pipe, This->state.fb.zsbuf, bufs, Z, Stencil, 1726 x1, y1, x2 - x1, y2 - y1); 1727 } 1728 return D3D_OK; 1729} 1730 1731HRESULT WINAPI 1732NineDevice9_SetTransform( struct NineDevice9 *This, 1733 D3DTRANSFORMSTATETYPE State, 1734 const D3DMATRIX *pMatrix ) 1735{ 1736 struct nine_state *state = This->update; 1737 D3DMATRIX *M = nine_state_access_transform(state, State, TRUE); 1738 1739 DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 1740 1741 user_assert(M, D3DERR_INVALIDCALL); 1742 1743 *M = *pMatrix; 1744 state->ff.changed.transform[State / 32] |= 1 << (State % 32); 1745 state->changed.group |= NINE_STATE_FF; 1746 1747 return D3D_OK; 1748} 1749 1750HRESULT WINAPI 1751NineDevice9_GetTransform( struct NineDevice9 *This, 1752 D3DTRANSFORMSTATETYPE State, 1753 D3DMATRIX *pMatrix ) 1754{ 1755 D3DMATRIX *M = nine_state_access_transform(&This->state, State, FALSE); 1756 user_assert(M, D3DERR_INVALIDCALL); 1757 *pMatrix = *M; 1758 return D3D_OK; 1759} 1760 1761HRESULT WINAPI 1762NineDevice9_MultiplyTransform( struct NineDevice9 *This, 1763 D3DTRANSFORMSTATETYPE State, 1764 const D3DMATRIX *pMatrix ) 1765{ 1766 struct nine_state *state = This->update; 1767 D3DMATRIX T; 1768 D3DMATRIX *M = nine_state_access_transform(state, State, TRUE); 1769 1770 DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix); 1771 1772 user_assert(M, D3DERR_INVALIDCALL); 1773 1774 nine_d3d_matrix_matrix_mul(&T, pMatrix, M); 1775 return NineDevice9_SetTransform(This, State, &T); 1776} 1777 1778HRESULT WINAPI 1779NineDevice9_SetViewport( struct NineDevice9 *This, 1780 const D3DVIEWPORT9 *pViewport ) 1781{ 1782 struct nine_state *state = This->update; 1783 1784 DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n", 1785 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, 1786 pViewport->MinZ, pViewport->MaxZ); 1787 1788 state->viewport = *pViewport; 1789 state->changed.group |= NINE_STATE_VIEWPORT; 1790 1791 return D3D_OK; 1792} 1793 1794HRESULT WINAPI 1795NineDevice9_GetViewport( struct NineDevice9 *This, 1796 D3DVIEWPORT9 *pViewport ) 1797{ 1798 *pViewport = This->state.viewport; 1799 return D3D_OK; 1800} 1801 1802HRESULT WINAPI 1803NineDevice9_SetMaterial( struct NineDevice9 *This, 1804 const D3DMATERIAL9 *pMaterial ) 1805{ 1806 struct nine_state *state = This->update; 1807 1808 DBG("This=%p pMaterial=%p\n", This, pMaterial); 1809 if (pMaterial) 1810 nine_dump_D3DMATERIAL9(DBG_FF, pMaterial); 1811 1812 user_assert(pMaterial, E_POINTER); 1813 1814 state->ff.material = *pMaterial; 1815 state->changed.group |= NINE_STATE_FF_MATERIAL; 1816 1817 return D3D_OK; 1818} 1819 1820HRESULT WINAPI 1821NineDevice9_GetMaterial( struct NineDevice9 *This, 1822 D3DMATERIAL9 *pMaterial ) 1823{ 1824 user_assert(pMaterial, E_POINTER); 1825 *pMaterial = This->state.ff.material; 1826 return D3D_OK; 1827} 1828 1829HRESULT WINAPI 1830NineDevice9_SetLight( struct NineDevice9 *This, 1831 DWORD Index, 1832 const D3DLIGHT9 *pLight ) 1833{ 1834 struct nine_state *state = This->update; 1835 1836 DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight); 1837 if (pLight) 1838 nine_dump_D3DLIGHT9(DBG_FF, pLight); 1839 1840 user_assert(pLight, D3DERR_INVALIDCALL); 1841 user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL); 1842 1843 user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */ 1844 1845 if (Index >= state->ff.num_lights) { 1846 unsigned n = state->ff.num_lights; 1847 unsigned N = Index + 1; 1848 1849 state->ff.light = REALLOC(state->ff.light, n * sizeof(D3DLIGHT9), 1850 N * sizeof(D3DLIGHT9)); 1851 if (!state->ff.light) 1852 return E_OUTOFMEMORY; 1853 state->ff.num_lights = N; 1854 1855 for (; n < Index; ++n) 1856 state->ff.light[n].Type = (D3DLIGHTTYPE)NINED3DLIGHT_INVALID; 1857 } 1858 state->ff.light[Index] = *pLight; 1859 1860 if (pLight->Type == D3DLIGHT_SPOT && pLight->Theta >= pLight->Phi) { 1861 DBG("Warning: clamping D3DLIGHT9.Theta\n"); 1862 state->ff.light[Index].Theta = state->ff.light[Index].Phi; 1863 } 1864 if (pLight->Type != D3DLIGHT_DIRECTIONAL && 1865 pLight->Attenuation0 == 0.0f && 1866 pLight->Attenuation1 == 0.0f && 1867 pLight->Attenuation2 == 0.0f) { 1868 DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n"); 1869 } 1870 1871 state->changed.group |= NINE_STATE_FF_LIGHTING; 1872 1873 return D3D_OK; 1874} 1875 1876HRESULT WINAPI 1877NineDevice9_GetLight( struct NineDevice9 *This, 1878 DWORD Index, 1879 D3DLIGHT9 *pLight ) 1880{ 1881 const struct nine_state *state = &This->state; 1882 1883 user_assert(pLight, D3DERR_INVALIDCALL); 1884 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 1885 user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 1886 D3DERR_INVALIDCALL); 1887 1888 *pLight = state->ff.light[Index]; 1889 1890 return D3D_OK; 1891} 1892 1893HRESULT WINAPI 1894NineDevice9_LightEnable( struct NineDevice9 *This, 1895 DWORD Index, 1896 BOOL Enable ) 1897{ 1898 struct nine_state *state = This->update; 1899 unsigned i; 1900 1901 DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable); 1902 1903 if (Index >= state->ff.num_lights || 1904 state->ff.light[Index].Type == NINED3DLIGHT_INVALID) { 1905 /* This should create a default light. */ 1906 D3DLIGHT9 light; 1907 memset(&light, 0, sizeof(light)); 1908 light.Type = D3DLIGHT_DIRECTIONAL; 1909 light.Diffuse.r = 1.0f; 1910 light.Diffuse.g = 1.0f; 1911 light.Diffuse.b = 1.0f; 1912 light.Direction.z = 1.0f; 1913 NineDevice9_SetLight(This, Index, &light); 1914 } 1915 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 1916 1917 for (i = 0; i < state->ff.num_lights_active; ++i) { 1918 if (state->ff.active_light[i] == Index) 1919 break; 1920 } 1921 1922 if (Enable) { 1923 if (i < state->ff.num_lights_active) 1924 return D3D_OK; 1925 /* XXX wine thinks this should still succeed: 1926 */ 1927 user_assert(i < NINE_MAX_LIGHTS_ACTIVE, D3DERR_INVALIDCALL); 1928 1929 state->ff.active_light[i] = Index; 1930 state->ff.num_lights_active++; 1931 } else { 1932 if (i == state->ff.num_lights_active) 1933 return D3D_OK; 1934 --state->ff.num_lights_active; 1935 for (; i < state->ff.num_lights_active; ++i) 1936 state->ff.active_light[i] = state->ff.active_light[i + 1]; 1937 } 1938 state->changed.group |= NINE_STATE_FF_LIGHTING; 1939 1940 return D3D_OK; 1941} 1942 1943HRESULT WINAPI 1944NineDevice9_GetLightEnable( struct NineDevice9 *This, 1945 DWORD Index, 1946 BOOL *pEnable ) 1947{ 1948 const struct nine_state *state = &This->state; 1949 unsigned i; 1950 1951 user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL); 1952 user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID, 1953 D3DERR_INVALIDCALL); 1954 1955 for (i = 0; i < state->ff.num_lights_active; ++i) 1956 if (state->ff.active_light[i] == Index) 1957 break; 1958 *pEnable = i != state->ff.num_lights_active; 1959 return D3D_OK; 1960} 1961 1962HRESULT WINAPI 1963NineDevice9_SetClipPlane( struct NineDevice9 *This, 1964 DWORD Index, 1965 const float *pPlane ) 1966{ 1967 struct nine_state *state = This->update; 1968 1969 DBG("This=%p Index=%u pPlane=%p(%f %f %f %f)\n", This, Index, pPlane, 1970 pPlane ? pPlane[0] : 0.0f, pPlane ? pPlane[1] : 0.0f, 1971 pPlane ? pPlane[2] : 0.0f, pPlane ? pPlane[3] : 0.0f); 1972 1973 user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 1974 1975 memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0])); 1976 state->changed.ucp |= 1 << Index; 1977 1978 return D3D_OK; 1979} 1980 1981HRESULT WINAPI 1982NineDevice9_GetClipPlane( struct NineDevice9 *This, 1983 DWORD Index, 1984 float *pPlane ) 1985{ 1986 const struct nine_state *state = &This->state; 1987 1988 user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL); 1989 1990 memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0])); 1991 return D3D_OK; 1992} 1993 1994HRESULT WINAPI 1995NineDevice9_SetRenderState( struct NineDevice9 *This, 1996 D3DRENDERSTATETYPE State, 1997 DWORD Value ) 1998{ 1999 struct nine_state *state = This->update; 2000 2001 DBG("This=%p State=%u(%s) Value=%08x\n", This, 2002 State, nine_d3drs_to_string(State), Value); 2003 2004 user_assert(State < Elements(state->rs), D3DERR_INVALIDCALL); 2005 2006 if (likely(state->rs[State] != Value) || unlikely(This->is_recording)) { 2007 state->rs[State] = Value; 2008 state->changed.rs[State / 32] |= 1 << (State % 32); 2009 state->changed.group |= nine_render_state_group[State]; 2010 } 2011 2012 return D3D_OK; 2013} 2014 2015HRESULT WINAPI 2016NineDevice9_GetRenderState( struct NineDevice9 *This, 2017 D3DRENDERSTATETYPE State, 2018 DWORD *pValue ) 2019{ 2020 user_assert(State < Elements(This->state.rs), D3DERR_INVALIDCALL); 2021 2022 *pValue = This->state.rs[State]; 2023 return D3D_OK; 2024} 2025 2026HRESULT WINAPI 2027NineDevice9_CreateStateBlock( struct NineDevice9 *This, 2028 D3DSTATEBLOCKTYPE Type, 2029 IDirect3DStateBlock9 **ppSB ) 2030{ 2031 struct NineStateBlock9 *nsb; 2032 struct nine_state *dst; 2033 HRESULT hr; 2034 enum nine_stateblock_type type; 2035 unsigned s; 2036 2037 DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB); 2038 2039 user_assert(Type == D3DSBT_ALL || 2040 Type == D3DSBT_VERTEXSTATE || 2041 Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL); 2042 2043 switch (Type) { 2044 case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break; 2045 case D3DSBT_PIXELSTATE: type = NINESBT_PIXELSTATE; break; 2046 default: 2047 type = NINESBT_ALL; 2048 break; 2049 } 2050 2051 hr = NineStateBlock9_new(This, &nsb, type); 2052 if (FAILED(hr)) 2053 return hr; 2054 *ppSB = (IDirect3DStateBlock9 *)nsb; 2055 dst = &nsb->state; 2056 2057 dst->changed.group = 2058 NINE_STATE_TEXTURE | 2059 NINE_STATE_SAMPLER; 2060 2061 if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) { 2062 dst->changed.group |= 2063 NINE_STATE_FF_LIGHTING | 2064 NINE_STATE_VS | NINE_STATE_VS_CONST | 2065 NINE_STATE_VDECL; 2066 /* TODO: texture/sampler state */ 2067 memcpy(dst->changed.rs, 2068 nine_render_states_vertex, sizeof(dst->changed.rs)); 2069 nine_ranges_insert(&dst->changed.vs_const_f, 0, This->max_vs_const_f, 2070 &This->range_pool); 2071 dst->changed.vs_const_i = 0xffff; 2072 dst->changed.vs_const_b = 0xffff; 2073 for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 2074 dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET; 2075 if (This->state.ff.num_lights) { 2076 dst->ff.num_lights = This->state.ff.num_lights; 2077 /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so 2078 * all currently existing lights will be captured 2079 */ 2080 dst->ff.light = CALLOC(This->state.ff.num_lights, 2081 sizeof(D3DLIGHT9)); 2082 if (!dst->ff.light) { 2083 nine_bind(ppSB, NULL); 2084 return E_OUTOFMEMORY; 2085 } 2086 } 2087 } 2088 if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) { 2089 dst->changed.group |= 2090 NINE_STATE_PS | NINE_STATE_PS_CONST; 2091 /* TODO: texture/sampler state */ 2092 memcpy(dst->changed.rs, 2093 nine_render_states_pixel, sizeof(dst->changed.rs)); 2094 nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f, 2095 &This->range_pool); 2096 dst->changed.ps_const_i = 0xffff; 2097 dst->changed.ps_const_b = 0xffff; 2098 for (s = 0; s < NINE_MAX_SAMPLERS; ++s) 2099 dst->changed.sampler[s] |= 0x1ffe; 2100 } 2101 if (Type == D3DSBT_ALL) { 2102 dst->changed.group |= 2103 NINE_STATE_VIEWPORT | 2104 NINE_STATE_SCISSOR | 2105 NINE_STATE_RASTERIZER | 2106 NINE_STATE_BLEND | 2107 NINE_STATE_DSA | 2108 NINE_STATE_IDXBUF | 2109 NINE_STATE_MATERIAL | 2110 NINE_STATE_BLEND_COLOR | 2111 NINE_STATE_SAMPLE_MASK; 2112 memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t)); 2113 dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1; 2114 dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1; 2115 dst->changed.stream_freq = dst->changed.vtxbuf; 2116 dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1; 2117 dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1; 2118 } 2119 NineStateBlock9_Capture(NineStateBlock9(*ppSB)); 2120 2121 /* TODO: fixed function state */ 2122 2123 return D3D_OK; 2124} 2125 2126HRESULT WINAPI 2127NineDevice9_BeginStateBlock( struct NineDevice9 *This ) 2128{ 2129 HRESULT hr; 2130 2131 DBG("This=%p\n", This); 2132 2133 user_assert(!This->record, D3DERR_INVALIDCALL); 2134 2135 hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM); 2136 if (FAILED(hr)) 2137 return hr; 2138 NineUnknown_ConvertRefToBind(NineUnknown(This->record)); 2139 2140 This->update = &This->record->state; 2141 This->is_recording = TRUE; 2142 2143 return D3D_OK; 2144} 2145 2146HRESULT WINAPI 2147NineDevice9_EndStateBlock( struct NineDevice9 *This, 2148 IDirect3DStateBlock9 **ppSB ) 2149{ 2150 DBG("This=%p ppSB=%p\n", This, ppSB); 2151 2152 user_assert(This->record, D3DERR_INVALIDCALL); 2153 2154 This->update = &This->state; 2155 This->is_recording = FALSE; 2156 2157 NineUnknown_AddRef(NineUnknown(This->record)); 2158 *ppSB = (IDirect3DStateBlock9 *)This->record; 2159 NineUnknown_Unbind(NineUnknown(This->record)); 2160 This->record = NULL; 2161 2162 return D3D_OK; 2163} 2164 2165HRESULT WINAPI 2166NineDevice9_SetClipStatus( struct NineDevice9 *This, 2167 const D3DCLIPSTATUS9 *pClipStatus ) 2168{ 2169 STUB(D3DERR_INVALIDCALL); 2170} 2171 2172HRESULT WINAPI 2173NineDevice9_GetClipStatus( struct NineDevice9 *This, 2174 D3DCLIPSTATUS9 *pClipStatus ) 2175{ 2176 STUB(D3DERR_INVALIDCALL); 2177} 2178 2179HRESULT WINAPI 2180NineDevice9_GetTexture( struct NineDevice9 *This, 2181 DWORD Stage, 2182 IDirect3DBaseTexture9 **ppTexture ) 2183{ 2184 user_assert(Stage < This->caps.MaxSimultaneousTextures || 2185 Stage == D3DDMAPSAMPLER || 2186 (Stage >= D3DVERTEXTEXTURESAMPLER0 && 2187 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2188 user_assert(ppTexture, D3DERR_INVALIDCALL); 2189 2190 if (Stage >= D3DDMAPSAMPLER) 2191 Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2192 2193 *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage]; 2194 2195 if (This->state.texture[Stage]) 2196 NineUnknown_AddRef(NineUnknown(This->state.texture[Stage])); 2197 return D3D_OK; 2198} 2199 2200HRESULT WINAPI 2201NineDevice9_SetTexture( struct NineDevice9 *This, 2202 DWORD Stage, 2203 IDirect3DBaseTexture9 *pTexture ) 2204{ 2205 struct nine_state *state = This->update; 2206 struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture); 2207 2208 DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture); 2209 2210 user_assert(Stage < This->caps.MaxSimultaneousTextures || 2211 Stage == D3DDMAPSAMPLER || 2212 (Stage >= D3DVERTEXTEXTURESAMPLER0 && 2213 Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2214 user_assert(!tex || tex->base.pool != D3DPOOL_SCRATCH, D3DERR_INVALIDCALL); 2215 2216 if (unlikely(tex && tex->base.pool == D3DPOOL_SYSTEMMEM)) { 2217 /* TODO: Currently not implemented. Better return error 2218 * with message telling what's wrong */ 2219 ERR("This=%p D3DPOOL_SYSTEMMEM not implemented for SetTexture\n", This); 2220 user_assert(tex->base.pool != D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); 2221 } 2222 2223 if (Stage >= D3DDMAPSAMPLER) 2224 Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2225 2226 if (!This->is_recording) { 2227 struct NineBaseTexture9 *old = state->texture[Stage]; 2228 if (old == tex) 2229 return D3D_OK; 2230 2231 state->samplers_shadow &= ~(1 << Stage); 2232 if (tex) { 2233 state->samplers_shadow |= tex->shadow << Stage; 2234 2235 if ((tex->dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list)) 2236 list_add(&tex->list, &This->update_textures); 2237 2238 tex->bind_count++; 2239 } 2240 if (old) 2241 old->bind_count--; 2242 } 2243 nine_bind(&state->texture[Stage], pTexture); 2244 2245 state->changed.texture |= 1 << Stage; 2246 state->changed.group |= NINE_STATE_TEXTURE; 2247 2248 return D3D_OK; 2249} 2250 2251HRESULT WINAPI 2252NineDevice9_GetTextureStageState( struct NineDevice9 *This, 2253 DWORD Stage, 2254 D3DTEXTURESTAGESTATETYPE Type, 2255 DWORD *pValue ) 2256{ 2257 const struct nine_state *state = &This->state; 2258 2259 user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL); 2260 user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 2261 2262 *pValue = state->ff.tex_stage[Stage][Type]; 2263 2264 return D3D_OK; 2265} 2266 2267HRESULT WINAPI 2268NineDevice9_SetTextureStageState( struct NineDevice9 *This, 2269 DWORD Stage, 2270 D3DTEXTURESTAGESTATETYPE Type, 2271 DWORD Value ) 2272{ 2273 struct nine_state *state = This->update; 2274 2275 DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value); 2276 nine_dump_D3DTSS_value(DBG_FF, Type, Value); 2277 2278 user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL); 2279 user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL); 2280 2281 state->ff.tex_stage[Stage][Type] = Value; 2282 2283 state->changed.group |= NINE_STATE_FF_PSSTAGES; 2284 state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32); 2285 2286 return D3D_OK; 2287} 2288 2289HRESULT WINAPI 2290NineDevice9_GetSamplerState( struct NineDevice9 *This, 2291 DWORD Sampler, 2292 D3DSAMPLERSTATETYPE Type, 2293 DWORD *pValue ) 2294{ 2295 user_assert(Sampler < This->caps.MaxSimultaneousTextures || 2296 Sampler == D3DDMAPSAMPLER || 2297 (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 2298 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2299 2300 if (Sampler >= D3DDMAPSAMPLER) 2301 Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2302 2303 *pValue = This->state.samp[Sampler][Type]; 2304 return D3D_OK; 2305} 2306 2307HRESULT WINAPI 2308NineDevice9_SetSamplerState( struct NineDevice9 *This, 2309 DWORD Sampler, 2310 D3DSAMPLERSTATETYPE Type, 2311 DWORD Value ) 2312{ 2313 struct nine_state *state = This->update; 2314 2315 DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This, 2316 Sampler, nine_D3DSAMP_to_str(Type), Value); 2317 2318 user_assert(Sampler < This->caps.MaxSimultaneousTextures || 2319 Sampler == D3DDMAPSAMPLER || 2320 (Sampler >= D3DVERTEXTEXTURESAMPLER0 && 2321 Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL); 2322 2323 if (Sampler >= D3DDMAPSAMPLER) 2324 Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS; 2325 2326 state->samp[Sampler][Type] = Value; 2327 state->changed.group |= NINE_STATE_SAMPLER; 2328 state->changed.sampler[Sampler] |= 1 << Type; 2329 2330 return D3D_OK; 2331} 2332 2333HRESULT WINAPI 2334NineDevice9_ValidateDevice( struct NineDevice9 *This, 2335 DWORD *pNumPasses ) 2336{ 2337 const struct nine_state *state = &This->state; 2338 unsigned i; 2339 unsigned w = 0, h = 0; 2340 2341 DBG("This=%p pNumPasses=%p\n", This, pNumPasses); 2342 2343 for (i = 0; i < Elements(state->samp); ++i) { 2344 if (state->samp[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE || 2345 state->samp[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE) 2346 return D3DERR_UNSUPPORTEDTEXTUREFILTER; 2347 } 2348 2349 for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { 2350 if (!state->rt[i]) 2351 continue; 2352 if (w == 0) { 2353 w = state->rt[i]->desc.Width; 2354 h = state->rt[i]->desc.Height; 2355 } else 2356 if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) { 2357 return D3DERR_CONFLICTINGRENDERSTATE; 2358 } 2359 } 2360 if (state->ds && 2361 (state->rs[D3DRS_ZENABLE] || state->rs[D3DRS_STENCILENABLE])) { 2362 if (w != 0 && 2363 (state->ds->desc.Width != w || state->ds->desc.Height != h)) 2364 return D3DERR_CONFLICTINGRENDERSTATE; 2365 } 2366 2367 if (pNumPasses) 2368 *pNumPasses = 1; 2369 2370 return D3D_OK; 2371} 2372 2373HRESULT WINAPI 2374NineDevice9_SetPaletteEntries( struct NineDevice9 *This, 2375 UINT PaletteNumber, 2376 const PALETTEENTRY *pEntries ) 2377{ 2378 STUB(D3D_OK); /* like wine */ 2379} 2380 2381HRESULT WINAPI 2382NineDevice9_GetPaletteEntries( struct NineDevice9 *This, 2383 UINT PaletteNumber, 2384 PALETTEENTRY *pEntries ) 2385{ 2386 STUB(D3DERR_INVALIDCALL); 2387} 2388 2389HRESULT WINAPI 2390NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This, 2391 UINT PaletteNumber ) 2392{ 2393 STUB(D3D_OK); /* like wine */ 2394} 2395 2396HRESULT WINAPI 2397NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This, 2398 UINT *PaletteNumber ) 2399{ 2400 STUB(D3DERR_INVALIDCALL); 2401} 2402 2403HRESULT WINAPI 2404NineDevice9_SetScissorRect( struct NineDevice9 *This, 2405 const RECT *pRect ) 2406{ 2407 struct nine_state *state = This->update; 2408 2409 DBG("x=(%u..%u) y=(%u..%u)\n", 2410 pRect->left, pRect->top, pRect->right, pRect->bottom); 2411 2412 state->scissor.minx = pRect->left; 2413 state->scissor.miny = pRect->top; 2414 state->scissor.maxx = pRect->right; 2415 state->scissor.maxy = pRect->bottom; 2416 2417 state->changed.group |= NINE_STATE_SCISSOR; 2418 2419 return D3D_OK; 2420} 2421 2422HRESULT WINAPI 2423NineDevice9_GetScissorRect( struct NineDevice9 *This, 2424 RECT *pRect ) 2425{ 2426 pRect->left = This->state.scissor.minx; 2427 pRect->top = This->state.scissor.miny; 2428 pRect->right = This->state.scissor.maxx; 2429 pRect->bottom = This->state.scissor.maxy; 2430 2431 return D3D_OK; 2432} 2433 2434HRESULT WINAPI 2435NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This, 2436 BOOL bSoftware ) 2437{ 2438 STUB(D3DERR_INVALIDCALL); 2439} 2440 2441BOOL WINAPI 2442NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This ) 2443{ 2444 return !!(This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING); 2445} 2446 2447HRESULT WINAPI 2448NineDevice9_SetNPatchMode( struct NineDevice9 *This, 2449 float nSegments ) 2450{ 2451 STUB(D3DERR_INVALIDCALL); 2452} 2453 2454float WINAPI 2455NineDevice9_GetNPatchMode( struct NineDevice9 *This ) 2456{ 2457 STUB(0); 2458} 2459 2460static INLINE void 2461init_draw_info(struct pipe_draw_info *info, 2462 struct NineDevice9 *dev, D3DPRIMITIVETYPE type, UINT count) 2463{ 2464 info->mode = d3dprimitivetype_to_pipe_prim(type); 2465 info->count = prim_count_to_vertex_count(type, count); 2466 info->start_instance = 0; 2467 info->instance_count = 1; 2468 if (dev->state.stream_instancedata_mask & dev->state.stream_usage_mask) 2469 info->instance_count = MAX2(dev->state.stream_freq[0] & 0x7FFFFF, 1); 2470 info->primitive_restart = FALSE; 2471 info->restart_index = 0; 2472 info->count_from_stream_output = NULL; 2473 info->indirect = NULL; 2474} 2475 2476HRESULT WINAPI 2477NineDevice9_DrawPrimitive( struct NineDevice9 *This, 2478 D3DPRIMITIVETYPE PrimitiveType, 2479 UINT StartVertex, 2480 UINT PrimitiveCount ) 2481{ 2482 struct pipe_draw_info info; 2483 2484 DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n", 2485 This, PrimitiveType, StartVertex, PrimitiveCount); 2486 2487 nine_update_state(This, ~0); 2488 2489 init_draw_info(&info, This, PrimitiveType, PrimitiveCount); 2490 info.indexed = FALSE; 2491 info.start = StartVertex; 2492 info.index_bias = 0; 2493 info.min_index = info.start; 2494 info.max_index = info.count - 1; 2495 2496 This->pipe->draw_vbo(This->pipe, &info); 2497 2498 return D3D_OK; 2499} 2500 2501HRESULT WINAPI 2502NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This, 2503 D3DPRIMITIVETYPE PrimitiveType, 2504 INT BaseVertexIndex, 2505 UINT MinVertexIndex, 2506 UINT NumVertices, 2507 UINT StartIndex, 2508 UINT PrimitiveCount ) 2509{ 2510 struct pipe_draw_info info; 2511 2512 DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u " 2513 "NumVertices %u, StartIndex %u, PrimitiveCount %u\n", 2514 This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, 2515 StartIndex, PrimitiveCount); 2516 2517 user_assert(This->state.idxbuf, D3DERR_INVALIDCALL); 2518 user_assert(This->state.vdecl, D3DERR_INVALIDCALL); 2519 2520 nine_update_state(This, ~0); 2521 2522 init_draw_info(&info, This, PrimitiveType, PrimitiveCount); 2523 info.indexed = TRUE; 2524 info.start = StartIndex; 2525 info.index_bias = BaseVertexIndex; 2526 /* These don't include index bias: */ 2527 info.min_index = MinVertexIndex; 2528 info.max_index = MinVertexIndex + NumVertices - 1; 2529 2530 This->pipe->draw_vbo(This->pipe, &info); 2531 2532 return D3D_OK; 2533} 2534 2535HRESULT WINAPI 2536NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This, 2537 D3DPRIMITIVETYPE PrimitiveType, 2538 UINT PrimitiveCount, 2539 const void *pVertexStreamZeroData, 2540 UINT VertexStreamZeroStride ) 2541{ 2542 struct pipe_vertex_buffer vtxbuf; 2543 struct pipe_draw_info info; 2544 2545 DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n", 2546 This, PrimitiveType, PrimitiveCount, 2547 pVertexStreamZeroData, VertexStreamZeroStride); 2548 2549 user_assert(pVertexStreamZeroData && VertexStreamZeroStride, 2550 D3DERR_INVALIDCALL); 2551 2552 nine_update_state(This, ~0); 2553 2554 init_draw_info(&info, This, PrimitiveType, PrimitiveCount); 2555 info.indexed = FALSE; 2556 info.start = 0; 2557 info.index_bias = 0; 2558 info.min_index = 0; 2559 info.max_index = info.count - 1; 2560 2561 vtxbuf.stride = VertexStreamZeroStride; 2562 vtxbuf.buffer_offset = 0; 2563 vtxbuf.buffer = NULL; 2564 vtxbuf.user_buffer = pVertexStreamZeroData; 2565 2566 if (!This->driver_caps.user_vbufs) 2567 u_upload_data(This->upload, 2568 0, 2569 (info.max_index + 1) * VertexStreamZeroStride, /* XXX */ 2570 vtxbuf.user_buffer, 2571 &vtxbuf.buffer_offset, 2572 &vtxbuf.buffer); 2573 2574 This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vtxbuf); 2575 2576 This->pipe->draw_vbo(This->pipe, &info); 2577 2578 NineDevice9_PauseRecording(This); 2579 NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); 2580 NineDevice9_ResumeRecording(This); 2581 2582 pipe_resource_reference(&vtxbuf.buffer, NULL); 2583 2584 return D3D_OK; 2585} 2586 2587HRESULT WINAPI 2588NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This, 2589 D3DPRIMITIVETYPE PrimitiveType, 2590 UINT MinVertexIndex, 2591 UINT NumVertices, 2592 UINT PrimitiveCount, 2593 const void *pIndexData, 2594 D3DFORMAT IndexDataFormat, 2595 const void *pVertexStreamZeroData, 2596 UINT VertexStreamZeroStride ) 2597{ 2598 struct pipe_draw_info info; 2599 struct pipe_vertex_buffer vbuf; 2600 struct pipe_index_buffer ibuf; 2601 2602 DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u " 2603 "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u " 2604 "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n", 2605 This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, 2606 pIndexData, IndexDataFormat, 2607 pVertexStreamZeroData, VertexStreamZeroStride); 2608 2609 user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL); 2610 user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL); 2611 user_assert(IndexDataFormat == D3DFMT_INDEX16 || 2612 IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL); 2613 2614 nine_update_state(This, ~0); 2615 2616 init_draw_info(&info, This, PrimitiveType, PrimitiveCount); 2617 info.indexed = TRUE; 2618 info.start = 0; 2619 info.index_bias = 0; 2620 info.min_index = MinVertexIndex; 2621 info.max_index = MinVertexIndex + NumVertices - 1; 2622 2623 vbuf.stride = VertexStreamZeroStride; 2624 vbuf.buffer_offset = 0; 2625 vbuf.buffer = NULL; 2626 vbuf.user_buffer = pVertexStreamZeroData; 2627 2628 ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4; 2629 ibuf.offset = 0; 2630 ibuf.buffer = NULL; 2631 ibuf.user_buffer = pIndexData; 2632 2633 if (!This->driver_caps.user_vbufs) { 2634 const unsigned base = info.min_index * VertexStreamZeroStride; 2635 u_upload_data(This->upload, 2636 base, 2637 (info.max_index - 2638 info.min_index + 1) * VertexStreamZeroStride, /* XXX */ 2639 (const uint8_t *)vbuf.user_buffer + base, 2640 &vbuf.buffer_offset, 2641 &vbuf.buffer); 2642 /* Won't be used: */ 2643 vbuf.buffer_offset -= base; 2644 } 2645 if (!This->driver_caps.user_ibufs) 2646 u_upload_data(This->upload, 2647 0, 2648 info.count * ibuf.index_size, 2649 ibuf.user_buffer, 2650 &ibuf.offset, 2651 &ibuf.buffer); 2652 2653 This->pipe->set_vertex_buffers(This->pipe, 0, 1, &vbuf); 2654 This->pipe->set_index_buffer(This->pipe, &ibuf); 2655 2656 This->pipe->draw_vbo(This->pipe, &info); 2657 2658 pipe_resource_reference(&vbuf.buffer, NULL); 2659 pipe_resource_reference(&ibuf.buffer, NULL); 2660 2661 NineDevice9_PauseRecording(This); 2662 NineDevice9_SetIndices(This, NULL); 2663 NineDevice9_SetStreamSource(This, 0, NULL, 0, 0); 2664 NineDevice9_ResumeRecording(This); 2665 2666 return D3D_OK; 2667} 2668 2669/* TODO: Write to pDestBuffer directly if vertex declaration contains 2670 * only f32 formats. 2671 */ 2672HRESULT WINAPI 2673NineDevice9_ProcessVertices( struct NineDevice9 *This, 2674 UINT SrcStartIndex, 2675 UINT DestIndex, 2676 UINT VertexCount, 2677 IDirect3DVertexBuffer9 *pDestBuffer, 2678 IDirect3DVertexDeclaration9 *pVertexDecl, 2679 DWORD Flags ) 2680{ 2681 struct pipe_screen *screen = This->screen; 2682 struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl); 2683 struct NineVertexShader9 *vs; 2684 struct pipe_resource *resource; 2685 struct pipe_stream_output_target *target; 2686 struct pipe_draw_info draw; 2687 HRESULT hr; 2688 unsigned buffer_offset, buffer_size; 2689 2690 DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u " 2691 "pDestBuffer=%p pVertexDecl=%p Flags=%d\n", 2692 This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, 2693 pVertexDecl, Flags); 2694 2695 if (!screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) 2696 STUB(D3DERR_INVALIDCALL); 2697 2698 nine_update_state(This, ~0); 2699 2700 /* TODO: Create shader with stream output. */ 2701 STUB(D3DERR_INVALIDCALL); 2702 struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer); 2703 2704 vs = This->state.vs ? This->state.vs : This->ff.vs; 2705 2706 buffer_size = VertexCount * vs->so->stride[0]; 2707 if (1) { 2708 struct pipe_resource templ; 2709 2710 templ.target = PIPE_BUFFER; 2711 templ.format = PIPE_FORMAT_R8_UNORM; 2712 templ.width0 = buffer_size; 2713 templ.flags = 0; 2714 templ.bind = PIPE_BIND_STREAM_OUTPUT; 2715 templ.usage = PIPE_USAGE_STREAM; 2716 templ.height0 = templ.depth0 = templ.array_size = 1; 2717 templ.last_level = templ.nr_samples = 0; 2718 2719 resource = This->screen->resource_create(This->screen, &templ); 2720 if (!resource) 2721 return E_OUTOFMEMORY; 2722 buffer_offset = 0; 2723 } else { 2724 /* SO matches vertex declaration */ 2725 resource = dst->base.resource; 2726 buffer_offset = DestIndex * vs->so->stride[0]; 2727 } 2728 target = This->pipe->create_stream_output_target(This->pipe, resource, 2729 buffer_offset, 2730 buffer_size); 2731 if (!target) { 2732 pipe_resource_reference(&resource, NULL); 2733 return D3DERR_DRIVERINTERNALERROR; 2734 } 2735 2736 if (!vdecl) { 2737 hr = NineVertexDeclaration9_new_from_fvf(This, dst->desc.FVF, &vdecl); 2738 if (FAILED(hr)) 2739 goto out; 2740 } 2741 2742 init_draw_info(&draw, This, D3DPT_POINTLIST, VertexCount); 2743 draw.instance_count = 1; 2744 draw.indexed = FALSE; 2745 draw.start = SrcStartIndex; 2746 draw.index_bias = 0; 2747 draw.min_index = SrcStartIndex; 2748 draw.max_index = SrcStartIndex + VertexCount - 1; 2749 2750 This->pipe->set_stream_output_targets(This->pipe, 1, &target, 0); 2751 This->pipe->draw_vbo(This->pipe, &draw); 2752 This->pipe->set_stream_output_targets(This->pipe, 0, NULL, 0); 2753 This->pipe->stream_output_target_destroy(This->pipe, target); 2754 2755 hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl, 2756 dst, DestIndex, VertexCount, 2757 resource, vs->so); 2758out: 2759 pipe_resource_reference(&resource, NULL); 2760 if (!pVertexDecl) 2761 NineUnknown_Release(NineUnknown(vdecl)); 2762 return hr; 2763} 2764 2765HRESULT WINAPI 2766NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This, 2767 const D3DVERTEXELEMENT9 *pVertexElements, 2768 IDirect3DVertexDeclaration9 **ppDecl ) 2769{ 2770 struct NineVertexDeclaration9 *vdecl; 2771 2772 DBG("This=%p pVertexElements=%p ppDecl=%p\n", 2773 This, pVertexElements, ppDecl); 2774 2775 HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl); 2776 if (SUCCEEDED(hr)) 2777 *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl; 2778 2779 return hr; 2780} 2781 2782HRESULT WINAPI 2783NineDevice9_SetVertexDeclaration( struct NineDevice9 *This, 2784 IDirect3DVertexDeclaration9 *pDecl ) 2785{ 2786 struct nine_state *state = This->update; 2787 2788 DBG("This=%p pDecl=%p\n", This, pDecl); 2789 2790 if (likely(!This->is_recording) && state->vdecl == NineVertexDeclaration9(pDecl)) 2791 return D3D_OK; 2792 nine_bind(&state->vdecl, pDecl); 2793 2794 state->changed.group |= NINE_STATE_VDECL; 2795 2796 return D3D_OK; 2797} 2798 2799HRESULT WINAPI 2800NineDevice9_GetVertexDeclaration( struct NineDevice9 *This, 2801 IDirect3DVertexDeclaration9 **ppDecl ) 2802{ 2803 user_assert(ppDecl, D3DERR_INVALIDCALL); 2804 2805 *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl; 2806 if (*ppDecl) 2807 NineUnknown_AddRef(NineUnknown(*ppDecl)); 2808 return D3D_OK; 2809} 2810 2811HRESULT WINAPI 2812NineDevice9_SetFVF( struct NineDevice9 *This, 2813 DWORD FVF ) 2814{ 2815 struct NineVertexDeclaration9 *vdecl; 2816 HRESULT hr; 2817 2818 DBG("FVF = %08x\n", FVF); 2819 if (!FVF) 2820 return D3D_OK; /* like wine */ 2821 2822 vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF); 2823 if (!vdecl) { 2824 hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl); 2825 if (FAILED(hr)) 2826 return hr; 2827 vdecl->fvf = FVF; 2828 util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl); 2829 NineUnknown_ConvertRefToBind(NineUnknown(vdecl)); 2830 } 2831 return NineDevice9_SetVertexDeclaration( 2832 This, (IDirect3DVertexDeclaration9 *)vdecl); 2833} 2834 2835HRESULT WINAPI 2836NineDevice9_GetFVF( struct NineDevice9 *This, 2837 DWORD *pFVF ) 2838{ 2839 *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0; 2840 return D3D_OK; 2841} 2842 2843HRESULT WINAPI 2844NineDevice9_CreateVertexShader( struct NineDevice9 *This, 2845 const DWORD *pFunction, 2846 IDirect3DVertexShader9 **ppShader ) 2847{ 2848 struct NineVertexShader9 *vs; 2849 HRESULT hr; 2850 2851 DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 2852 2853 hr = NineVertexShader9_new(This, &vs, pFunction, NULL); 2854 if (FAILED(hr)) 2855 return hr; 2856 *ppShader = (IDirect3DVertexShader9 *)vs; 2857 return D3D_OK; 2858} 2859 2860HRESULT WINAPI 2861NineDevice9_SetVertexShader( struct NineDevice9 *This, 2862 IDirect3DVertexShader9 *pShader ) 2863{ 2864 struct nine_state *state = This->update; 2865 2866 DBG("This=%p pShader=%p\n", This, pShader); 2867 2868 nine_bind(&state->vs, pShader); 2869 2870 state->changed.group |= NINE_STATE_VS; 2871 2872 return D3D_OK; 2873} 2874 2875HRESULT WINAPI 2876NineDevice9_GetVertexShader( struct NineDevice9 *This, 2877 IDirect3DVertexShader9 **ppShader ) 2878{ 2879 user_assert(ppShader, D3DERR_INVALIDCALL); 2880 nine_reference_set(ppShader, This->state.vs); 2881 return D3D_OK; 2882} 2883 2884HRESULT WINAPI 2885NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This, 2886 UINT StartRegister, 2887 const float *pConstantData, 2888 UINT Vector4fCount ) 2889{ 2890 struct nine_state *state = This->update; 2891 2892 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 2893 This, StartRegister, pConstantData, Vector4fCount); 2894 2895 user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 2896 user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 2897 2898 if (!Vector4fCount) 2899 return D3D_OK; 2900 user_assert(pConstantData, D3DERR_INVALIDCALL); 2901 2902 memcpy(&state->vs_const_f[StartRegister * 4], 2903 pConstantData, 2904 Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 2905 2906 nine_ranges_insert(&state->changed.vs_const_f, 2907 StartRegister, StartRegister + Vector4fCount, 2908 &This->range_pool); 2909 2910 state->changed.group |= NINE_STATE_VS_CONST; 2911 2912 return D3D_OK; 2913} 2914 2915HRESULT WINAPI 2916NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This, 2917 UINT StartRegister, 2918 float *pConstantData, 2919 UINT Vector4fCount ) 2920{ 2921 const struct nine_state *state = &This->state; 2922 2923 user_assert(StartRegister < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 2924 user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL); 2925 user_assert(pConstantData, D3DERR_INVALIDCALL); 2926 2927 memcpy(pConstantData, 2928 &state->vs_const_f[StartRegister * 4], 2929 Vector4fCount * 4 * sizeof(state->vs_const_f[0])); 2930 2931 return D3D_OK; 2932} 2933 2934HRESULT WINAPI 2935NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This, 2936 UINT StartRegister, 2937 const int *pConstantData, 2938 UINT Vector4iCount ) 2939{ 2940 struct nine_state *state = This->update; 2941 int i; 2942 2943 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 2944 This, StartRegister, pConstantData, Vector4iCount); 2945 2946 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 2947 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 2948 user_assert(pConstantData, D3DERR_INVALIDCALL); 2949 2950 if (This->driver_caps.vs_integer) { 2951 memcpy(&state->vs_const_i[StartRegister][0], 2952 pConstantData, 2953 Vector4iCount * sizeof(state->vs_const_i[0])); 2954 } else { 2955 for (i = 0; i < Vector4iCount; i++) { 2956 state->vs_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); 2957 state->vs_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); 2958 state->vs_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); 2959 state->vs_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); 2960 } 2961 } 2962 2963 state->changed.vs_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; 2964 state->changed.group |= NINE_STATE_VS_CONST; 2965 2966 return D3D_OK; 2967} 2968 2969HRESULT WINAPI 2970NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This, 2971 UINT StartRegister, 2972 int *pConstantData, 2973 UINT Vector4iCount ) 2974{ 2975 const struct nine_state *state = &This->state; 2976 int i; 2977 2978 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 2979 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 2980 user_assert(pConstantData, D3DERR_INVALIDCALL); 2981 2982 if (This->driver_caps.vs_integer) { 2983 memcpy(pConstantData, 2984 &state->vs_const_i[StartRegister][0], 2985 Vector4iCount * sizeof(state->vs_const_i[0])); 2986 } else { 2987 for (i = 0; i < Vector4iCount; i++) { 2988 pConstantData[4*i] = (int32_t) uif(state->vs_const_i[StartRegister+i][0]); 2989 pConstantData[4*i+1] = (int32_t) uif(state->vs_const_i[StartRegister+i][1]); 2990 pConstantData[4*i+2] = (int32_t) uif(state->vs_const_i[StartRegister+i][2]); 2991 pConstantData[4*i+3] = (int32_t) uif(state->vs_const_i[StartRegister+i][3]); 2992 } 2993 } 2994 2995 return D3D_OK; 2996} 2997 2998HRESULT WINAPI 2999NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This, 3000 UINT StartRegister, 3001 const BOOL *pConstantData, 3002 UINT BoolCount ) 3003{ 3004 struct nine_state *state = This->update; 3005 int i; 3006 uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f); 3007 3008 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 3009 This, StartRegister, pConstantData, BoolCount); 3010 3011 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3012 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3013 user_assert(pConstantData, D3DERR_INVALIDCALL); 3014 3015 for (i = 0; i < BoolCount; i++) 3016 state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 3017 3018 state->changed.vs_const_b |= ((1 << BoolCount) - 1) << StartRegister; 3019 state->changed.group |= NINE_STATE_VS_CONST; 3020 3021 return D3D_OK; 3022} 3023 3024HRESULT WINAPI 3025NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This, 3026 UINT StartRegister, 3027 BOOL *pConstantData, 3028 UINT BoolCount ) 3029{ 3030 const struct nine_state *state = &This->state; 3031 int i; 3032 3033 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3034 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3035 user_assert(pConstantData, D3DERR_INVALIDCALL); 3036 3037 for (i = 0; i < BoolCount; i++) 3038 pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE; 3039 3040 return D3D_OK; 3041} 3042 3043HRESULT WINAPI 3044NineDevice9_SetStreamSource( struct NineDevice9 *This, 3045 UINT StreamNumber, 3046 IDirect3DVertexBuffer9 *pStreamData, 3047 UINT OffsetInBytes, 3048 UINT Stride ) 3049{ 3050 struct nine_state *state = This->update; 3051 struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData); 3052 const unsigned i = StreamNumber; 3053 3054 DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n", 3055 This, StreamNumber, pStreamData, OffsetInBytes, Stride); 3056 3057 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3058 user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL); 3059 3060 if (likely(!This->is_recording)) { 3061 if (state->stream[i] == NineVertexBuffer9(pStreamData) && 3062 state->vtxbuf[i].stride == Stride && 3063 state->vtxbuf[i].buffer_offset == OffsetInBytes) 3064 return D3D_OK; 3065 } 3066 nine_bind(&state->stream[i], pStreamData); 3067 3068 state->changed.vtxbuf |= 1 << StreamNumber; 3069 3070 if (pStreamData) { 3071 state->vtxbuf[i].stride = Stride; 3072 state->vtxbuf[i].buffer_offset = OffsetInBytes; 3073 } 3074 state->vtxbuf[i].buffer = pStreamData ? pVBuf9->base.resource : NULL; 3075 3076 return D3D_OK; 3077} 3078 3079HRESULT WINAPI 3080NineDevice9_GetStreamSource( struct NineDevice9 *This, 3081 UINT StreamNumber, 3082 IDirect3DVertexBuffer9 **ppStreamData, 3083 UINT *pOffsetInBytes, 3084 UINT *pStride ) 3085{ 3086 const struct nine_state *state = &This->state; 3087 const unsigned i = StreamNumber; 3088 3089 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3090 user_assert(ppStreamData, D3DERR_INVALIDCALL); 3091 3092 nine_reference_set(ppStreamData, state->stream[i]); 3093 *pStride = state->vtxbuf[i].stride; 3094 *pOffsetInBytes = state->vtxbuf[i].buffer_offset; 3095 3096 return D3D_OK; 3097} 3098 3099HRESULT WINAPI 3100NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This, 3101 UINT StreamNumber, 3102 UINT Setting ) 3103{ 3104 struct nine_state *state = This->update; 3105 /* const UINT freq = Setting & 0x7FFFFF; */ 3106 3107 DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This, 3108 StreamNumber, Setting); 3109 3110 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3111 user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA), 3112 D3DERR_INVALIDCALL); 3113 user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) && 3114 (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL); 3115 user_assert(Setting, D3DERR_INVALIDCALL); 3116 3117 state->stream_freq[StreamNumber] = Setting; 3118 3119 if (Setting & D3DSTREAMSOURCE_INSTANCEDATA) 3120 state->stream_instancedata_mask |= 1 << StreamNumber; 3121 else 3122 state->stream_instancedata_mask &= ~(1 << StreamNumber); 3123 3124 state->changed.stream_freq |= 1 << StreamNumber; 3125 return D3D_OK; 3126} 3127 3128HRESULT WINAPI 3129NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This, 3130 UINT StreamNumber, 3131 UINT *pSetting ) 3132{ 3133 user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL); 3134 *pSetting = This->state.stream_freq[StreamNumber]; 3135 return D3D_OK; 3136} 3137 3138HRESULT WINAPI 3139NineDevice9_SetIndices( struct NineDevice9 *This, 3140 IDirect3DIndexBuffer9 *pIndexData ) 3141{ 3142 struct nine_state *state = This->update; 3143 3144 DBG("This=%p pIndexData=%p\n", This, pIndexData); 3145 3146 if (likely(!This->is_recording)) 3147 if (state->idxbuf == NineIndexBuffer9(pIndexData)) 3148 return D3D_OK; 3149 nine_bind(&state->idxbuf, pIndexData); 3150 3151 state->changed.group |= NINE_STATE_IDXBUF; 3152 3153 return D3D_OK; 3154} 3155 3156/* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense 3157 * here because it's an argument passed to the Draw calls. 3158 */ 3159HRESULT WINAPI 3160NineDevice9_GetIndices( struct NineDevice9 *This, 3161 IDirect3DIndexBuffer9 **ppIndexData /*, 3162 UINT *pBaseVertexIndex */ ) 3163{ 3164 user_assert(ppIndexData, D3DERR_INVALIDCALL); 3165 nine_reference_set(ppIndexData, This->state.idxbuf); 3166 return D3D_OK; 3167} 3168 3169HRESULT WINAPI 3170NineDevice9_CreatePixelShader( struct NineDevice9 *This, 3171 const DWORD *pFunction, 3172 IDirect3DPixelShader9 **ppShader ) 3173{ 3174 struct NinePixelShader9 *ps; 3175 HRESULT hr; 3176 3177 DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader); 3178 3179 hr = NinePixelShader9_new(This, &ps, pFunction, NULL); 3180 if (FAILED(hr)) 3181 return hr; 3182 *ppShader = (IDirect3DPixelShader9 *)ps; 3183 return D3D_OK; 3184} 3185 3186HRESULT WINAPI 3187NineDevice9_SetPixelShader( struct NineDevice9 *This, 3188 IDirect3DPixelShader9 *pShader ) 3189{ 3190 struct nine_state *state = This->update; 3191 3192 DBG("This=%p pShader=%p\n", This, pShader); 3193 3194 nine_bind(&state->ps, pShader); 3195 3196 state->changed.group |= NINE_STATE_PS; 3197 3198 return D3D_OK; 3199} 3200 3201HRESULT WINAPI 3202NineDevice9_GetPixelShader( struct NineDevice9 *This, 3203 IDirect3DPixelShader9 **ppShader ) 3204{ 3205 user_assert(ppShader, D3DERR_INVALIDCALL); 3206 nine_reference_set(ppShader, This->state.ps); 3207 return D3D_OK; 3208} 3209 3210HRESULT WINAPI 3211NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This, 3212 UINT StartRegister, 3213 const float *pConstantData, 3214 UINT Vector4fCount ) 3215{ 3216 struct nine_state *state = This->update; 3217 3218 DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n", 3219 This, StartRegister, pConstantData, Vector4fCount); 3220 3221 user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL); 3222 user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL); 3223 3224 if (!Vector4fCount) 3225 return D3D_OK; 3226 user_assert(pConstantData, D3DERR_INVALIDCALL); 3227 3228 memcpy(&state->ps_const_f[StartRegister * 4], 3229 pConstantData, 3230 Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 3231 3232 nine_ranges_insert(&state->changed.ps_const_f, 3233 StartRegister, StartRegister + Vector4fCount, 3234 &This->range_pool); 3235 3236 state->changed.group |= NINE_STATE_PS_CONST; 3237 3238 return D3D_OK; 3239} 3240 3241HRESULT WINAPI 3242NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This, 3243 UINT StartRegister, 3244 float *pConstantData, 3245 UINT Vector4fCount ) 3246{ 3247 const struct nine_state *state = &This->state; 3248 3249 user_assert(StartRegister < NINE_MAX_CONST_F, D3DERR_INVALIDCALL); 3250 user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F, D3DERR_INVALIDCALL); 3251 user_assert(pConstantData, D3DERR_INVALIDCALL); 3252 3253 memcpy(pConstantData, 3254 &state->ps_const_f[StartRegister * 4], 3255 Vector4fCount * 4 * sizeof(state->ps_const_f[0])); 3256 3257 return D3D_OK; 3258} 3259 3260HRESULT WINAPI 3261NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This, 3262 UINT StartRegister, 3263 const int *pConstantData, 3264 UINT Vector4iCount ) 3265{ 3266 struct nine_state *state = This->update; 3267 int i; 3268 3269 DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n", 3270 This, StartRegister, pConstantData, Vector4iCount); 3271 3272 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3273 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3274 user_assert(pConstantData, D3DERR_INVALIDCALL); 3275 3276 if (This->driver_caps.ps_integer) { 3277 memcpy(&state->ps_const_i[StartRegister][0], 3278 pConstantData, 3279 Vector4iCount * sizeof(state->ps_const_i[0])); 3280 } else { 3281 for (i = 0; i < Vector4iCount; i++) { 3282 state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i])); 3283 state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1])); 3284 state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2])); 3285 state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3])); 3286 } 3287 } 3288 state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister; 3289 state->changed.group |= NINE_STATE_PS_CONST; 3290 3291 return D3D_OK; 3292} 3293 3294HRESULT WINAPI 3295NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This, 3296 UINT StartRegister, 3297 int *pConstantData, 3298 UINT Vector4iCount ) 3299{ 3300 const struct nine_state *state = &This->state; 3301 int i; 3302 3303 user_assert(StartRegister < NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3304 user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL); 3305 user_assert(pConstantData, D3DERR_INVALIDCALL); 3306 3307 if (This->driver_caps.ps_integer) { 3308 memcpy(pConstantData, 3309 &state->ps_const_i[StartRegister][0], 3310 Vector4iCount * sizeof(state->ps_const_i[0])); 3311 } else { 3312 for (i = 0; i < Vector4iCount; i++) { 3313 pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]); 3314 pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]); 3315 pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]); 3316 pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]); 3317 } 3318 } 3319 3320 return D3D_OK; 3321} 3322 3323HRESULT WINAPI 3324NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This, 3325 UINT StartRegister, 3326 const BOOL *pConstantData, 3327 UINT BoolCount ) 3328{ 3329 struct nine_state *state = This->update; 3330 int i; 3331 uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f); 3332 3333 DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n", 3334 This, StartRegister, pConstantData, BoolCount); 3335 3336 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3337 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3338 user_assert(pConstantData, D3DERR_INVALIDCALL); 3339 3340 for (i = 0; i < BoolCount; i++) 3341 state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0; 3342 3343 state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister; 3344 state->changed.group |= NINE_STATE_PS_CONST; 3345 3346 return D3D_OK; 3347} 3348 3349HRESULT WINAPI 3350NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This, 3351 UINT StartRegister, 3352 BOOL *pConstantData, 3353 UINT BoolCount ) 3354{ 3355 const struct nine_state *state = &This->state; 3356 int i; 3357 3358 user_assert(StartRegister < NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3359 user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL); 3360 user_assert(pConstantData, D3DERR_INVALIDCALL); 3361 3362 for (i = 0; i < BoolCount; i++) 3363 pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE; 3364 3365 return D3D_OK; 3366} 3367 3368HRESULT WINAPI 3369NineDevice9_DrawRectPatch( struct NineDevice9 *This, 3370 UINT Handle, 3371 const float *pNumSegs, 3372 const D3DRECTPATCH_INFO *pRectPatchInfo ) 3373{ 3374 STUB(D3DERR_INVALIDCALL); 3375} 3376 3377HRESULT WINAPI 3378NineDevice9_DrawTriPatch( struct NineDevice9 *This, 3379 UINT Handle, 3380 const float *pNumSegs, 3381 const D3DTRIPATCH_INFO *pTriPatchInfo ) 3382{ 3383 STUB(D3DERR_INVALIDCALL); 3384} 3385 3386HRESULT WINAPI 3387NineDevice9_DeletePatch( struct NineDevice9 *This, 3388 UINT Handle ) 3389{ 3390 STUB(D3DERR_INVALIDCALL); 3391} 3392 3393HRESULT WINAPI 3394NineDevice9_CreateQuery( struct NineDevice9 *This, 3395 D3DQUERYTYPE Type, 3396 IDirect3DQuery9 **ppQuery ) 3397{ 3398 struct NineQuery9 *query; 3399 HRESULT hr; 3400 3401 DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery); 3402 3403 hr = nine_is_query_supported(This->screen, Type); 3404 if (!ppQuery || hr != D3D_OK) 3405 return hr; 3406 3407 hr = NineQuery9_new(This, &query, Type); 3408 if (FAILED(hr)) 3409 return hr; 3410 *ppQuery = (IDirect3DQuery9 *)query; 3411 return D3D_OK; 3412} 3413 3414IDirect3DDevice9Vtbl NineDevice9_vtable = { 3415 (void *)NineUnknown_QueryInterface, 3416 (void *)NineUnknown_AddRef, 3417 (void *)NineUnknown_Release, 3418 (void *)NineDevice9_TestCooperativeLevel, 3419 (void *)NineDevice9_GetAvailableTextureMem, 3420 (void *)NineDevice9_EvictManagedResources, 3421 (void *)NineDevice9_GetDirect3D, 3422 (void *)NineDevice9_GetDeviceCaps, 3423 (void *)NineDevice9_GetDisplayMode, 3424 (void *)NineDevice9_GetCreationParameters, 3425 (void *)NineDevice9_SetCursorProperties, 3426 (void *)NineDevice9_SetCursorPosition, 3427 (void *)NineDevice9_ShowCursor, 3428 (void *)NineDevice9_CreateAdditionalSwapChain, 3429 (void *)NineDevice9_GetSwapChain, 3430 (void *)NineDevice9_GetNumberOfSwapChains, 3431 (void *)NineDevice9_Reset, 3432 (void *)NineDevice9_Present, 3433 (void *)NineDevice9_GetBackBuffer, 3434 (void *)NineDevice9_GetRasterStatus, 3435 (void *)NineDevice9_SetDialogBoxMode, 3436 (void *)NineDevice9_SetGammaRamp, 3437 (void *)NineDevice9_GetGammaRamp, 3438 (void *)NineDevice9_CreateTexture, 3439 (void *)NineDevice9_CreateVolumeTexture, 3440 (void *)NineDevice9_CreateCubeTexture, 3441 (void *)NineDevice9_CreateVertexBuffer, 3442 (void *)NineDevice9_CreateIndexBuffer, 3443 (void *)NineDevice9_CreateRenderTarget, 3444 (void *)NineDevice9_CreateDepthStencilSurface, 3445 (void *)NineDevice9_UpdateSurface, 3446 (void *)NineDevice9_UpdateTexture, 3447 (void *)NineDevice9_GetRenderTargetData, 3448 (void *)NineDevice9_GetFrontBufferData, 3449 (void *)NineDevice9_StretchRect, 3450 (void *)NineDevice9_ColorFill, 3451 (void *)NineDevice9_CreateOffscreenPlainSurface, 3452 (void *)NineDevice9_SetRenderTarget, 3453 (void *)NineDevice9_GetRenderTarget, 3454 (void *)NineDevice9_SetDepthStencilSurface, 3455 (void *)NineDevice9_GetDepthStencilSurface, 3456 (void *)NineDevice9_BeginScene, 3457 (void *)NineDevice9_EndScene, 3458 (void *)NineDevice9_Clear, 3459 (void *)NineDevice9_SetTransform, 3460 (void *)NineDevice9_GetTransform, 3461 (void *)NineDevice9_MultiplyTransform, 3462 (void *)NineDevice9_SetViewport, 3463 (void *)NineDevice9_GetViewport, 3464 (void *)NineDevice9_SetMaterial, 3465 (void *)NineDevice9_GetMaterial, 3466 (void *)NineDevice9_SetLight, 3467 (void *)NineDevice9_GetLight, 3468 (void *)NineDevice9_LightEnable, 3469 (void *)NineDevice9_GetLightEnable, 3470 (void *)NineDevice9_SetClipPlane, 3471 (void *)NineDevice9_GetClipPlane, 3472 (void *)NineDevice9_SetRenderState, 3473 (void *)NineDevice9_GetRenderState, 3474 (void *)NineDevice9_CreateStateBlock, 3475 (void *)NineDevice9_BeginStateBlock, 3476 (void *)NineDevice9_EndStateBlock, 3477 (void *)NineDevice9_SetClipStatus, 3478 (void *)NineDevice9_GetClipStatus, 3479 (void *)NineDevice9_GetTexture, 3480 (void *)NineDevice9_SetTexture, 3481 (void *)NineDevice9_GetTextureStageState, 3482 (void *)NineDevice9_SetTextureStageState, 3483 (void *)NineDevice9_GetSamplerState, 3484 (void *)NineDevice9_SetSamplerState, 3485 (void *)NineDevice9_ValidateDevice, 3486 (void *)NineDevice9_SetPaletteEntries, 3487 (void *)NineDevice9_GetPaletteEntries, 3488 (void *)NineDevice9_SetCurrentTexturePalette, 3489 (void *)NineDevice9_GetCurrentTexturePalette, 3490 (void *)NineDevice9_SetScissorRect, 3491 (void *)NineDevice9_GetScissorRect, 3492 (void *)NineDevice9_SetSoftwareVertexProcessing, 3493 (void *)NineDevice9_GetSoftwareVertexProcessing, 3494 (void *)NineDevice9_SetNPatchMode, 3495 (void *)NineDevice9_GetNPatchMode, 3496 (void *)NineDevice9_DrawPrimitive, 3497 (void *)NineDevice9_DrawIndexedPrimitive, 3498 (void *)NineDevice9_DrawPrimitiveUP, 3499 (void *)NineDevice9_DrawIndexedPrimitiveUP, 3500 (void *)NineDevice9_ProcessVertices, 3501 (void *)NineDevice9_CreateVertexDeclaration, 3502 (void *)NineDevice9_SetVertexDeclaration, 3503 (void *)NineDevice9_GetVertexDeclaration, 3504 (void *)NineDevice9_SetFVF, 3505 (void *)NineDevice9_GetFVF, 3506 (void *)NineDevice9_CreateVertexShader, 3507 (void *)NineDevice9_SetVertexShader, 3508 (void *)NineDevice9_GetVertexShader, 3509 (void *)NineDevice9_SetVertexShaderConstantF, 3510 (void *)NineDevice9_GetVertexShaderConstantF, 3511 (void *)NineDevice9_SetVertexShaderConstantI, 3512 (void *)NineDevice9_GetVertexShaderConstantI, 3513 (void *)NineDevice9_SetVertexShaderConstantB, 3514 (void *)NineDevice9_GetVertexShaderConstantB, 3515 (void *)NineDevice9_SetStreamSource, 3516 (void *)NineDevice9_GetStreamSource, 3517 (void *)NineDevice9_SetStreamSourceFreq, 3518 (void *)NineDevice9_GetStreamSourceFreq, 3519 (void *)NineDevice9_SetIndices, 3520 (void *)NineDevice9_GetIndices, 3521 (void *)NineDevice9_CreatePixelShader, 3522 (void *)NineDevice9_SetPixelShader, 3523 (void *)NineDevice9_GetPixelShader, 3524 (void *)NineDevice9_SetPixelShaderConstantF, 3525 (void *)NineDevice9_GetPixelShaderConstantF, 3526 (void *)NineDevice9_SetPixelShaderConstantI, 3527 (void *)NineDevice9_GetPixelShaderConstantI, 3528 (void *)NineDevice9_SetPixelShaderConstantB, 3529 (void *)NineDevice9_GetPixelShaderConstantB, 3530 (void *)NineDevice9_DrawRectPatch, 3531 (void *)NineDevice9_DrawTriPatch, 3532 (void *)NineDevice9_DeletePatch, 3533 (void *)NineDevice9_CreateQuery 3534}; 3535 3536static const GUID *NineDevice9_IIDs[] = { 3537 &IID_IDirect3DDevice9, 3538 &IID_IUnknown, 3539 NULL 3540}; 3541 3542HRESULT 3543NineDevice9_new( struct pipe_screen *pScreen, 3544 D3DDEVICE_CREATION_PARAMETERS *pCreationParameters, 3545 D3DCAPS9 *pCaps, 3546 D3DPRESENT_PARAMETERS *pPresentationParameters, 3547 IDirect3D9 *pD3D9, 3548 ID3DPresentGroup *pPresentationGroup, 3549 struct d3dadapter9_context *pCTX, 3550 boolean ex, 3551 D3DDISPLAYMODEEX *pFullscreenDisplayMode, 3552 struct NineDevice9 **ppOut ) 3553{ 3554 BOOL lock; 3555 lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED); 3556 3557 NINE_NEW(Device9, ppOut, lock, /* args */ 3558 pScreen, pCreationParameters, pCaps, 3559 pPresentationParameters, pD3D9, pPresentationGroup, pCTX, 3560 ex, pFullscreenDisplayMode); 3561} 3562