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   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
394SIZE_T APIENTRY
395CalcPrivateOpenedResourceSize(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
412void APIENTRY
413OpenResource(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
437void APIENTRY
438DestroyResource(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
476void APIENTRY
477ResourceMap(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
563void APIENTRY
564ResourceUnmap(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
603static bool
604areResourcesCompatible(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
652void APIENTRY
653ResourceCopy(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
720void APIENTRY
721ResourceCopyRegion(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
793void APIENTRY
794ResourceResolveSubResource(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
816BOOL APIENTRY
817ResourceIsStagingBusy(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
841void APIENTRY
842ResourceReadAfterWriteHazard(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
863void APIENTRY
864ResourceUpdateSubResourceUP(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