1 /* 2 * Copyright 2011 Joakim Sindholt <opensource (at) zhasha.com> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 23 #include "iunknown.h" 24 #include "surface9.h" 25 #include "device9.h" 26 27 /* for marking dirty */ 28 #include "basetexture9.h" 29 #include "texture9.h" 30 #include "cubetexture9.h" 31 32 #include "nine_helpers.h" 33 #include "nine_pipe.h" 34 #include "nine_dump.h" 35 #include "nine_state.h" 36 37 #include "pipe/p_context.h" 38 #include "pipe/p_screen.h" 39 #include "pipe/p_state.h" 40 41 #include "util/u_math.h" 42 #include "util/u_inlines.h" 43 #include "util/u_surface.h" 44 45 #define DBG_CHANNEL DBG_SURFACE 46 47 static void 48 NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ); 49 50 HRESULT 51 NineSurface9_ctor( struct NineSurface9 *This, 52 struct NineUnknownParams *pParams, 53 struct NineUnknown *pContainer, 54 struct pipe_resource *pResource, 55 void *user_buffer, 56 uint8_t TextureType, 57 unsigned Level, 58 unsigned Layer, 59 D3DSURFACE_DESC *pDesc ) 60 { 61 HRESULT hr; 62 bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL; 63 D3DMULTISAMPLE_TYPE multisample_type; 64 65 DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n", 66 This, pParams->device, pResource, Level, Layer, pDesc); 67 68 /* Mark this as a special surface held by another internal resource. */ 69 pParams->container = pContainer; 70 /* Make sure there's a Desc */ 71 assert(pDesc); 72 73 assert(allocate || pResource || user_buffer || 74 pDesc->Format == D3DFMT_NULL); 75 assert(!allocate || (!pResource && !user_buffer)); 76 assert(!pResource || !user_buffer); 77 assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT); 78 assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT); 79 /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */ 80 assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0)); 81 82 This->data = (uint8_t *)user_buffer; 83 84 multisample_type = pDesc->MultiSampleType; 85 86 /* Map MultiSampleQuality to MultiSampleType */ 87 hr = d3dmultisample_type_check(pParams->device->screen, 88 pDesc->Format, 89 &multisample_type, 90 pDesc->MultiSampleQuality, 91 NULL); 92 if (FAILED(hr)) { 93 return hr; 94 } 95 96 /* TODO: this is (except width and height) duplicate from 97 * container info (in the pContainer case). Some refactoring is 98 * needed to avoid duplication */ 99 This->base.info.screen = pParams->device->screen; 100 This->base.info.target = PIPE_TEXTURE_2D; 101 This->base.info.width0 = pDesc->Width; 102 This->base.info.height0 = pDesc->Height; 103 This->base.info.depth0 = 1; 104 This->base.info.last_level = 0; 105 This->base.info.array_size = 1; 106 This->base.info.nr_samples = multisample_type; 107 This->base.info.usage = PIPE_USAGE_DEFAULT; 108 This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ 109 110 if (pDesc->Usage & D3DUSAGE_RENDERTARGET) { 111 This->base.info.bind |= PIPE_BIND_RENDER_TARGET; 112 } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) { 113 This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); 114 if (TextureType) 115 This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; 116 } 117 118 This->base.info.flags = 0; 119 This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen, 120 pDesc->Format, 121 This->base.info.target, 122 This->base.info.nr_samples, 123 This->base.info.bind, 124 FALSE, 125 pDesc->Pool == D3DPOOL_SCRATCH); 126 127 if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL) 128 return D3DERR_INVALIDCALL; 129 130 if (allocate && compressed_format(pDesc->Format)) { 131 const unsigned w = util_format_get_blockwidth(This->base.info.format); 132 const unsigned h = util_format_get_blockheight(This->base.info.format); 133 134 /* Note: In the !allocate case, the test could fail (lower levels of a texture) */ 135 user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL); 136 } 137 138 /* Get true format */ 139 This->format_conversion = d3d9_to_pipe_format_checked(This->base.info.screen, 140 pDesc->Format, 141 This->base.info.target, 142 This->base.info.nr_samples, 143 This->base.info.bind, 144 FALSE, 145 TRUE); 146 if (This->base.info.format != This->format_conversion) { 147 This->data_conversion = align_calloc( 148 nine_format_get_level_alloc_size(This->format_conversion, 149 pDesc->Width, 150 pDesc->Height, 151 0), 32); 152 if (!This->data_conversion) 153 return E_OUTOFMEMORY; 154 This->stride_conversion = nine_format_get_stride(This->format_conversion, 155 pDesc->Width); 156 } 157 158 if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) { 159 /* Ram buffer with no parent. Has to allocate the resource itself */ 160 assert(!user_buffer); 161 This->data = align_calloc( 162 nine_format_get_level_alloc_size(This->base.info.format, 163 pDesc->Width, 164 pDesc->Height, 165 0), 32); 166 if (!This->data) 167 return E_OUTOFMEMORY; 168 } 169 170 hr = NineResource9_ctor(&This->base, pParams, pResource, 171 allocate && (pDesc->Pool == D3DPOOL_DEFAULT), 172 D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage); 173 174 if (FAILED(hr)) 175 return hr; 176 177 This->transfer = NULL; 178 179 This->texture = TextureType; 180 This->level = Level; 181 This->level_actual = Level; 182 This->layer = Layer; 183 This->desc = *pDesc; 184 185 This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width); 186 187 if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) 188 This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; 189 190 if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) 191 NineSurface9_CreatePipeSurfaces(This); 192 193 /* TODO: investigate what else exactly needs to be cleared */ 194 if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) 195 nine_context_clear_render_target(pParams->device, This, 0, 0, 0, pDesc->Width, pDesc->Height); 196 197 NineSurface9_Dump(This); 198 199 return D3D_OK; 200 } 201 202 void 203 NineSurface9_dtor( struct NineSurface9 *This ) 204 { 205 DBG("This=%p\n", This); 206 207 if (This->transfer) { 208 struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device); 209 pipe->transfer_unmap(pipe, This->transfer); 210 This->transfer = NULL; 211 } 212 213 /* Note: Following condition cannot happen currently, since we 214 * refcount the surface in the functions increasing 215 * pending_uploads_counter. */ 216 if (p_atomic_read(&This->pending_uploads_counter)) 217 nine_csmt_process(This->base.base.device); 218 219 pipe_surface_reference(&This->surface[0], NULL); 220 pipe_surface_reference(&This->surface[1], NULL); 221 222 /* Release system memory when we have to manage it (no parent) */ 223 if (!This->base.base.container && This->data) 224 align_free(This->data); 225 if (This->data_conversion) 226 align_free(This->data_conversion); 227 NineResource9_dtor(&This->base); 228 } 229 230 static void 231 NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ) 232 { 233 struct pipe_context *pipe; 234 struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); 235 struct pipe_resource *resource = This->base.resource; 236 struct pipe_surface templ; 237 enum pipe_format srgb_format; 238 239 assert(This->desc.Pool == D3DPOOL_DEFAULT); 240 assert(resource); 241 242 srgb_format = util_format_srgb(resource->format); 243 if (srgb_format == PIPE_FORMAT_NONE || 244 !screen->is_format_supported(screen, srgb_format, 245 resource->target, 0, resource->bind)) 246 srgb_format = resource->format; 247 248 memset(&templ, 0, sizeof(templ)); 249 templ.format = resource->format; 250 templ.u.tex.level = This->level; 251 templ.u.tex.first_layer = This->layer; 252 templ.u.tex.last_layer = This->layer; 253 254 pipe = nine_context_get_pipe_acquire(This->base.base.device); 255 256 This->surface[0] = pipe->create_surface(pipe, resource, &templ); 257 258 memset(&templ, 0, sizeof(templ)); 259 templ.format = srgb_format; 260 templ.u.tex.level = This->level; 261 templ.u.tex.first_layer = This->layer; 262 templ.u.tex.last_layer = This->layer; 263 264 This->surface[1] = pipe->create_surface(pipe, resource, &templ); 265 266 nine_context_get_pipe_release(This->base.base.device); 267 268 assert(This->surface[0]); /* TODO: Handle failure */ 269 assert(This->surface[1]); 270 } 271 272 #ifdef DEBUG 273 void 274 NineSurface9_Dump( struct NineSurface9 *This ) 275 { 276 struct NineBaseTexture9 *tex; 277 GUID id = IID_IDirect3DBaseTexture9; 278 REFIID ref = &id; 279 280 DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n" 281 "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n" 282 "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data, 283 nine_D3DPOOL_to_str(This->desc.Pool), 284 nine_D3DRTYPE_to_str(This->desc.Type), 285 nine_D3DUSAGE_to_str(This->desc.Usage), 286 This->desc.Width, This->desc.Height, 287 d3dformat_to_string(This->desc.Format), This->stride, 288 This->base.resource && 289 (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE), 290 This->level, This->level_actual, This->layer); 291 292 if (!This->base.base.container) 293 return; 294 NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex); 295 if (tex) { 296 NineBaseTexture9_Dump(tex); 297 NineUnknown_Release(NineUnknown(tex)); 298 } 299 } 300 #endif /* DEBUG */ 301 302 HRESULT NINE_WINAPI 303 NineSurface9_GetContainer( struct NineSurface9 *This, 304 REFIID riid, 305 void **ppContainer ) 306 { 307 HRESULT hr; 308 char guid_str[64]; 309 310 DBG("This=%p riid=%p id=%s ppContainer=%p\n", 311 This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); 312 313 (void)guid_str; 314 315 if (!ppContainer) return E_POINTER; 316 317 /* Return device for OffscreenPlainSurface, DepthStencilSurface and RenderTarget */ 318 if (!NineUnknown(This)->container) { 319 *ppContainer = NineUnknown(This)->device; 320 NineUnknown_AddRef(NineUnknown(*ppContainer)); 321 322 return D3D_OK; 323 } 324 325 hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); 326 if (FAILED(hr)) 327 DBG("QueryInterface FAILED!\n"); 328 return hr; 329 } 330 331 void 332 NineSurface9_MarkContainerDirty( struct NineSurface9 *This ) 333 { 334 if (This->texture) { 335 struct NineBaseTexture9 *tex = 336 NineBaseTexture9(This->base.base.container); 337 assert(tex); 338 assert(This->texture == D3DRTYPE_TEXTURE || 339 This->texture == D3DRTYPE_CUBETEXTURE); 340 if (This->base.pool == D3DPOOL_MANAGED) 341 tex->managed.dirty = TRUE; 342 else 343 if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) 344 tex->dirty_mip = TRUE; 345 346 BASETEX_REGISTER_UPDATE(tex); 347 } 348 } 349 350 HRESULT NINE_WINAPI 351 NineSurface9_GetDesc( struct NineSurface9 *This, 352 D3DSURFACE_DESC *pDesc ) 353 { 354 user_assert(pDesc != NULL, E_POINTER); 355 *pDesc = This->desc; 356 return D3D_OK; 357 } 358 359 /* Add the dirty rects to the source texture */ 360 inline void 361 NineSurface9_AddDirtyRect( struct NineSurface9 *This, 362 const struct pipe_box *box ) 363 { 364 RECT dirty_rect; 365 366 DBG("This=%p box=%p\n", This, box); 367 368 assert (This->base.pool != D3DPOOL_MANAGED || 369 This->texture == D3DRTYPE_CUBETEXTURE || 370 This->texture == D3DRTYPE_TEXTURE); 371 372 if (This->base.pool == D3DPOOL_DEFAULT) 373 return; 374 375 /* Add a dirty rect to level 0 of the parent texture */ 376 dirty_rect.left = box->x << This->level_actual; 377 dirty_rect.right = dirty_rect.left + (box->width << This->level_actual); 378 dirty_rect.top = box->y << This->level_actual; 379 dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual); 380 381 if (This->texture == D3DRTYPE_TEXTURE) { 382 struct NineTexture9 *tex = 383 NineTexture9(This->base.base.container); 384 385 NineTexture9_AddDirtyRect(tex, &dirty_rect); 386 } else if (This->texture == D3DRTYPE_CUBETEXTURE) { 387 struct NineCubeTexture9 *ctex = 388 NineCubeTexture9(This->base.base.container); 389 390 NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect); 391 } 392 } 393 394 static inline uint8_t * 395 NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y) 396 { 397 unsigned x_offset = util_format_get_stride(This->base.info.format, x); 398 399 y = util_format_get_nblocksy(This->base.info.format, y); 400 401 assert(This->data); 402 return This->data + (y * This->stride + x_offset); 403 } 404 405 HRESULT NINE_WINAPI 406 NineSurface9_LockRect( struct NineSurface9 *This, 407 D3DLOCKED_RECT *pLockedRect, 408 const RECT *pRect, 409 DWORD Flags ) 410 { 411 struct pipe_resource *resource = This->base.resource; 412 struct pipe_context *pipe; 413 struct pipe_box box; 414 unsigned usage; 415 416 DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This, 417 pLockedRect, pRect, 418 pRect ? pRect->left : 0, pRect ? pRect->right : 0, 419 pRect ? pRect->top : 0, pRect ? pRect->bottom : 0, 420 nine_D3DLOCK_to_str(Flags)); 421 NineSurface9_Dump(This); 422 423 /* check if it's already locked */ 424 user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); 425 426 /* set pBits to NULL after lock_count check */ 427 user_assert(pLockedRect, E_POINTER); 428 pLockedRect->pBits = NULL; 429 430 #ifdef NINE_STRICT 431 user_assert(This->base.pool != D3DPOOL_DEFAULT || 432 (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)), 433 D3DERR_INVALIDCALL); 434 #endif 435 user_assert(!(Flags & ~(D3DLOCK_DISCARD | 436 D3DLOCK_DONOTWAIT | 437 D3DLOCK_NO_DIRTY_UPDATE | 438 D3DLOCK_NOOVERWRITE | 439 D3DLOCK_NOSYSLOCK | /* ignored */ 440 D3DLOCK_READONLY)), D3DERR_INVALIDCALL); 441 user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), 442 D3DERR_INVALIDCALL); 443 444 user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE, 445 D3DERR_INVALIDCALL); 446 447 if (pRect && This->desc.Pool == D3DPOOL_DEFAULT && 448 util_format_is_compressed(This->base.info.format)) { 449 const unsigned w = util_format_get_blockwidth(This->base.info.format); 450 const unsigned h = util_format_get_blockheight(This->base.info.format); 451 user_assert((pRect->left == 0 && pRect->right == This->desc.Width && 452 pRect->top == 0 && pRect->bottom == This->desc.Height) || 453 (!(pRect->left % w) && !(pRect->right % w) && 454 !(pRect->top % h) && !(pRect->bottom % h)), 455 D3DERR_INVALIDCALL); 456 } 457 458 if (Flags & D3DLOCK_DISCARD) { 459 usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE; 460 } else { 461 usage = (Flags & D3DLOCK_READONLY) ? 462 PIPE_TRANSFER_READ : PIPE_TRANSFER_READ_WRITE; 463 } 464 if (Flags & D3DLOCK_DONOTWAIT) 465 usage |= PIPE_TRANSFER_DONTBLOCK; 466 467 if (pRect) { 468 /* Windows XP accepts invalid locking rectangles, Windows 7 rejects 469 * them. Use Windows XP behaviour for now. */ 470 rect_to_pipe_box(&box, pRect); 471 } else { 472 u_box_origin_2d(This->desc.Width, This->desc.Height, &box); 473 } 474 box.z = This->layer; 475 476 user_warn(This->desc.Format == D3DFMT_NULL); 477 478 if (p_atomic_read(&This->pending_uploads_counter)) 479 nine_csmt_process(This->base.base.device); 480 481 if (This->data_conversion) { 482 /* For now we only have uncompressed formats here */ 483 pLockedRect->Pitch = This->stride_conversion; 484 pLockedRect->pBits = This->data_conversion + box.y * This->stride_conversion + 485 util_format_get_stride(This->format_conversion, box.x); 486 } else if (This->data) { 487 DBG("returning system memory\n"); 488 /* ATI1 and ATI2 need special handling, because of d3d9 bug. 489 * We must advertise to the application as if it is uncompressed 490 * and bpp 8, and the app has a workaround to work with the fact 491 * that it is actually compressed. */ 492 if (is_ATI1_ATI2(This->base.info.format)) { 493 pLockedRect->Pitch = This->desc.Width; 494 pLockedRect->pBits = This->data + box.y * This->desc.Width + box.x; 495 } else { 496 pLockedRect->Pitch = This->stride; 497 pLockedRect->pBits = NineSurface9_GetSystemMemPointer(This, 498 box.x, 499 box.y); 500 } 501 } else { 502 bool no_refs = !p_atomic_read(&This->base.base.bind) && 503 !(This->base.base.container && p_atomic_read(&This->base.base.container->bind)); 504 DBG("mapping pipe_resource %p (level=%u usage=%x)\n", 505 resource, This->level, usage); 506 507 /* if the object is not bound internally, there can't be any pending 508 * operation with the surface in the queue */ 509 if (no_refs) 510 pipe = nine_context_get_pipe_acquire(This->base.base.device); 511 else 512 pipe = NineDevice9_GetPipe(This->base.base.device); 513 pLockedRect->pBits = pipe->transfer_map(pipe, resource, 514 This->level, usage, &box, 515 &This->transfer); 516 if (no_refs) 517 nine_context_get_pipe_release(This->base.base.device); 518 if (!This->transfer) { 519 DBG("transfer_map failed\n"); 520 if (Flags & D3DLOCK_DONOTWAIT) 521 return D3DERR_WASSTILLDRAWING; 522 return D3DERR_INVALIDCALL; 523 } 524 pLockedRect->Pitch = This->transfer->stride; 525 } 526 527 if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { 528 NineSurface9_MarkContainerDirty(This); 529 NineSurface9_AddDirtyRect(This, &box); 530 } 531 532 ++This->lock_count; 533 return D3D_OK; 534 } 535 536 HRESULT NINE_WINAPI 537 NineSurface9_UnlockRect( struct NineSurface9 *This ) 538 { 539 struct pipe_context *pipe; 540 DBG("This=%p lock_count=%u\n", This, This->lock_count); 541 user_assert(This->lock_count, D3DERR_INVALIDCALL); 542 if (This->transfer) { 543 pipe = nine_context_get_pipe_acquire(This->base.base.device); 544 pipe->transfer_unmap(pipe, This->transfer); 545 nine_context_get_pipe_release(This->base.base.device); 546 This->transfer = NULL; 547 } 548 --This->lock_count; 549 550 if (This->data_conversion) { 551 struct pipe_transfer *transfer; 552 uint8_t *dst = This->data; 553 struct pipe_box box; 554 555 u_box_origin_2d(This->desc.Width, This->desc.Height, &box); 556 557 pipe = NineDevice9_GetPipe(This->base.base.device); 558 if (!dst) { 559 dst = pipe->transfer_map(pipe, 560 This->base.resource, 561 This->level, 562 PIPE_TRANSFER_WRITE | 563 PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, 564 &box, &transfer); 565 if (!dst) 566 return D3D_OK; 567 } 568 569 (void) util_format_translate(This->base.info.format, 570 dst, This->data ? This->stride : transfer->stride, 571 0, 0, 572 This->format_conversion, 573 This->data_conversion, 574 This->stride_conversion, 575 0, 0, 576 This->desc.Width, This->desc.Height); 577 578 if (!This->data) 579 pipe_transfer_unmap(pipe, transfer); 580 } 581 return D3D_OK; 582 } 583 584 HRESULT NINE_WINAPI 585 NineSurface9_GetDC( struct NineSurface9 *This, 586 HDC *phdc ) 587 { 588 STUB(D3DERR_INVALIDCALL); 589 } 590 591 HRESULT NINE_WINAPI 592 NineSurface9_ReleaseDC( struct NineSurface9 *This, 593 HDC hdc ) 594 { 595 STUB(D3DERR_INVALIDCALL); 596 } 597 598 IDirect3DSurface9Vtbl NineSurface9_vtable = { 599 (void *)NineUnknown_QueryInterface, 600 (void *)NineUnknown_AddRef, 601 (void *)NineUnknown_Release, 602 (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ 603 (void *)NineUnknown_SetPrivateData, 604 (void *)NineUnknown_GetPrivateData, 605 (void *)NineUnknown_FreePrivateData, 606 (void *)NineResource9_SetPriority, 607 (void *)NineResource9_GetPriority, 608 (void *)NineResource9_PreLoad, 609 (void *)NineResource9_GetType, 610 (void *)NineSurface9_GetContainer, 611 (void *)NineSurface9_GetDesc, 612 (void *)NineSurface9_LockRect, 613 (void *)NineSurface9_UnlockRect, 614 (void *)NineSurface9_GetDC, 615 (void *)NineSurface9_ReleaseDC 616 }; 617 618 /* When this function is called, we have already checked 619 * The copy regions fit the surfaces */ 620 void 621 NineSurface9_CopyMemToDefault( struct NineSurface9 *This, 622 struct NineSurface9 *From, 623 const POINT *pDestPoint, 624 const RECT *pSourceRect ) 625 { 626 struct pipe_resource *r_dst = This->base.resource; 627 struct pipe_box dst_box, src_box; 628 int src_x, src_y, dst_x, dst_y, copy_width, copy_height; 629 630 assert(This->base.pool == D3DPOOL_DEFAULT && 631 From->base.pool == D3DPOOL_SYSTEMMEM); 632 633 if (pDestPoint) { 634 dst_x = pDestPoint->x; 635 dst_y = pDestPoint->y; 636 } else { 637 dst_x = 0; 638 dst_y = 0; 639 } 640 641 if (pSourceRect) { 642 src_x = pSourceRect->left; 643 src_y = pSourceRect->top; 644 copy_width = pSourceRect->right - pSourceRect->left; 645 copy_height = pSourceRect->bottom - pSourceRect->top; 646 } else { 647 src_x = 0; 648 src_y = 0; 649 copy_width = From->desc.Width; 650 copy_height = From->desc.Height; 651 } 652 653 u_box_2d_zslice(dst_x, dst_y, This->layer, 654 copy_width, copy_height, &dst_box); 655 u_box_2d_zslice(src_x, src_y, 0, 656 copy_width, copy_height, &src_box); 657 658 nine_context_box_upload(This->base.base.device, 659 &From->pending_uploads_counter, 660 (struct NineUnknown *)This, 661 r_dst, 662 This->level, 663 &dst_box, 664 From->base.info.format, 665 From->data, From->stride, 666 0, /* depth = 1 */ 667 &src_box); 668 669 if (This->data_conversion) 670 (void) util_format_translate(This->format_conversion, 671 This->data_conversion, 672 This->stride_conversion, 673 dst_x, dst_y, 674 From->base.info.format, 675 From->data, From->stride, 676 src_x, src_y, 677 copy_width, copy_height); 678 679 NineSurface9_MarkContainerDirty(This); 680 } 681 682 void 683 NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, 684 struct NineSurface9 *From ) 685 { 686 struct pipe_context *pipe; 687 struct pipe_resource *r_src = From->base.resource; 688 struct pipe_transfer *transfer; 689 struct pipe_box src_box; 690 uint8_t *p_dst; 691 const uint8_t *p_src; 692 693 assert(This->base.pool == D3DPOOL_SYSTEMMEM && 694 From->base.pool == D3DPOOL_DEFAULT); 695 696 assert(This->desc.Width == From->desc.Width); 697 assert(This->desc.Height == From->desc.Height); 698 699 u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box); 700 src_box.z = From->layer; 701 702 if (p_atomic_read(&This->pending_uploads_counter)) 703 nine_csmt_process(This->base.base.device); 704 705 pipe = NineDevice9_GetPipe(This->base.base.device); 706 p_src = pipe->transfer_map(pipe, r_src, From->level, 707 PIPE_TRANSFER_READ, 708 &src_box, &transfer); 709 p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0); 710 711 assert (p_src && p_dst); 712 713 util_copy_rect(p_dst, This->base.info.format, 714 This->stride, 0, 0, 715 This->desc.Width, This->desc.Height, 716 p_src, 717 transfer->stride, 0, 0); 718 719 pipe->transfer_unmap(pipe, transfer); 720 } 721 722 723 /* Gladly, rendering to a MANAGED surface is not permitted, so we will 724 * never have to do the reverse, i.e. download the surface. 725 */ 726 HRESULT 727 NineSurface9_UploadSelf( struct NineSurface9 *This, 728 const struct pipe_box *damaged ) 729 { 730 struct pipe_resource *res = This->base.resource; 731 struct pipe_box box; 732 733 DBG("This=%p damaged=%p\n", This, damaged); 734 735 assert(This->base.pool == D3DPOOL_MANAGED); 736 737 if (damaged) { 738 box = *damaged; 739 box.z = This->layer; 740 box.depth = 1; 741 } else { 742 box.x = 0; 743 box.y = 0; 744 box.z = This->layer; 745 box.width = This->desc.Width; 746 box.height = This->desc.Height; 747 box.depth = 1; 748 } 749 750 nine_context_box_upload(This->base.base.device, 751 &This->pending_uploads_counter, 752 (struct NineUnknown *)This, 753 res, 754 This->level, 755 &box, 756 res->format, 757 This->data, This->stride, 758 0, /* depth = 1 */ 759 &box); 760 761 return D3D_OK; 762 } 763 764 /* Currently nine_context uses the NineSurface9 765 * fields when it is render target. Any modification requires 766 * pending commands with the surface to be executed. If the bind 767 * count is 0, there is no pending commands. */ 768 #define PROCESS_IF_BOUND(surf) \ 769 if (surf->base.base.bind) \ 770 nine_csmt_process(surf->base.base.device); 771 772 void 773 NineSurface9_SetResource( struct NineSurface9 *This, 774 struct pipe_resource *resource, unsigned level ) 775 { 776 /* No need to call PROCESS_IF_BOUND, because SetResource is used only 777 * for MANAGED textures, and they are not render targets. */ 778 assert(This->base.pool == D3DPOOL_MANAGED); 779 This->level = level; 780 pipe_resource_reference(&This->base.resource, resource); 781 } 782 783 void 784 NineSurface9_SetMultiSampleType( struct NineSurface9 *This, 785 D3DMULTISAMPLE_TYPE mst ) 786 { 787 PROCESS_IF_BOUND(This); 788 This->desc.MultiSampleType = mst; 789 } 790 791 void 792 NineSurface9_SetResourceResize( struct NineSurface9 *This, 793 struct pipe_resource *resource ) 794 { 795 assert(This->level == 0 && This->level_actual == 0); 796 assert(!This->lock_count); 797 assert(This->desc.Pool == D3DPOOL_DEFAULT); 798 assert(!This->texture); 799 800 PROCESS_IF_BOUND(This); 801 pipe_resource_reference(&This->base.resource, resource); 802 803 This->desc.Width = This->base.info.width0 = resource->width0; 804 This->desc.Height = This->base.info.height0 = resource->height0; 805 This->base.info.nr_samples = resource->nr_samples; 806 807 This->stride = nine_format_get_stride(This->base.info.format, 808 This->desc.Width); 809 810 pipe_surface_reference(&This->surface[0], NULL); 811 pipe_surface_reference(&This->surface[1], NULL); 812 if (resource) 813 NineSurface9_CreatePipeSurfaces(This); 814 } 815 816 817 static const GUID *NineSurface9_IIDs[] = { 818 &IID_IDirect3DSurface9, 819 &IID_IDirect3DResource9, 820 &IID_IUnknown, 821 NULL 822 }; 823 824 HRESULT 825 NineSurface9_new( struct NineDevice9 *pDevice, 826 struct NineUnknown *pContainer, 827 struct pipe_resource *pResource, 828 void *user_buffer, 829 uint8_t TextureType, 830 unsigned Level, 831 unsigned Layer, 832 D3DSURFACE_DESC *pDesc, 833 struct NineSurface9 **ppOut ) 834 { 835 NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */ 836 pContainer, pResource, user_buffer, 837 TextureType, Level, Layer, pDesc); 838 } 839