xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/d3d10umd/Resource.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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