Resource.cpp revision 7ec681f3
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
59SIZE_T APIENTRY
60CalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice,                                // IN
61                        __in const D3D10DDIARG_CREATERESOURCE *pCreateResource)  // IN
62{
63   LOG_ENTRYPOINT();
64   return sizeof(Resource);
65}
66
67
68static unsigned
69translate_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
95static unsigned
96translate_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
125static enum pipe_texture_target
126translate_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
151static void
152subResourceBox(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
189void APIENTRY
190CreateResource(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
274   if (pCreateResource->Format == DXGI_FORMAT_UNKNOWN) {
275      assert(pCreateResource->ResourceDimension == D3D10DDIRESOURCE_BUFFER);
276      templat.format = PIPE_FORMAT_R8_UINT;
277   } else {
278      BOOL bindDepthStencil = !!(pCreateResource->BindFlags & D3D10_DDI_BIND_DEPTH_STENCIL);
279      templat.format = FormatTranslate(pCreateResource->Format, bindDepthStencil);
280   }
281
282   templat.width0     = pCreateResource->pMipInfoList[0].TexelWidth;
283   templat.height0    = pCreateResource->pMipInfoList[0].TexelHeight;
284   templat.depth0     = pCreateResource->pMipInfoList[0].TexelDepth;
285   templat.array_size = pCreateResource->ArraySize;
286   templat.last_level = pCreateResource->MipLevels - 1;
287   templat.nr_samples = pCreateResource->SampleDesc.Count;
288   templat.nr_storage_samples = pCreateResource->SampleDesc.Count;
289   templat.bind       = translate_resource_flags(pCreateResource->BindFlags);
290   templat.usage      = translate_resource_usage(pCreateResource->Usage);
291
292   if (templat.target != PIPE_BUFFER) {
293      if (!screen->is_format_supported(screen,
294                                       templat.format,
295                                       templat.target,
296                                       templat.nr_samples,
297                                       templat.nr_storage_samples,
298                                       templat.bind)) {
299         debug_printf("%s: unsupported format %s\n",
300                     __FUNCTION__, util_format_name(templat.format));
301         SetError(hDevice, E_OUTOFMEMORY);
302         return;
303      }
304   }
305
306   pResource->resource = screen->resource_create(screen, &templat);
307   if (!pResource) {
308      DebugPrintf("%s: failed to create resource\n", __FUNCTION__);
309      SetError(hDevice, E_OUTOFMEMORY);
310      return;
311   }
312
313   pResource->NumSubResources = pCreateResource->MipLevels * pCreateResource->ArraySize;
314   pResource->transfers = (struct pipe_transfer **)calloc(pResource->NumSubResources,
315                                                          sizeof *pResource->transfers);
316
317   if (pCreateResource->pInitialDataUP) {
318      for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
319         const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP =
320               &pCreateResource->pInitialDataUP[SubResource];
321
322         unsigned level;
323         struct pipe_box box;
324         subResourceBox(pResource->resource, SubResource, &level, &box);
325
326         struct pipe_transfer *transfer;
327         void *map;
328         map = pipe->transfer_map(pipe,
329                                  pResource->resource,
330                                  level,
331                                  PIPE_MAP_WRITE |
332                                  PIPE_MAP_UNSYNCHRONIZED,
333                                  &box,
334                                  &transfer);
335         assert(map);
336         if (map) {
337            for (int z = 0; z < box.depth; ++z) {
338               ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
339               const ubyte *src = (const ubyte*)pInitialDataUP->pSysMem + z*pInitialDataUP->SysMemSlicePitch;
340               util_copy_rect(dst,
341                              templat.format,
342                              transfer->stride,
343                              0, 0, box.width, box.height,
344                              src,
345                              pInitialDataUP->SysMemPitch,
346                              0, 0);
347            }
348            pipe_transfer_unmap(pipe, transfer);
349         }
350      }
351   }
352}
353
354
355/*
356 * ----------------------------------------------------------------------
357 *
358 * CalcPrivateOpenedResourceSize --
359 *
360 *    The CalcPrivateOpenedResourceSize function determines the size
361 *    of the user-mode display driver's private shared region of memory
362 *    (that is, the size of internal driver structures, not the size
363 *    of the resource video memory) for an opened resource.
364 *
365 * ----------------------------------------------------------------------
366 */
367
368SIZE_T APIENTRY
369CalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice,                             // IN
370                              __in const D3D10DDIARG_OPENRESOURCE *pOpenResource)   // IN
371{
372   return sizeof(Resource);
373}
374
375
376/*
377 * ----------------------------------------------------------------------
378 *
379 * OpenResource --
380 *
381 *    The OpenResource function opens a shared resource.
382 *
383 * ----------------------------------------------------------------------
384 */
385
386void APIENTRY
387OpenResource(D3D10DDI_HDEVICE hDevice,                            // IN
388             __in const D3D10DDIARG_OPENRESOURCE *pOpenResource,  // IN
389             D3D10DDI_HRESOURCE hResource,                        // IN
390             D3D10DDI_HRTRESOURCE hRTResource)                    // IN
391{
392   LOG_UNSUPPORTED_ENTRYPOINT();
393   SetError(hDevice, E_OUTOFMEMORY);
394}
395
396
397/*
398 * ----------------------------------------------------------------------
399 *
400 * DestroyResource --
401 *
402 *    The DestroyResource function destroys the specified resource
403 *    object. The resource object can be destoyed only if it is not
404 *    currently bound to a display device, and if all views that
405 *    refer to the resource are also destroyed.
406 *
407 * ----------------------------------------------------------------------
408 */
409
410
411void APIENTRY
412DestroyResource(D3D10DDI_HDEVICE hDevice,       // IN
413                D3D10DDI_HRESOURCE hResource)   // IN
414{
415   LOG_ENTRYPOINT();
416
417   struct pipe_context *pipe = CastPipeContext(hDevice);
418   Resource *pResource = CastResource(hResource);
419
420   if (pResource->so_target) {
421      pipe_so_target_reference(&pResource->so_target, NULL);
422   }
423
424   for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
425      if (pResource->transfers[SubResource]) {
426         pipe_transfer_unmap(pipe, pResource->transfers[SubResource]);
427         pResource->transfers[SubResource] = NULL;
428      }
429   }
430   free(pResource->transfers);
431
432   pipe_resource_reference(&pResource->resource, NULL);
433}
434
435
436/*
437 * ----------------------------------------------------------------------
438 *
439 * ResourceMap --
440 *
441 *    The ResourceMap function maps a subresource of a resource.
442 *
443 * ----------------------------------------------------------------------
444 */
445
446void APIENTRY
447ResourceMap(D3D10DDI_HDEVICE hDevice,                                // IN
448            D3D10DDI_HRESOURCE hResource,                            // IN
449            UINT SubResource,                                        // IN
450            D3D10_DDI_MAP DDIMap,                                    // IN
451            UINT Flags,                                              // IN
452            __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource)   // OUT
453{
454   LOG_ENTRYPOINT();
455
456   struct pipe_context *pipe = CastPipeContext(hDevice);
457   Resource *pResource = CastResource(hResource);
458   struct pipe_resource *resource = pResource->resource;
459
460   unsigned usage;
461   switch (DDIMap) {
462   case D3D10_DDI_MAP_READ:
463      usage = PIPE_MAP_READ;
464      break;
465   case D3D10_DDI_MAP_READWRITE:
466      usage = PIPE_MAP_READ | PIPE_MAP_WRITE;
467      break;
468   case D3D10_DDI_MAP_WRITE:
469      usage = PIPE_MAP_WRITE;
470      break;
471   case D3D10_DDI_MAP_WRITE_DISCARD:
472      usage = PIPE_MAP_WRITE;
473      if (resource->last_level == 0 && resource->array_size == 1) {
474         usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
475      } else {
476         usage |= PIPE_MAP_DISCARD_RANGE;
477      }
478      break;
479   case D3D10_DDI_MAP_WRITE_NOOVERWRITE:
480      usage = PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED;
481      break;
482   default:
483      assert(0);
484      return;
485   }
486
487   assert(SubResource < pResource->NumSubResources);
488
489   unsigned level;
490   struct pipe_box box;
491   subResourceBox(resource, SubResource, &level, &box);
492
493   assert(!pResource->transfers[SubResource]);
494
495   void *map;
496   map = pipe->transfer_map(pipe,
497                            resource,
498                            level,
499                            usage,
500                            &box,
501                            &pResource->transfers[SubResource]);
502   if (!map) {
503      DebugPrintf("%s: failed to map resource\n", __FUNCTION__);
504      SetError(hDevice, E_FAIL);
505      return;
506   }
507
508   pMappedSubResource->pData = map;
509   pMappedSubResource->RowPitch = pResource->transfers[SubResource]->stride;
510   pMappedSubResource->DepthPitch = pResource->transfers[SubResource]->layer_stride;
511}
512
513
514/*
515 * ----------------------------------------------------------------------
516 *
517 * ResourceUnmap --
518 *
519 *    The ResourceUnmap function unmaps a subresource of a resource.
520 *
521 * ----------------------------------------------------------------------
522 */
523
524void APIENTRY
525ResourceUnmap(D3D10DDI_HDEVICE hDevice,      // IN
526              D3D10DDI_HRESOURCE hResource,  // IN
527              UINT SubResource)              // IN
528{
529   LOG_ENTRYPOINT();
530
531   struct pipe_context *pipe = CastPipeContext(hDevice);
532   Resource *pResource = CastResource(hResource);
533
534   assert(SubResource < pResource->NumSubResources);
535
536   if (pResource->transfers[SubResource]) {
537      pipe_transfer_unmap(pipe, pResource->transfers[SubResource]);
538      pResource->transfers[SubResource] = NULL;
539   }
540}
541
542
543/*
544 *----------------------------------------------------------------------
545 *
546 * areResourcesCompatible --
547 *
548 *      Check whether two resources can be safely passed to
549 *      pipe_context::resource_copy_region method.
550 *
551 * Results:
552 *      As above.
553 *
554 * Side effects:
555 *      None.
556 *
557 *----------------------------------------------------------------------
558 */
559
560static bool
561areResourcesCompatible(const struct pipe_resource *src_resource, // IN
562                       const struct pipe_resource *dst_resource) // IN
563{
564   if (src_resource->format == dst_resource->format) {
565      /*
566       * Trivial.
567       */
568
569      return TRUE;
570   } else if (src_resource->target == PIPE_BUFFER &&
571              dst_resource->target == PIPE_BUFFER) {
572      /*
573       * Buffer resources are merely a collection of bytes.
574       */
575
576      return TRUE;
577   } else {
578      /*
579       * Check whether the formats are supported by
580       * the resource_copy_region method.
581       */
582
583      const struct util_format_description *src_format_desc;
584      const struct util_format_description *dst_format_desc;
585
586      src_format_desc = util_format_description(src_resource->format);
587      dst_format_desc = util_format_description(dst_resource->format);
588
589      assert(src_format_desc->block.width  == dst_format_desc->block.width);
590      assert(src_format_desc->block.height == dst_format_desc->block.height);
591      assert(src_format_desc->block.bits   == dst_format_desc->block.bits);
592
593      return util_is_format_compatible(src_format_desc, dst_format_desc);
594   }
595}
596
597
598/*
599 * ----------------------------------------------------------------------
600 *
601 * ResourceCopy --
602 *
603 *    The ResourceCopy function copies an entire source
604 *    resource to a destination resource.
605 *
606 * ----------------------------------------------------------------------
607 */
608
609void APIENTRY
610ResourceCopy(D3D10DDI_HDEVICE hDevice,          // IN
611             D3D10DDI_HRESOURCE hDstResource,   // IN
612             D3D10DDI_HRESOURCE hSrcResource)   // IN
613{
614   LOG_ENTRYPOINT();
615
616   Device *pDevice = CastDevice(hDevice);
617   if (!CheckPredicate(pDevice)) {
618      return;
619   }
620
621   struct pipe_context *pipe = pDevice->pipe;
622   Resource *pDstResource = CastResource(hDstResource);
623   Resource *pSrcResource = CastResource(hSrcResource);
624   struct pipe_resource *dst_resource = pDstResource->resource;
625   struct pipe_resource *src_resource = pSrcResource->resource;
626   bool compatible;
627
628   assert(dst_resource->target == src_resource->target);
629   assert(dst_resource->width0 == src_resource->width0);
630   assert(dst_resource->height0 == src_resource->height0);
631   assert(dst_resource->depth0 == src_resource->depth0);
632   assert(dst_resource->last_level == src_resource->last_level);
633   assert(dst_resource->array_size == src_resource->array_size);
634
635   compatible = areResourcesCompatible(src_resource, dst_resource);
636
637   /* could also use one 3d copy for arrays */
638   for (unsigned layer = 0; layer < dst_resource->array_size; ++layer) {
639      for (unsigned level = 0; level <= dst_resource->last_level; ++level) {
640         struct pipe_box box;
641         box.x = 0;
642         box.y = 0;
643         box.z = 0 + layer;
644         box.width  = u_minify(dst_resource->width0,  level);
645         box.height = u_minify(dst_resource->height0, level);
646         box.depth  = u_minify(dst_resource->depth0,  level);
647
648	 if (compatible) {
649            pipe->resource_copy_region(pipe,
650                                       dst_resource, level,
651                                       0, 0, layer,
652                                       src_resource, level,
653                                       &box);
654         } else {
655            util_resource_copy_region(pipe,
656                                      dst_resource, level,
657                                      0, 0, layer,
658                                      src_resource, level,
659                                      &box);
660         }
661      }
662   }
663}
664
665
666/*
667 * ----------------------------------------------------------------------
668 *
669 * ResourceCopyRegion --
670 *
671 *    The ResourceCopyRegion function copies a source subresource
672 *    region to a location on a destination subresource.
673 *
674 * ----------------------------------------------------------------------
675 */
676
677void APIENTRY
678ResourceCopyRegion(D3D10DDI_HDEVICE hDevice,                // IN
679                   D3D10DDI_HRESOURCE hDstResource,         // IN
680                   UINT DstSubResource,                     // IN
681                   UINT DstX,                               // IN
682                   UINT DstY,                               // IN
683                   UINT DstZ,                               // IN
684                   D3D10DDI_HRESOURCE hSrcResource,         // IN
685                   UINT SrcSubResource,                     // IN
686                   __in_opt const D3D10_DDI_BOX *pSrcBox)   // IN (optional)
687{
688   LOG_ENTRYPOINT();
689
690   Device *pDevice = CastDevice(hDevice);
691   if (!CheckPredicate(pDevice)) {
692      return;
693   }
694
695   struct pipe_context *pipe = pDevice->pipe;
696   Resource *pDstResource = CastResource(hDstResource);
697   Resource *pSrcResource = CastResource(hSrcResource);
698   struct pipe_resource *dst_resource = pDstResource->resource;
699   struct pipe_resource *src_resource = pSrcResource->resource;
700
701   unsigned dst_level = DstSubResource % (dst_resource->last_level + 1);
702   unsigned dst_layer = DstSubResource / (dst_resource->last_level + 1);
703   unsigned src_level = SrcSubResource % (src_resource->last_level + 1);
704   unsigned src_layer = SrcSubResource / (src_resource->last_level + 1);
705
706   struct pipe_box src_box;
707   if (pSrcBox) {
708      src_box.x = pSrcBox->left;
709      src_box.y = pSrcBox->top;
710      src_box.z = pSrcBox->front + src_layer;
711      src_box.width  = pSrcBox->right  - pSrcBox->left;
712      src_box.height = pSrcBox->bottom - pSrcBox->top;
713      src_box.depth  = pSrcBox->back   - pSrcBox->front;
714   } else {
715      src_box.x = 0;
716      src_box.y = 0;
717      src_box.z = 0 + src_layer;
718      src_box.width  = u_minify(src_resource->width0,  src_level);
719      src_box.height = u_minify(src_resource->height0, src_level);
720      src_box.depth  = u_minify(src_resource->depth0,  src_level);
721   }
722
723   if (areResourcesCompatible(src_resource, dst_resource)) {
724      pipe->resource_copy_region(pipe,
725                                 dst_resource, dst_level,
726                                 DstX, DstY, DstZ + dst_layer,
727                                 src_resource, src_level,
728                                 &src_box);
729   } else {
730      util_resource_copy_region(pipe,
731                                dst_resource, dst_level,
732                                DstX, DstY, DstZ + dst_layer,
733                                src_resource, src_level,
734                                &src_box);
735   }
736}
737
738
739/*
740 * ----------------------------------------------------------------------
741 *
742 * ResourceResolveSubResource --
743 *
744 *    The ResourceResolveSubResource function resolves
745 *    multiple samples to one pixel.
746 *
747 * ----------------------------------------------------------------------
748 */
749
750void APIENTRY
751ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice,        // IN
752                           D3D10DDI_HRESOURCE hDstResource, // IN
753                           UINT DstSubResource,             // IN
754                           D3D10DDI_HRESOURCE hSrcResource, // IN
755                           UINT SrcSubResource,             // IN
756                           DXGI_FORMAT ResolveFormat)       // IN
757{
758   LOG_UNSUPPORTED_ENTRYPOINT();
759}
760
761
762/*
763 * ----------------------------------------------------------------------
764 *
765 * ResourceIsStagingBusy --
766 *
767 *    The ResourceIsStagingBusy function determines whether a
768 *    resource is currently being used by the graphics pipeline.
769 *
770 * ----------------------------------------------------------------------
771 */
772
773BOOL APIENTRY
774ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice,       // IN
775                      D3D10DDI_HRESOURCE hResource)   // IN
776{
777   LOG_ENTRYPOINT();
778
779   /* ignore */
780
781   return FALSE;
782}
783
784
785/*
786 * ----------------------------------------------------------------------
787 *
788 * ResourceReadAfterWriteHazard --
789 *
790 *    The ResourceReadAfterWriteHazard function informs the user-mode
791 *    display driver that the specified resource was used as an output
792 *    from the graphics processing unit (GPU) and that the resource
793 *    will be used as an input to the GPU.
794 *
795 * ----------------------------------------------------------------------
796 */
797
798void APIENTRY
799ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice,      // IN
800                             D3D10DDI_HRESOURCE hResource)  // IN
801{
802   LOG_ENTRYPOINT();
803
804   /* Not actually necessary */
805}
806
807
808/*
809 * ----------------------------------------------------------------------
810 *
811 * ResourceUpdateSubResourceUP --
812 *
813 *    The ResourceUpdateSubresourceUP function updates a
814 *    destination subresource region from a source
815 *    system memory region.
816 *
817 * ----------------------------------------------------------------------
818 */
819
820void APIENTRY
821ResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice,                // IN
822                            D3D10DDI_HRESOURCE hDstResource,         // IN
823                            UINT DstSubResource,                     // IN
824                            __in_opt const D3D10_DDI_BOX *pDstBox,   // IN
825                            __in const void *pSysMemUP,              // IN
826                            UINT RowPitch,                           // IN
827                            UINT DepthPitch)                         // IN
828{
829   LOG_ENTRYPOINT();
830
831   Device *pDevice = CastDevice(hDevice);
832   if (!CheckPredicate(pDevice)) {
833      return;
834   }
835
836   struct pipe_context *pipe = pDevice->pipe;
837   struct pipe_resource *dst_resource = CastPipeResource(hDstResource);
838
839   unsigned level;
840   struct pipe_box box;
841
842   if (pDstBox) {
843      UINT DstMipLevels = dst_resource->last_level + 1;
844      level = DstSubResource % DstMipLevels;
845      unsigned dst_layer = DstSubResource / DstMipLevels;
846      box.x = pDstBox->left;
847      box.y = pDstBox->top;
848      box.z = pDstBox->front + dst_layer;
849      box.width  = pDstBox->right  - pDstBox->left;
850      box.height = pDstBox->bottom - pDstBox->top;
851      box.depth  = pDstBox->back   - pDstBox->front;
852   } else {
853      subResourceBox(dst_resource, DstSubResource, &level, &box);
854   }
855
856   struct pipe_transfer *transfer;
857   void *map;
858   map = pipe->transfer_map(pipe,
859                            dst_resource,
860                            level,
861                            PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
862                            &box,
863                            &transfer);
864   assert(map);
865   if (map) {
866      for (int z = 0; z < box.depth; ++z) {
867         ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
868         const ubyte *src = (const ubyte*)pSysMemUP + z*DepthPitch;
869         util_copy_rect(dst,
870                        dst_resource->format,
871                        transfer->stride,
872                        0, 0, box.width, box.height,
873                        src,
874                        RowPitch,
875                        0, 0);
876      }
877      pipe_transfer_unmap(pipe, transfer);
878   }
879}
880
881