1 /**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28 /*
29 * Resource.cpp --
30 * Functions that manipulate GPU resources.
31 */
32
33
34 #include "Resource.h"
35 #include "Format.h"
36 #include "State.h"
37 #include "Query.h"
38
39 #include "Debug.h"
40
41 #include "util/u_math.h"
42 #include "util/u_rect.h"
43 #include "util/u_surface.h"
44
45
46 /*
47 * ----------------------------------------------------------------------
48 *
49 * CalcPrivateResourceSize --
50 *
51 * The CalcPrivateResourceSize function determines the size of
52 * the user-mode display driver's private region of memory
53 * (that is, the size of internal driver structures, not the
54 * size of the resource video memory).
55 *
56 * ----------------------------------------------------------------------
57 */
58
59 SIZE_T APIENTRY
CalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATERESOURCE * pCreateResource)60 CalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice, // IN
61 __in const D3D10DDIARG_CREATERESOURCE *pCreateResource) // IN
62 {
63 LOG_ENTRYPOINT();
64 return sizeof(Resource);
65 }
66
67
68 static unsigned
translate_resource_usage(unsigned usage)69 translate_resource_usage( unsigned usage )
70 {
71 unsigned resource_usage = 0;
72
73 switch (usage) {
74 case D3D10_DDI_USAGE_DEFAULT:
75 resource_usage = PIPE_USAGE_DEFAULT;
76 break;
77 case D3D10_DDI_USAGE_IMMUTABLE:
78 resource_usage = PIPE_USAGE_IMMUTABLE;
79 break;
80 case D3D10_DDI_USAGE_DYNAMIC:
81 resource_usage = PIPE_USAGE_DYNAMIC;
82 break;
83 case D3D10_DDI_USAGE_STAGING:
84 resource_usage = PIPE_USAGE_STAGING;
85 break;
86 default:
87 assert(0);
88 break;
89 }
90
91 return resource_usage;
92 }
93
94
95 static unsigned
translate_resource_flags(UINT flags)96 translate_resource_flags(UINT flags)
97 {
98 unsigned bind = 0;
99
100 if (flags & D3D10_DDI_BIND_VERTEX_BUFFER)
101 bind |= PIPE_BIND_VERTEX_BUFFER;
102
103 if (flags & D3D10_DDI_BIND_INDEX_BUFFER)
104 bind |= PIPE_BIND_INDEX_BUFFER;
105
106 if (flags & D3D10_DDI_BIND_CONSTANT_BUFFER)
107 bind |= PIPE_BIND_CONSTANT_BUFFER;
108
109 if (flags & D3D10_DDI_BIND_SHADER_RESOURCE)
110 bind |= PIPE_BIND_SAMPLER_VIEW;
111
112 if (flags & D3D10_DDI_BIND_RENDER_TARGET)
113 bind |= PIPE_BIND_RENDER_TARGET;
114
115 if (flags & D3D10_DDI_BIND_DEPTH_STENCIL)
116 bind |= PIPE_BIND_DEPTH_STENCIL;
117
118 if (flags & D3D10_DDI_BIND_STREAM_OUTPUT)
119 bind |= PIPE_BIND_STREAM_OUTPUT;
120
121 return bind;
122 }
123
124
125 static enum pipe_texture_target
translate_texture_target(D3D10DDIRESOURCE_TYPE ResourceDimension,UINT ArraySize)126 translate_texture_target( D3D10DDIRESOURCE_TYPE ResourceDimension,
127 UINT ArraySize)
128 {
129 assert(ArraySize >= 1);
130 switch(ResourceDimension) {
131 case D3D10DDIRESOURCE_BUFFER:
132 assert(ArraySize == 1);
133 return PIPE_BUFFER;
134 case D3D10DDIRESOURCE_TEXTURE1D:
135 return ArraySize > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D;
136 case D3D10DDIRESOURCE_TEXTURE2D:
137 return ArraySize > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D;
138 case D3D10DDIRESOURCE_TEXTURE3D:
139 assert(ArraySize == 1);
140 return PIPE_TEXTURE_3D;
141 case D3D10DDIRESOURCE_TEXTURECUBE:
142 assert(ArraySize % 6 == 0);
143 return ArraySize > 6 ? PIPE_TEXTURE_CUBE_ARRAY : PIPE_TEXTURE_CUBE;
144 default:
145 assert(0);
146 return PIPE_TEXTURE_1D;
147 }
148 }
149
150
151 static void
subResourceBox(struct pipe_resource * resource,UINT SubResource,unsigned * pLevel,struct pipe_box * pBox)152 subResourceBox(struct pipe_resource *resource, // IN
153 UINT SubResource, // IN
154 unsigned *pLevel, // OUT
155 struct pipe_box *pBox) // OUT
156 {
157 UINT MipLevels = resource->last_level + 1;
158 unsigned layer;
159 unsigned width;
160 unsigned height;
161 unsigned depth;
162
163 *pLevel = SubResource % MipLevels;
164 layer = SubResource / MipLevels;
165
166 width = u_minify(resource->width0, *pLevel);
167 height = u_minify(resource->height0, *pLevel);
168 depth = u_minify(resource->depth0, *pLevel);
169
170 pBox->x = 0;
171 pBox->y = 0;
172 pBox->z = 0 + layer;
173 pBox->width = width;
174 pBox->height = height;
175 pBox->depth = depth;
176 }
177
178
179 /*
180 * ----------------------------------------------------------------------
181 *
182 * CreateResource --
183 *
184 * The CreateResource function creates a resource.
185 *
186 * ----------------------------------------------------------------------
187 */
188
189 void APIENTRY
CreateResource(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATERESOURCE * pCreateResource,D3D10DDI_HRESOURCE hResource,D3D10DDI_HRTRESOURCE hRTResource)190 CreateResource(D3D10DDI_HDEVICE hDevice, // IN
191 __in const D3D10DDIARG_CREATERESOURCE *pCreateResource, // IN
192 D3D10DDI_HRESOURCE hResource, // IN
193 D3D10DDI_HRTRESOURCE hRTResource) // IN
194 {
195 LOG_ENTRYPOINT();
196
197 if ((pCreateResource->MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED) ||
198 (pCreateResource->pPrimaryDesc &&
199 pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) {
200
201 DebugPrintf("%s(%dx%dx%d hResource=%p)\n",
202 __FUNCTION__,
203 pCreateResource->pMipInfoList[0].TexelWidth,
204 pCreateResource->pMipInfoList[0].TexelHeight,
205 pCreateResource->pMipInfoList[0].TexelDepth,
206 hResource.pDrvPrivate);
207 DebugPrintf(" ResourceDimension = %u\n",
208 pCreateResource->ResourceDimension);
209 DebugPrintf(" Usage = %u\n",
210 pCreateResource->Usage);
211 DebugPrintf(" BindFlags = 0x%x\n",
212 pCreateResource->BindFlags);
213 DebugPrintf(" MapFlags = 0x%x\n",
214 pCreateResource->MapFlags);
215 DebugPrintf(" MiscFlags = 0x%x\n",
216 pCreateResource->MiscFlags);
217 DebugPrintf(" Format = %s\n",
218 FormatToName(pCreateResource->Format));
219 DebugPrintf(" SampleDesc.Count = %u\n", pCreateResource->SampleDesc.Count);
220 DebugPrintf(" SampleDesc.Quality = %u\n", pCreateResource->SampleDesc.Quality);
221 DebugPrintf(" MipLevels = %u\n", pCreateResource->MipLevels);
222 DebugPrintf(" ArraySize = %u\n", pCreateResource->ArraySize);
223 DebugPrintf(" pPrimaryDesc = %p\n", pCreateResource->pPrimaryDesc);
224 if (pCreateResource->pPrimaryDesc) {
225 DebugPrintf(" Flags = 0x%x\n",
226 pCreateResource->pPrimaryDesc->Flags);
227 DebugPrintf(" VidPnSourceId = %u\n", pCreateResource->pPrimaryDesc->VidPnSourceId);
228 DebugPrintf(" ModeDesc.Width = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Width);
229 DebugPrintf(" ModeDesc.Height = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Height);
230 DebugPrintf(" ModeDesc.Format = %u)\n",
231 pCreateResource->pPrimaryDesc->ModeDesc.Format);
232 DebugPrintf(" ModeDesc.RefreshRate.Numerator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Numerator);
233 DebugPrintf(" ModeDesc.RefreshRate.Denominator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Denominator);
234 DebugPrintf(" ModeDesc.ScanlineOrdering = %u\n",
235 pCreateResource->pPrimaryDesc->ModeDesc.ScanlineOrdering);
236 DebugPrintf(" ModeDesc.Rotation = %u\n",
237 pCreateResource->pPrimaryDesc->ModeDesc.Rotation);
238 DebugPrintf(" ModeDesc.Scaling = %u\n",
239 pCreateResource->pPrimaryDesc->ModeDesc.Scaling);
240 DebugPrintf(" DriverFlags = 0x%x\n",
241 pCreateResource->pPrimaryDesc->DriverFlags);
242 }
243
244 }
245
246 struct pipe_context *pipe = CastPipeContext(hDevice);
247 struct pipe_screen *screen = pipe->screen;
248
249 Resource *pResource = CastResource(hResource);
250
251 memset(pResource, 0, sizeof *pResource);
252
253 #if 0
254 if (pCreateResource->pPrimaryDesc) {
255 pCreateResource->pPrimaryDesc->DriverFlags = DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT;
256 if (!(pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) {
257 // http://msdn.microsoft.com/en-us/library/windows/hardware/ff568846.aspx
258 SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED);
259 return;
260 }
261 }
262 #endif
263
264 pResource->Format = pCreateResource->Format;
265 pResource->MipLevels = pCreateResource->MipLevels;
266
267 struct pipe_resource templat;
268
269 memset(&templat, 0, sizeof templat);
270
271 templat.target = translate_texture_target( pCreateResource->ResourceDimension,
272 pCreateResource->ArraySize );
273 pResource->buffer = templat.target == PIPE_BUFFER;
274
275 if (pCreateResource->Format == DXGI_FORMAT_UNKNOWN) {
276 assert(pCreateResource->ResourceDimension == D3D10DDIRESOURCE_BUFFER);
277 templat.format = PIPE_FORMAT_R8_UINT;
278 } else {
279 BOOL bindDepthStencil = !!(pCreateResource->BindFlags & D3D10_DDI_BIND_DEPTH_STENCIL);
280 templat.format = FormatTranslate(pCreateResource->Format, bindDepthStencil);
281 }
282
283 templat.width0 = pCreateResource->pMipInfoList[0].TexelWidth;
284 templat.height0 = pCreateResource->pMipInfoList[0].TexelHeight;
285 templat.depth0 = pCreateResource->pMipInfoList[0].TexelDepth;
286 templat.array_size = pCreateResource->ArraySize;
287 templat.last_level = pCreateResource->MipLevels - 1;
288 templat.nr_samples = pCreateResource->SampleDesc.Count;
289 templat.nr_storage_samples = pCreateResource->SampleDesc.Count;
290 templat.bind = translate_resource_flags(pCreateResource->BindFlags);
291 templat.usage = translate_resource_usage(pCreateResource->Usage);
292
293 if (templat.target != PIPE_BUFFER) {
294 if (!screen->is_format_supported(screen,
295 templat.format,
296 templat.target,
297 templat.nr_samples,
298 templat.nr_storage_samples,
299 templat.bind)) {
300 debug_printf("%s: unsupported format %s\n",
301 __FUNCTION__, util_format_name(templat.format));
302 SetError(hDevice, E_OUTOFMEMORY);
303 return;
304 }
305 }
306
307 pResource->resource = screen->resource_create(screen, &templat);
308 if (!pResource) {
309 DebugPrintf("%s: failed to create resource\n", __FUNCTION__);
310 SetError(hDevice, E_OUTOFMEMORY);
311 return;
312 }
313
314 pResource->NumSubResources = pCreateResource->MipLevels * pCreateResource->ArraySize;
315 pResource->transfers = (struct pipe_transfer **)calloc(pResource->NumSubResources,
316 sizeof *pResource->transfers);
317
318 if (pCreateResource->pInitialDataUP) {
319 if (pResource->buffer) {
320 assert(pResource->NumSubResources == 1);
321 const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP =
322 &pCreateResource->pInitialDataUP[0];
323
324 unsigned level;
325 struct pipe_box box;
326 subResourceBox(pResource->resource, 0, &level, &box);
327
328 struct pipe_transfer *transfer;
329 void *map;
330 map = pipe->buffer_map(pipe,
331 pResource->resource,
332 level,
333 PIPE_MAP_WRITE |
334 PIPE_MAP_UNSYNCHRONIZED,
335 &box,
336 &transfer);
337 assert(map);
338 if (map) {
339 memcpy(map, pInitialDataUP->pSysMem, box.width);
340 pipe_buffer_unmap(pipe, transfer);
341 }
342 } else {
343 for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
344 const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP =
345 &pCreateResource->pInitialDataUP[SubResource];
346
347 unsigned level;
348 struct pipe_box box;
349 subResourceBox(pResource->resource, SubResource, &level, &box);
350
351 struct pipe_transfer *transfer;
352 void *map;
353 map = pipe->texture_map(pipe,
354 pResource->resource,
355 level,
356 PIPE_MAP_WRITE |
357 PIPE_MAP_UNSYNCHRONIZED,
358 &box,
359 &transfer);
360 assert(map);
361 if (map) {
362 for (int z = 0; z < box.depth; ++z) {
363 ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
364 const ubyte *src = (const ubyte*)pInitialDataUP->pSysMem + z*pInitialDataUP->SysMemSlicePitch;
365 util_copy_rect(dst,
366 templat.format,
367 transfer->stride,
368 0, 0, box.width, box.height,
369 src,
370 pInitialDataUP->SysMemPitch,
371 0, 0);
372 }
373 pipe_texture_unmap(pipe, transfer);
374 }
375 }
376 }
377 }
378 }
379
380
381 /*
382 * ----------------------------------------------------------------------
383 *
384 * CalcPrivateOpenedResourceSize --
385 *
386 * The CalcPrivateOpenedResourceSize function determines the size
387 * of the user-mode display driver's private shared region of memory
388 * (that is, the size of internal driver structures, not the size
389 * of the resource video memory) for an opened resource.
390 *
391 * ----------------------------------------------------------------------
392 */
393
394 SIZE_T APIENTRY
CalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_OPENRESOURCE * pOpenResource)395 CalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice, // IN
396 __in const D3D10DDIARG_OPENRESOURCE *pOpenResource) // IN
397 {
398 return sizeof(Resource);
399 }
400
401
402 /*
403 * ----------------------------------------------------------------------
404 *
405 * OpenResource --
406 *
407 * The OpenResource function opens a shared resource.
408 *
409 * ----------------------------------------------------------------------
410 */
411
412 void APIENTRY
OpenResource(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_OPENRESOURCE * pOpenResource,D3D10DDI_HRESOURCE hResource,D3D10DDI_HRTRESOURCE hRTResource)413 OpenResource(D3D10DDI_HDEVICE hDevice, // IN
414 __in const D3D10DDIARG_OPENRESOURCE *pOpenResource, // IN
415 D3D10DDI_HRESOURCE hResource, // IN
416 D3D10DDI_HRTRESOURCE hRTResource) // IN
417 {
418 LOG_UNSUPPORTED_ENTRYPOINT();
419 SetError(hDevice, E_OUTOFMEMORY);
420 }
421
422
423 /*
424 * ----------------------------------------------------------------------
425 *
426 * DestroyResource --
427 *
428 * The DestroyResource function destroys the specified resource
429 * object. The resource object can be destoyed only if it is not
430 * currently bound to a display device, and if all views that
431 * refer to the resource are also destroyed.
432 *
433 * ----------------------------------------------------------------------
434 */
435
436
437 void APIENTRY
DestroyResource(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hResource)438 DestroyResource(D3D10DDI_HDEVICE hDevice, // IN
439 D3D10DDI_HRESOURCE hResource) // IN
440 {
441 LOG_ENTRYPOINT();
442
443 struct pipe_context *pipe = CastPipeContext(hDevice);
444 Resource *pResource = CastResource(hResource);
445
446 if (pResource->so_target) {
447 pipe_so_target_reference(&pResource->so_target, NULL);
448 }
449
450 for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
451 if (pResource->transfers[SubResource]) {
452 if (pResource->buffer) {
453 pipe_buffer_unmap(pipe, pResource->transfers[SubResource]);
454 } else {
455 pipe_texture_unmap(pipe, pResource->transfers[SubResource]);
456 }
457 pResource->transfers[SubResource] = NULL;
458 }
459 }
460 free(pResource->transfers);
461
462 pipe_resource_reference(&pResource->resource, NULL);
463 }
464
465
466 /*
467 * ----------------------------------------------------------------------
468 *
469 * ResourceMap --
470 *
471 * The ResourceMap function maps a subresource of a resource.
472 *
473 * ----------------------------------------------------------------------
474 */
475
476 void APIENTRY
ResourceMap(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hResource,UINT SubResource,D3D10_DDI_MAP DDIMap,UINT Flags,__out D3D10DDI_MAPPED_SUBRESOURCE * pMappedSubResource)477 ResourceMap(D3D10DDI_HDEVICE hDevice, // IN
478 D3D10DDI_HRESOURCE hResource, // IN
479 UINT SubResource, // IN
480 D3D10_DDI_MAP DDIMap, // IN
481 UINT Flags, // IN
482 __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource) // OUT
483 {
484 LOG_ENTRYPOINT();
485
486 struct pipe_context *pipe = CastPipeContext(hDevice);
487 Resource *pResource = CastResource(hResource);
488 struct pipe_resource *resource = pResource->resource;
489
490 unsigned usage;
491 switch (DDIMap) {
492 case D3D10_DDI_MAP_READ:
493 usage = PIPE_MAP_READ;
494 break;
495 case D3D10_DDI_MAP_READWRITE:
496 usage = PIPE_MAP_READ | PIPE_MAP_WRITE;
497 break;
498 case D3D10_DDI_MAP_WRITE:
499 usage = PIPE_MAP_WRITE;
500 break;
501 case D3D10_DDI_MAP_WRITE_DISCARD:
502 usage = PIPE_MAP_WRITE;
503 if (resource->last_level == 0 && resource->array_size == 1) {
504 usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
505 } else {
506 usage |= PIPE_MAP_DISCARD_RANGE;
507 }
508 break;
509 case D3D10_DDI_MAP_WRITE_NOOVERWRITE:
510 usage = PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED;
511 break;
512 default:
513 assert(0);
514 return;
515 }
516
517 assert(SubResource < pResource->NumSubResources);
518
519 unsigned level;
520 struct pipe_box box;
521 subResourceBox(resource, SubResource, &level, &box);
522
523 assert(!pResource->transfers[SubResource]);
524
525 void *map;
526 if (pResource->buffer) {
527 map = pipe->buffer_map(pipe,
528 resource,
529 level,
530 usage,
531 &box,
532 &pResource->transfers[SubResource]);
533 } else {
534 map = pipe->texture_map(pipe,
535 resource,
536 level,
537 usage,
538 &box,
539 &pResource->transfers[SubResource]);
540 }
541 if (!map) {
542 DebugPrintf("%s: failed to map resource\n", __FUNCTION__);
543 SetError(hDevice, E_FAIL);
544 return;
545 }
546
547 pMappedSubResource->pData = map;
548 pMappedSubResource->RowPitch = pResource->transfers[SubResource]->stride;
549 pMappedSubResource->DepthPitch = pResource->transfers[SubResource]->layer_stride;
550 }
551
552
553 /*
554 * ----------------------------------------------------------------------
555 *
556 * ResourceUnmap --
557 *
558 * The ResourceUnmap function unmaps a subresource of a resource.
559 *
560 * ----------------------------------------------------------------------
561 */
562
563 void APIENTRY
ResourceUnmap(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hResource,UINT SubResource)564 ResourceUnmap(D3D10DDI_HDEVICE hDevice, // IN
565 D3D10DDI_HRESOURCE hResource, // IN
566 UINT SubResource) // IN
567 {
568 LOG_ENTRYPOINT();
569
570 struct pipe_context *pipe = CastPipeContext(hDevice);
571 Resource *pResource = CastResource(hResource);
572
573 assert(SubResource < pResource->NumSubResources);
574
575 if (pResource->transfers[SubResource]) {
576 if (pResource->buffer) {
577 pipe_buffer_unmap(pipe, pResource->transfers[SubResource]);
578 } else {
579 pipe_texture_unmap(pipe, pResource->transfers[SubResource]);
580 }
581 pResource->transfers[SubResource] = NULL;
582 }
583 }
584
585
586 /*
587 *----------------------------------------------------------------------
588 *
589 * areResourcesCompatible --
590 *
591 * Check whether two resources can be safely passed to
592 * pipe_context::resource_copy_region method.
593 *
594 * Results:
595 * As above.
596 *
597 * Side effects:
598 * None.
599 *
600 *----------------------------------------------------------------------
601 */
602
603 static bool
areResourcesCompatible(const struct pipe_resource * src_resource,const struct pipe_resource * dst_resource)604 areResourcesCompatible(const struct pipe_resource *src_resource, // IN
605 const struct pipe_resource *dst_resource) // IN
606 {
607 if (src_resource->format == dst_resource->format) {
608 /*
609 * Trivial.
610 */
611
612 return TRUE;
613 } else if (src_resource->target == PIPE_BUFFER &&
614 dst_resource->target == PIPE_BUFFER) {
615 /*
616 * Buffer resources are merely a collection of bytes.
617 */
618
619 return TRUE;
620 } else {
621 /*
622 * Check whether the formats are supported by
623 * the resource_copy_region method.
624 */
625
626 const struct util_format_description *src_format_desc;
627 const struct util_format_description *dst_format_desc;
628
629 src_format_desc = util_format_description(src_resource->format);
630 dst_format_desc = util_format_description(dst_resource->format);
631
632 assert(src_format_desc->block.width == dst_format_desc->block.width);
633 assert(src_format_desc->block.height == dst_format_desc->block.height);
634 assert(src_format_desc->block.bits == dst_format_desc->block.bits);
635
636 return util_is_format_compatible(src_format_desc, dst_format_desc);
637 }
638 }
639
640
641 /*
642 * ----------------------------------------------------------------------
643 *
644 * ResourceCopy --
645 *
646 * The ResourceCopy function copies an entire source
647 * resource to a destination resource.
648 *
649 * ----------------------------------------------------------------------
650 */
651
652 void APIENTRY
ResourceCopy(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hDstResource,D3D10DDI_HRESOURCE hSrcResource)653 ResourceCopy(D3D10DDI_HDEVICE hDevice, // IN
654 D3D10DDI_HRESOURCE hDstResource, // IN
655 D3D10DDI_HRESOURCE hSrcResource) // IN
656 {
657 LOG_ENTRYPOINT();
658
659 Device *pDevice = CastDevice(hDevice);
660 if (!CheckPredicate(pDevice)) {
661 return;
662 }
663
664 struct pipe_context *pipe = pDevice->pipe;
665 Resource *pDstResource = CastResource(hDstResource);
666 Resource *pSrcResource = CastResource(hSrcResource);
667 struct pipe_resource *dst_resource = pDstResource->resource;
668 struct pipe_resource *src_resource = pSrcResource->resource;
669 bool compatible;
670
671 assert(dst_resource->target == src_resource->target);
672 assert(dst_resource->width0 == src_resource->width0);
673 assert(dst_resource->height0 == src_resource->height0);
674 assert(dst_resource->depth0 == src_resource->depth0);
675 assert(dst_resource->last_level == src_resource->last_level);
676 assert(dst_resource->array_size == src_resource->array_size);
677
678 compatible = areResourcesCompatible(src_resource, dst_resource);
679
680 /* could also use one 3d copy for arrays */
681 for (unsigned layer = 0; layer < dst_resource->array_size; ++layer) {
682 for (unsigned level = 0; level <= dst_resource->last_level; ++level) {
683 struct pipe_box box;
684 box.x = 0;
685 box.y = 0;
686 box.z = 0 + layer;
687 box.width = u_minify(dst_resource->width0, level);
688 box.height = u_minify(dst_resource->height0, level);
689 box.depth = u_minify(dst_resource->depth0, level);
690
691 if (compatible) {
692 pipe->resource_copy_region(pipe,
693 dst_resource, level,
694 0, 0, layer,
695 src_resource, level,
696 &box);
697 } else {
698 util_resource_copy_region(pipe,
699 dst_resource, level,
700 0, 0, layer,
701 src_resource, level,
702 &box);
703 }
704 }
705 }
706 }
707
708
709 /*
710 * ----------------------------------------------------------------------
711 *
712 * ResourceCopyRegion --
713 *
714 * The ResourceCopyRegion function copies a source subresource
715 * region to a location on a destination subresource.
716 *
717 * ----------------------------------------------------------------------
718 */
719
720 void APIENTRY
ResourceCopyRegion(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hDstResource,UINT DstSubResource,UINT DstX,UINT DstY,UINT DstZ,D3D10DDI_HRESOURCE hSrcResource,UINT SrcSubResource,__in_opt const D3D10_DDI_BOX * pSrcBox)721 ResourceCopyRegion(D3D10DDI_HDEVICE hDevice, // IN
722 D3D10DDI_HRESOURCE hDstResource, // IN
723 UINT DstSubResource, // IN
724 UINT DstX, // IN
725 UINT DstY, // IN
726 UINT DstZ, // IN
727 D3D10DDI_HRESOURCE hSrcResource, // IN
728 UINT SrcSubResource, // IN
729 __in_opt const D3D10_DDI_BOX *pSrcBox) // IN (optional)
730 {
731 LOG_ENTRYPOINT();
732
733 Device *pDevice = CastDevice(hDevice);
734 if (!CheckPredicate(pDevice)) {
735 return;
736 }
737
738 struct pipe_context *pipe = pDevice->pipe;
739 Resource *pDstResource = CastResource(hDstResource);
740 Resource *pSrcResource = CastResource(hSrcResource);
741 struct pipe_resource *dst_resource = pDstResource->resource;
742 struct pipe_resource *src_resource = pSrcResource->resource;
743
744 unsigned dst_level = DstSubResource % (dst_resource->last_level + 1);
745 unsigned dst_layer = DstSubResource / (dst_resource->last_level + 1);
746 unsigned src_level = SrcSubResource % (src_resource->last_level + 1);
747 unsigned src_layer = SrcSubResource / (src_resource->last_level + 1);
748
749 struct pipe_box src_box;
750 if (pSrcBox) {
751 src_box.x = pSrcBox->left;
752 src_box.y = pSrcBox->top;
753 src_box.z = pSrcBox->front + src_layer;
754 src_box.width = pSrcBox->right - pSrcBox->left;
755 src_box.height = pSrcBox->bottom - pSrcBox->top;
756 src_box.depth = pSrcBox->back - pSrcBox->front;
757 } else {
758 src_box.x = 0;
759 src_box.y = 0;
760 src_box.z = 0 + src_layer;
761 src_box.width = u_minify(src_resource->width0, src_level);
762 src_box.height = u_minify(src_resource->height0, src_level);
763 src_box.depth = u_minify(src_resource->depth0, src_level);
764 }
765
766 if (areResourcesCompatible(src_resource, dst_resource)) {
767 pipe->resource_copy_region(pipe,
768 dst_resource, dst_level,
769 DstX, DstY, DstZ + dst_layer,
770 src_resource, src_level,
771 &src_box);
772 } else {
773 util_resource_copy_region(pipe,
774 dst_resource, dst_level,
775 DstX, DstY, DstZ + dst_layer,
776 src_resource, src_level,
777 &src_box);
778 }
779 }
780
781
782 /*
783 * ----------------------------------------------------------------------
784 *
785 * ResourceResolveSubResource --
786 *
787 * The ResourceResolveSubResource function resolves
788 * multiple samples to one pixel.
789 *
790 * ----------------------------------------------------------------------
791 */
792
793 void APIENTRY
ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hDstResource,UINT DstSubResource,D3D10DDI_HRESOURCE hSrcResource,UINT SrcSubResource,DXGI_FORMAT ResolveFormat)794 ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice, // IN
795 D3D10DDI_HRESOURCE hDstResource, // IN
796 UINT DstSubResource, // IN
797 D3D10DDI_HRESOURCE hSrcResource, // IN
798 UINT SrcSubResource, // IN
799 DXGI_FORMAT ResolveFormat) // IN
800 {
801 LOG_UNSUPPORTED_ENTRYPOINT();
802 }
803
804
805 /*
806 * ----------------------------------------------------------------------
807 *
808 * ResourceIsStagingBusy --
809 *
810 * The ResourceIsStagingBusy function determines whether a
811 * resource is currently being used by the graphics pipeline.
812 *
813 * ----------------------------------------------------------------------
814 */
815
816 BOOL APIENTRY
ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hResource)817 ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice, // IN
818 D3D10DDI_HRESOURCE hResource) // IN
819 {
820 LOG_ENTRYPOINT();
821
822 /* ignore */
823
824 return FALSE;
825 }
826
827
828 /*
829 * ----------------------------------------------------------------------
830 *
831 * ResourceReadAfterWriteHazard --
832 *
833 * The ResourceReadAfterWriteHazard function informs the user-mode
834 * display driver that the specified resource was used as an output
835 * from the graphics processing unit (GPU) and that the resource
836 * will be used as an input to the GPU.
837 *
838 * ----------------------------------------------------------------------
839 */
840
841 void APIENTRY
ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hResource)842 ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, // IN
843 D3D10DDI_HRESOURCE hResource) // IN
844 {
845 LOG_ENTRYPOINT();
846
847 /* Not actually necessary */
848 }
849
850
851 /*
852 * ----------------------------------------------------------------------
853 *
854 * ResourceUpdateSubResourceUP --
855 *
856 * The ResourceUpdateSubresourceUP function updates a
857 * destination subresource region from a source
858 * system memory region.
859 *
860 * ----------------------------------------------------------------------
861 */
862
863 void APIENTRY
ResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hDstResource,UINT DstSubResource,__in_opt const D3D10_DDI_BOX * pDstBox,__in const void * pSysMemUP,UINT RowPitch,UINT DepthPitch)864 ResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice, // IN
865 D3D10DDI_HRESOURCE hDstResource, // IN
866 UINT DstSubResource, // IN
867 __in_opt const D3D10_DDI_BOX *pDstBox, // IN
868 __in const void *pSysMemUP, // IN
869 UINT RowPitch, // IN
870 UINT DepthPitch) // IN
871 {
872 LOG_ENTRYPOINT();
873
874 Device *pDevice = CastDevice(hDevice);
875 if (!CheckPredicate(pDevice)) {
876 return;
877 }
878
879 struct pipe_context *pipe = pDevice->pipe;
880 Resource *pDstResource = CastResource(hDstResource);
881 struct pipe_resource *dst_resource = pDstResource->resource;
882
883 unsigned level;
884 struct pipe_box box;
885
886 if (pDstBox) {
887 UINT DstMipLevels = dst_resource->last_level + 1;
888 level = DstSubResource % DstMipLevels;
889 unsigned dst_layer = DstSubResource / DstMipLevels;
890 box.x = pDstBox->left;
891 box.y = pDstBox->top;
892 box.z = pDstBox->front + dst_layer;
893 box.width = pDstBox->right - pDstBox->left;
894 box.height = pDstBox->bottom - pDstBox->top;
895 box.depth = pDstBox->back - pDstBox->front;
896 } else {
897 subResourceBox(dst_resource, DstSubResource, &level, &box);
898 }
899
900 struct pipe_transfer *transfer;
901 void *map;
902 if (pDstResource->buffer) {
903 map = pipe->buffer_map(pipe,
904 dst_resource,
905 level,
906 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
907 &box,
908 &transfer);
909 } else {
910 map = pipe->texture_map(pipe,
911 dst_resource,
912 level,
913 PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
914 &box,
915 &transfer);
916 }
917 assert(map);
918 if (map) {
919 for (int z = 0; z < box.depth; ++z) {
920 ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
921 const ubyte *src = (const ubyte*)pSysMemUP + z*DepthPitch;
922 util_copy_rect(dst,
923 dst_resource->format,
924 transfer->stride,
925 0, 0, box.width, box.height,
926 src,
927 RowPitch,
928 0, 0);
929 }
930 if (pDstResource->buffer) {
931 pipe_buffer_unmap(pipe, transfer);
932 } else {
933 pipe_texture_unmap(pipe, transfer);
934 }
935 }
936 }
937
938