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