• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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