17ec681f3Smrg/**************************************************************************
27ec681f3Smrg *
37ec681f3Smrg * Copyright 2012-2021 VMware, Inc.
47ec681f3Smrg * All Rights Reserved.
57ec681f3Smrg *
67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77ec681f3Smrg * copy of this software and associated documentation files (the
87ec681f3Smrg * "Software"), to deal in the Software without restriction, including
97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish,
107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to
117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to
127ec681f3Smrg * the following conditions:
137ec681f3Smrg *
147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
157ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
177ec681f3Smrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
187ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
197ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
207ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
217ec681f3Smrg *
227ec681f3Smrg * The above copyright notice and this permission notice (including the
237ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions
247ec681f3Smrg * of the Software.
257ec681f3Smrg *
267ec681f3Smrg **************************************************************************/
277ec681f3Smrg
287ec681f3Smrg/*
297ec681f3Smrg * Resource.cpp --
307ec681f3Smrg *    Functions that manipulate GPU resources.
317ec681f3Smrg */
327ec681f3Smrg
337ec681f3Smrg
347ec681f3Smrg#include "Resource.h"
357ec681f3Smrg#include "Format.h"
367ec681f3Smrg#include "State.h"
377ec681f3Smrg#include "Query.h"
387ec681f3Smrg
397ec681f3Smrg#include "Debug.h"
407ec681f3Smrg
417ec681f3Smrg#include "util/u_math.h"
427ec681f3Smrg#include "util/u_rect.h"
437ec681f3Smrg#include "util/u_surface.h"
447ec681f3Smrg
457ec681f3Smrg
467ec681f3Smrg/*
477ec681f3Smrg * ----------------------------------------------------------------------
487ec681f3Smrg *
497ec681f3Smrg * CalcPrivateResourceSize --
507ec681f3Smrg *
517ec681f3Smrg *    The CalcPrivateResourceSize function determines the size of
527ec681f3Smrg *    the user-mode display driver's private region of memory
537ec681f3Smrg *    (that is, the size of internal driver structures, not the
547ec681f3Smrg *    size of the resource video memory).
557ec681f3Smrg *
567ec681f3Smrg * ----------------------------------------------------------------------
577ec681f3Smrg */
587ec681f3Smrg
597ec681f3SmrgSIZE_T APIENTRY
607ec681f3SmrgCalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice,                                // IN
617ec681f3Smrg                        __in const D3D10DDIARG_CREATERESOURCE *pCreateResource)  // IN
627ec681f3Smrg{
637ec681f3Smrg   LOG_ENTRYPOINT();
647ec681f3Smrg   return sizeof(Resource);
657ec681f3Smrg}
667ec681f3Smrg
677ec681f3Smrg
687ec681f3Smrgstatic unsigned
697ec681f3Smrgtranslate_resource_usage( unsigned usage )
707ec681f3Smrg{
717ec681f3Smrg   unsigned resource_usage = 0;
727ec681f3Smrg
737ec681f3Smrg   switch (usage) {
747ec681f3Smrg   case D3D10_DDI_USAGE_DEFAULT:
757ec681f3Smrg      resource_usage = PIPE_USAGE_DEFAULT;
767ec681f3Smrg      break;
777ec681f3Smrg   case D3D10_DDI_USAGE_IMMUTABLE:
787ec681f3Smrg      resource_usage = PIPE_USAGE_IMMUTABLE;
797ec681f3Smrg      break;
807ec681f3Smrg   case D3D10_DDI_USAGE_DYNAMIC:
817ec681f3Smrg      resource_usage = PIPE_USAGE_DYNAMIC;
827ec681f3Smrg      break;
837ec681f3Smrg   case D3D10_DDI_USAGE_STAGING:
847ec681f3Smrg      resource_usage = PIPE_USAGE_STAGING;
857ec681f3Smrg      break;
867ec681f3Smrg   default:
877ec681f3Smrg      assert(0);
887ec681f3Smrg      break;
897ec681f3Smrg   }
907ec681f3Smrg
917ec681f3Smrg   return resource_usage;
927ec681f3Smrg}
937ec681f3Smrg
947ec681f3Smrg
957ec681f3Smrgstatic unsigned
967ec681f3Smrgtranslate_resource_flags(UINT flags)
977ec681f3Smrg{
987ec681f3Smrg   unsigned bind = 0;
997ec681f3Smrg
1007ec681f3Smrg   if (flags & D3D10_DDI_BIND_VERTEX_BUFFER)
1017ec681f3Smrg      bind |= PIPE_BIND_VERTEX_BUFFER;
1027ec681f3Smrg
1037ec681f3Smrg   if (flags & D3D10_DDI_BIND_INDEX_BUFFER)
1047ec681f3Smrg      bind |= PIPE_BIND_INDEX_BUFFER;
1057ec681f3Smrg
1067ec681f3Smrg   if (flags & D3D10_DDI_BIND_CONSTANT_BUFFER)
1077ec681f3Smrg      bind |= PIPE_BIND_CONSTANT_BUFFER;
1087ec681f3Smrg
1097ec681f3Smrg   if (flags & D3D10_DDI_BIND_SHADER_RESOURCE)
1107ec681f3Smrg      bind |= PIPE_BIND_SAMPLER_VIEW;
1117ec681f3Smrg
1127ec681f3Smrg   if (flags & D3D10_DDI_BIND_RENDER_TARGET)
1137ec681f3Smrg      bind |= PIPE_BIND_RENDER_TARGET;
1147ec681f3Smrg
1157ec681f3Smrg   if (flags & D3D10_DDI_BIND_DEPTH_STENCIL)
1167ec681f3Smrg      bind |= PIPE_BIND_DEPTH_STENCIL;
1177ec681f3Smrg
1187ec681f3Smrg   if (flags & D3D10_DDI_BIND_STREAM_OUTPUT)
1197ec681f3Smrg      bind |= PIPE_BIND_STREAM_OUTPUT;
1207ec681f3Smrg
1217ec681f3Smrg   return bind;
1227ec681f3Smrg}
1237ec681f3Smrg
1247ec681f3Smrg
1257ec681f3Smrgstatic enum pipe_texture_target
1267ec681f3Smrgtranslate_texture_target( D3D10DDIRESOURCE_TYPE ResourceDimension,
1277ec681f3Smrg                             UINT ArraySize)
1287ec681f3Smrg{
1297ec681f3Smrg   assert(ArraySize >= 1);
1307ec681f3Smrg   switch(ResourceDimension) {
1317ec681f3Smrg   case D3D10DDIRESOURCE_BUFFER:
1327ec681f3Smrg      assert(ArraySize == 1);
1337ec681f3Smrg      return PIPE_BUFFER;
1347ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE1D:
1357ec681f3Smrg      return ArraySize > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D;
1367ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE2D:
1377ec681f3Smrg      return ArraySize > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D;
1387ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURE3D:
1397ec681f3Smrg      assert(ArraySize == 1);
1407ec681f3Smrg      return PIPE_TEXTURE_3D;
1417ec681f3Smrg   case D3D10DDIRESOURCE_TEXTURECUBE:
1427ec681f3Smrg      assert(ArraySize % 6 == 0);
1437ec681f3Smrg      return ArraySize > 6 ? PIPE_TEXTURE_CUBE_ARRAY : PIPE_TEXTURE_CUBE;
1447ec681f3Smrg   default:
1457ec681f3Smrg      assert(0);
1467ec681f3Smrg      return PIPE_TEXTURE_1D;
1477ec681f3Smrg   }
1487ec681f3Smrg}
1497ec681f3Smrg
1507ec681f3Smrg
1517ec681f3Smrgstatic void
1527ec681f3SmrgsubResourceBox(struct pipe_resource *resource, // IN
1537ec681f3Smrg                 UINT SubResource,  // IN
1547ec681f3Smrg                 unsigned *pLevel, // OUT
1557ec681f3Smrg                 struct pipe_box *pBox)   // OUT
1567ec681f3Smrg{
1577ec681f3Smrg   UINT MipLevels = resource->last_level + 1;
1587ec681f3Smrg   unsigned layer;
1597ec681f3Smrg   unsigned width;
1607ec681f3Smrg   unsigned height;
1617ec681f3Smrg   unsigned depth;
1627ec681f3Smrg
1637ec681f3Smrg   *pLevel = SubResource % MipLevels;
1647ec681f3Smrg   layer = SubResource / MipLevels;
1657ec681f3Smrg
1667ec681f3Smrg   width  = u_minify(resource->width0,  *pLevel);
1677ec681f3Smrg   height = u_minify(resource->height0, *pLevel);
1687ec681f3Smrg   depth  = u_minify(resource->depth0,  *pLevel);
1697ec681f3Smrg
1707ec681f3Smrg   pBox->x = 0;
1717ec681f3Smrg   pBox->y = 0;
1727ec681f3Smrg   pBox->z = 0 + layer;
1737ec681f3Smrg   pBox->width  = width;
1747ec681f3Smrg   pBox->height = height;
1757ec681f3Smrg   pBox->depth  = depth;
1767ec681f3Smrg}
1777ec681f3Smrg
1787ec681f3Smrg
1797ec681f3Smrg/*
1807ec681f3Smrg * ----------------------------------------------------------------------
1817ec681f3Smrg *
1827ec681f3Smrg * CreateResource --
1837ec681f3Smrg *
1847ec681f3Smrg *    The CreateResource function creates a resource.
1857ec681f3Smrg *
1867ec681f3Smrg * ----------------------------------------------------------------------
1877ec681f3Smrg */
1887ec681f3Smrg
1897ec681f3Smrgvoid APIENTRY
1907ec681f3SmrgCreateResource(D3D10DDI_HDEVICE hDevice,                                // IN
1917ec681f3Smrg               __in const D3D10DDIARG_CREATERESOURCE *pCreateResource,  // IN
1927ec681f3Smrg               D3D10DDI_HRESOURCE hResource,                            // IN
1937ec681f3Smrg               D3D10DDI_HRTRESOURCE hRTResource)                        // IN
1947ec681f3Smrg{
1957ec681f3Smrg   LOG_ENTRYPOINT();
1967ec681f3Smrg
1977ec681f3Smrg   if ((pCreateResource->MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED) ||
1987ec681f3Smrg       (pCreateResource->pPrimaryDesc &&
1997ec681f3Smrg        pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) {
2007ec681f3Smrg
2017ec681f3Smrg      DebugPrintf("%s(%dx%dx%d hResource=%p)\n",
2027ec681f3Smrg	       __FUNCTION__,
2037ec681f3Smrg	       pCreateResource->pMipInfoList[0].TexelWidth,
2047ec681f3Smrg	       pCreateResource->pMipInfoList[0].TexelHeight,
2057ec681f3Smrg	       pCreateResource->pMipInfoList[0].TexelDepth,
2067ec681f3Smrg	       hResource.pDrvPrivate);
2077ec681f3Smrg      DebugPrintf("  ResourceDimension = %u\n",
2087ec681f3Smrg	       pCreateResource->ResourceDimension);
2097ec681f3Smrg      DebugPrintf("  Usage = %u\n",
2107ec681f3Smrg	       pCreateResource->Usage);
2117ec681f3Smrg      DebugPrintf("  BindFlags = 0x%x\n",
2127ec681f3Smrg	       pCreateResource->BindFlags);
2137ec681f3Smrg      DebugPrintf("  MapFlags = 0x%x\n",
2147ec681f3Smrg	       pCreateResource->MapFlags);
2157ec681f3Smrg      DebugPrintf("  MiscFlags = 0x%x\n",
2167ec681f3Smrg	       pCreateResource->MiscFlags);
2177ec681f3Smrg      DebugPrintf("  Format = %s\n",
2187ec681f3Smrg	       FormatToName(pCreateResource->Format));
2197ec681f3Smrg      DebugPrintf("  SampleDesc.Count = %u\n", pCreateResource->SampleDesc.Count);
2207ec681f3Smrg      DebugPrintf("  SampleDesc.Quality = %u\n", pCreateResource->SampleDesc.Quality);
2217ec681f3Smrg      DebugPrintf("  MipLevels = %u\n", pCreateResource->MipLevels);
2227ec681f3Smrg      DebugPrintf("  ArraySize = %u\n", pCreateResource->ArraySize);
2237ec681f3Smrg      DebugPrintf("  pPrimaryDesc = %p\n", pCreateResource->pPrimaryDesc);
2247ec681f3Smrg      if (pCreateResource->pPrimaryDesc) {
2257ec681f3Smrg	 DebugPrintf("    Flags = 0x%x\n",
2267ec681f3Smrg		  pCreateResource->pPrimaryDesc->Flags);
2277ec681f3Smrg	 DebugPrintf("    VidPnSourceId = %u\n", pCreateResource->pPrimaryDesc->VidPnSourceId);
2287ec681f3Smrg	 DebugPrintf("    ModeDesc.Width = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Width);
2297ec681f3Smrg	 DebugPrintf("    ModeDesc.Height = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Height);
2307ec681f3Smrg	 DebugPrintf("    ModeDesc.Format = %u)\n",
2317ec681f3Smrg		  pCreateResource->pPrimaryDesc->ModeDesc.Format);
2327ec681f3Smrg	 DebugPrintf("    ModeDesc.RefreshRate.Numerator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Numerator);
2337ec681f3Smrg	 DebugPrintf("    ModeDesc.RefreshRate.Denominator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Denominator);
2347ec681f3Smrg	 DebugPrintf("    ModeDesc.ScanlineOrdering = %u\n",
2357ec681f3Smrg		  pCreateResource->pPrimaryDesc->ModeDesc.ScanlineOrdering);
2367ec681f3Smrg	 DebugPrintf("    ModeDesc.Rotation = %u\n",
2377ec681f3Smrg		  pCreateResource->pPrimaryDesc->ModeDesc.Rotation);
2387ec681f3Smrg	 DebugPrintf("    ModeDesc.Scaling = %u\n",
2397ec681f3Smrg		  pCreateResource->pPrimaryDesc->ModeDesc.Scaling);
2407ec681f3Smrg	 DebugPrintf("    DriverFlags = 0x%x\n",
2417ec681f3Smrg		  pCreateResource->pPrimaryDesc->DriverFlags);
2427ec681f3Smrg      }
2437ec681f3Smrg
2447ec681f3Smrg   }
2457ec681f3Smrg
2467ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
2477ec681f3Smrg   struct pipe_screen *screen = pipe->screen;
2487ec681f3Smrg
2497ec681f3Smrg   Resource *pResource = CastResource(hResource);
2507ec681f3Smrg
2517ec681f3Smrg   memset(pResource, 0, sizeof *pResource);
2527ec681f3Smrg
2537ec681f3Smrg#if 0
2547ec681f3Smrg   if (pCreateResource->pPrimaryDesc) {
2557ec681f3Smrg      pCreateResource->pPrimaryDesc->DriverFlags = DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT;
2567ec681f3Smrg      if (!(pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) {
2577ec681f3Smrg         // http://msdn.microsoft.com/en-us/library/windows/hardware/ff568846.aspx
2587ec681f3Smrg         SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED);
2597ec681f3Smrg         return;
2607ec681f3Smrg      }
2617ec681f3Smrg   }
2627ec681f3Smrg#endif
2637ec681f3Smrg
2647ec681f3Smrg   pResource->Format = pCreateResource->Format;
2657ec681f3Smrg   pResource->MipLevels = pCreateResource->MipLevels;
2667ec681f3Smrg
2677ec681f3Smrg   struct pipe_resource templat;
2687ec681f3Smrg
2697ec681f3Smrg   memset(&templat, 0, sizeof templat);
2707ec681f3Smrg
2717ec681f3Smrg   templat.target     = translate_texture_target( pCreateResource->ResourceDimension,
2727ec681f3Smrg                                                  pCreateResource->ArraySize );
2737ec681f3Smrg
2747ec681f3Smrg   if (pCreateResource->Format == DXGI_FORMAT_UNKNOWN) {
2757ec681f3Smrg      assert(pCreateResource->ResourceDimension == D3D10DDIRESOURCE_BUFFER);
2767ec681f3Smrg      templat.format = PIPE_FORMAT_R8_UINT;
2777ec681f3Smrg   } else {
2787ec681f3Smrg      BOOL bindDepthStencil = !!(pCreateResource->BindFlags & D3D10_DDI_BIND_DEPTH_STENCIL);
2797ec681f3Smrg      templat.format = FormatTranslate(pCreateResource->Format, bindDepthStencil);
2807ec681f3Smrg   }
2817ec681f3Smrg
2827ec681f3Smrg   templat.width0     = pCreateResource->pMipInfoList[0].TexelWidth;
2837ec681f3Smrg   templat.height0    = pCreateResource->pMipInfoList[0].TexelHeight;
2847ec681f3Smrg   templat.depth0     = pCreateResource->pMipInfoList[0].TexelDepth;
2857ec681f3Smrg   templat.array_size = pCreateResource->ArraySize;
2867ec681f3Smrg   templat.last_level = pCreateResource->MipLevels - 1;
2877ec681f3Smrg   templat.nr_samples = pCreateResource->SampleDesc.Count;
2887ec681f3Smrg   templat.nr_storage_samples = pCreateResource->SampleDesc.Count;
2897ec681f3Smrg   templat.bind       = translate_resource_flags(pCreateResource->BindFlags);
2907ec681f3Smrg   templat.usage      = translate_resource_usage(pCreateResource->Usage);
2917ec681f3Smrg
2927ec681f3Smrg   if (templat.target != PIPE_BUFFER) {
2937ec681f3Smrg      if (!screen->is_format_supported(screen,
2947ec681f3Smrg                                       templat.format,
2957ec681f3Smrg                                       templat.target,
2967ec681f3Smrg                                       templat.nr_samples,
2977ec681f3Smrg                                       templat.nr_storage_samples,
2987ec681f3Smrg                                       templat.bind)) {
2997ec681f3Smrg         debug_printf("%s: unsupported format %s\n",
3007ec681f3Smrg                     __FUNCTION__, util_format_name(templat.format));
3017ec681f3Smrg         SetError(hDevice, E_OUTOFMEMORY);
3027ec681f3Smrg         return;
3037ec681f3Smrg      }
3047ec681f3Smrg   }
3057ec681f3Smrg
3067ec681f3Smrg   pResource->resource = screen->resource_create(screen, &templat);
3077ec681f3Smrg   if (!pResource) {
3087ec681f3Smrg      DebugPrintf("%s: failed to create resource\n", __FUNCTION__);
3097ec681f3Smrg      SetError(hDevice, E_OUTOFMEMORY);
3107ec681f3Smrg      return;
3117ec681f3Smrg   }
3127ec681f3Smrg
3137ec681f3Smrg   pResource->NumSubResources = pCreateResource->MipLevels * pCreateResource->ArraySize;
3147ec681f3Smrg   pResource->transfers = (struct pipe_transfer **)calloc(pResource->NumSubResources,
3157ec681f3Smrg                                                          sizeof *pResource->transfers);
3167ec681f3Smrg
3177ec681f3Smrg   if (pCreateResource->pInitialDataUP) {
3187ec681f3Smrg      for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
3197ec681f3Smrg         const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP =
3207ec681f3Smrg               &pCreateResource->pInitialDataUP[SubResource];
3217ec681f3Smrg
3227ec681f3Smrg         unsigned level;
3237ec681f3Smrg         struct pipe_box box;
3247ec681f3Smrg         subResourceBox(pResource->resource, SubResource, &level, &box);
3257ec681f3Smrg
3267ec681f3Smrg         struct pipe_transfer *transfer;
3277ec681f3Smrg         void *map;
3287ec681f3Smrg         map = pipe->transfer_map(pipe,
3297ec681f3Smrg                                  pResource->resource,
3307ec681f3Smrg                                  level,
3317ec681f3Smrg                                  PIPE_MAP_WRITE |
3327ec681f3Smrg                                  PIPE_MAP_UNSYNCHRONIZED,
3337ec681f3Smrg                                  &box,
3347ec681f3Smrg                                  &transfer);
3357ec681f3Smrg         assert(map);
3367ec681f3Smrg         if (map) {
3377ec681f3Smrg            for (int z = 0; z < box.depth; ++z) {
3387ec681f3Smrg               ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
3397ec681f3Smrg               const ubyte *src = (const ubyte*)pInitialDataUP->pSysMem + z*pInitialDataUP->SysMemSlicePitch;
3407ec681f3Smrg               util_copy_rect(dst,
3417ec681f3Smrg                              templat.format,
3427ec681f3Smrg                              transfer->stride,
3437ec681f3Smrg                              0, 0, box.width, box.height,
3447ec681f3Smrg                              src,
3457ec681f3Smrg                              pInitialDataUP->SysMemPitch,
3467ec681f3Smrg                              0, 0);
3477ec681f3Smrg            }
3487ec681f3Smrg            pipe_transfer_unmap(pipe, transfer);
3497ec681f3Smrg         }
3507ec681f3Smrg      }
3517ec681f3Smrg   }
3527ec681f3Smrg}
3537ec681f3Smrg
3547ec681f3Smrg
3557ec681f3Smrg/*
3567ec681f3Smrg * ----------------------------------------------------------------------
3577ec681f3Smrg *
3587ec681f3Smrg * CalcPrivateOpenedResourceSize --
3597ec681f3Smrg *
3607ec681f3Smrg *    The CalcPrivateOpenedResourceSize function determines the size
3617ec681f3Smrg *    of the user-mode display driver's private shared region of memory
3627ec681f3Smrg *    (that is, the size of internal driver structures, not the size
3637ec681f3Smrg *    of the resource video memory) for an opened resource.
3647ec681f3Smrg *
3657ec681f3Smrg * ----------------------------------------------------------------------
3667ec681f3Smrg */
3677ec681f3Smrg
3687ec681f3SmrgSIZE_T APIENTRY
3697ec681f3SmrgCalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice,                             // IN
3707ec681f3Smrg                              __in const D3D10DDIARG_OPENRESOURCE *pOpenResource)   // IN
3717ec681f3Smrg{
3727ec681f3Smrg   return sizeof(Resource);
3737ec681f3Smrg}
3747ec681f3Smrg
3757ec681f3Smrg
3767ec681f3Smrg/*
3777ec681f3Smrg * ----------------------------------------------------------------------
3787ec681f3Smrg *
3797ec681f3Smrg * OpenResource --
3807ec681f3Smrg *
3817ec681f3Smrg *    The OpenResource function opens a shared resource.
3827ec681f3Smrg *
3837ec681f3Smrg * ----------------------------------------------------------------------
3847ec681f3Smrg */
3857ec681f3Smrg
3867ec681f3Smrgvoid APIENTRY
3877ec681f3SmrgOpenResource(D3D10DDI_HDEVICE hDevice,                            // IN
3887ec681f3Smrg             __in const D3D10DDIARG_OPENRESOURCE *pOpenResource,  // IN
3897ec681f3Smrg             D3D10DDI_HRESOURCE hResource,                        // IN
3907ec681f3Smrg             D3D10DDI_HRTRESOURCE hRTResource)                    // IN
3917ec681f3Smrg{
3927ec681f3Smrg   LOG_UNSUPPORTED_ENTRYPOINT();
3937ec681f3Smrg   SetError(hDevice, E_OUTOFMEMORY);
3947ec681f3Smrg}
3957ec681f3Smrg
3967ec681f3Smrg
3977ec681f3Smrg/*
3987ec681f3Smrg * ----------------------------------------------------------------------
3997ec681f3Smrg *
4007ec681f3Smrg * DestroyResource --
4017ec681f3Smrg *
4027ec681f3Smrg *    The DestroyResource function destroys the specified resource
4037ec681f3Smrg *    object. The resource object can be destoyed only if it is not
4047ec681f3Smrg *    currently bound to a display device, and if all views that
4057ec681f3Smrg *    refer to the resource are also destroyed.
4067ec681f3Smrg *
4077ec681f3Smrg * ----------------------------------------------------------------------
4087ec681f3Smrg */
4097ec681f3Smrg
4107ec681f3Smrg
4117ec681f3Smrgvoid APIENTRY
4127ec681f3SmrgDestroyResource(D3D10DDI_HDEVICE hDevice,       // IN
4137ec681f3Smrg                D3D10DDI_HRESOURCE hResource)   // IN
4147ec681f3Smrg{
4157ec681f3Smrg   LOG_ENTRYPOINT();
4167ec681f3Smrg
4177ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
4187ec681f3Smrg   Resource *pResource = CastResource(hResource);
4197ec681f3Smrg
4207ec681f3Smrg   if (pResource->so_target) {
4217ec681f3Smrg      pipe_so_target_reference(&pResource->so_target, NULL);
4227ec681f3Smrg   }
4237ec681f3Smrg
4247ec681f3Smrg   for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) {
4257ec681f3Smrg      if (pResource->transfers[SubResource]) {
4267ec681f3Smrg         pipe_transfer_unmap(pipe, pResource->transfers[SubResource]);
4277ec681f3Smrg         pResource->transfers[SubResource] = NULL;
4287ec681f3Smrg      }
4297ec681f3Smrg   }
4307ec681f3Smrg   free(pResource->transfers);
4317ec681f3Smrg
4327ec681f3Smrg   pipe_resource_reference(&pResource->resource, NULL);
4337ec681f3Smrg}
4347ec681f3Smrg
4357ec681f3Smrg
4367ec681f3Smrg/*
4377ec681f3Smrg * ----------------------------------------------------------------------
4387ec681f3Smrg *
4397ec681f3Smrg * ResourceMap --
4407ec681f3Smrg *
4417ec681f3Smrg *    The ResourceMap function maps a subresource of a resource.
4427ec681f3Smrg *
4437ec681f3Smrg * ----------------------------------------------------------------------
4447ec681f3Smrg */
4457ec681f3Smrg
4467ec681f3Smrgvoid APIENTRY
4477ec681f3SmrgResourceMap(D3D10DDI_HDEVICE hDevice,                                // IN
4487ec681f3Smrg            D3D10DDI_HRESOURCE hResource,                            // IN
4497ec681f3Smrg            UINT SubResource,                                        // IN
4507ec681f3Smrg            D3D10_DDI_MAP DDIMap,                                    // IN
4517ec681f3Smrg            UINT Flags,                                              // IN
4527ec681f3Smrg            __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource)   // OUT
4537ec681f3Smrg{
4547ec681f3Smrg   LOG_ENTRYPOINT();
4557ec681f3Smrg
4567ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
4577ec681f3Smrg   Resource *pResource = CastResource(hResource);
4587ec681f3Smrg   struct pipe_resource *resource = pResource->resource;
4597ec681f3Smrg
4607ec681f3Smrg   unsigned usage;
4617ec681f3Smrg   switch (DDIMap) {
4627ec681f3Smrg   case D3D10_DDI_MAP_READ:
4637ec681f3Smrg      usage = PIPE_MAP_READ;
4647ec681f3Smrg      break;
4657ec681f3Smrg   case D3D10_DDI_MAP_READWRITE:
4667ec681f3Smrg      usage = PIPE_MAP_READ | PIPE_MAP_WRITE;
4677ec681f3Smrg      break;
4687ec681f3Smrg   case D3D10_DDI_MAP_WRITE:
4697ec681f3Smrg      usage = PIPE_MAP_WRITE;
4707ec681f3Smrg      break;
4717ec681f3Smrg   case D3D10_DDI_MAP_WRITE_DISCARD:
4727ec681f3Smrg      usage = PIPE_MAP_WRITE;
4737ec681f3Smrg      if (resource->last_level == 0 && resource->array_size == 1) {
4747ec681f3Smrg         usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE;
4757ec681f3Smrg      } else {
4767ec681f3Smrg         usage |= PIPE_MAP_DISCARD_RANGE;
4777ec681f3Smrg      }
4787ec681f3Smrg      break;
4797ec681f3Smrg   case D3D10_DDI_MAP_WRITE_NOOVERWRITE:
4807ec681f3Smrg      usage = PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED;
4817ec681f3Smrg      break;
4827ec681f3Smrg   default:
4837ec681f3Smrg      assert(0);
4847ec681f3Smrg      return;
4857ec681f3Smrg   }
4867ec681f3Smrg
4877ec681f3Smrg   assert(SubResource < pResource->NumSubResources);
4887ec681f3Smrg
4897ec681f3Smrg   unsigned level;
4907ec681f3Smrg   struct pipe_box box;
4917ec681f3Smrg   subResourceBox(resource, SubResource, &level, &box);
4927ec681f3Smrg
4937ec681f3Smrg   assert(!pResource->transfers[SubResource]);
4947ec681f3Smrg
4957ec681f3Smrg   void *map;
4967ec681f3Smrg   map = pipe->transfer_map(pipe,
4977ec681f3Smrg                            resource,
4987ec681f3Smrg                            level,
4997ec681f3Smrg                            usage,
5007ec681f3Smrg                            &box,
5017ec681f3Smrg                            &pResource->transfers[SubResource]);
5027ec681f3Smrg   if (!map) {
5037ec681f3Smrg      DebugPrintf("%s: failed to map resource\n", __FUNCTION__);
5047ec681f3Smrg      SetError(hDevice, E_FAIL);
5057ec681f3Smrg      return;
5067ec681f3Smrg   }
5077ec681f3Smrg
5087ec681f3Smrg   pMappedSubResource->pData = map;
5097ec681f3Smrg   pMappedSubResource->RowPitch = pResource->transfers[SubResource]->stride;
5107ec681f3Smrg   pMappedSubResource->DepthPitch = pResource->transfers[SubResource]->layer_stride;
5117ec681f3Smrg}
5127ec681f3Smrg
5137ec681f3Smrg
5147ec681f3Smrg/*
5157ec681f3Smrg * ----------------------------------------------------------------------
5167ec681f3Smrg *
5177ec681f3Smrg * ResourceUnmap --
5187ec681f3Smrg *
5197ec681f3Smrg *    The ResourceUnmap function unmaps a subresource of a resource.
5207ec681f3Smrg *
5217ec681f3Smrg * ----------------------------------------------------------------------
5227ec681f3Smrg */
5237ec681f3Smrg
5247ec681f3Smrgvoid APIENTRY
5257ec681f3SmrgResourceUnmap(D3D10DDI_HDEVICE hDevice,      // IN
5267ec681f3Smrg              D3D10DDI_HRESOURCE hResource,  // IN
5277ec681f3Smrg              UINT SubResource)              // IN
5287ec681f3Smrg{
5297ec681f3Smrg   LOG_ENTRYPOINT();
5307ec681f3Smrg
5317ec681f3Smrg   struct pipe_context *pipe = CastPipeContext(hDevice);
5327ec681f3Smrg   Resource *pResource = CastResource(hResource);
5337ec681f3Smrg
5347ec681f3Smrg   assert(SubResource < pResource->NumSubResources);
5357ec681f3Smrg
5367ec681f3Smrg   if (pResource->transfers[SubResource]) {
5377ec681f3Smrg      pipe_transfer_unmap(pipe, pResource->transfers[SubResource]);
5387ec681f3Smrg      pResource->transfers[SubResource] = NULL;
5397ec681f3Smrg   }
5407ec681f3Smrg}
5417ec681f3Smrg
5427ec681f3Smrg
5437ec681f3Smrg/*
5447ec681f3Smrg *----------------------------------------------------------------------
5457ec681f3Smrg *
5467ec681f3Smrg * areResourcesCompatible --
5477ec681f3Smrg *
5487ec681f3Smrg *      Check whether two resources can be safely passed to
5497ec681f3Smrg *      pipe_context::resource_copy_region method.
5507ec681f3Smrg *
5517ec681f3Smrg * Results:
5527ec681f3Smrg *      As above.
5537ec681f3Smrg *
5547ec681f3Smrg * Side effects:
5557ec681f3Smrg *      None.
5567ec681f3Smrg *
5577ec681f3Smrg *----------------------------------------------------------------------
5587ec681f3Smrg */
5597ec681f3Smrg
5607ec681f3Smrgstatic bool
5617ec681f3SmrgareResourcesCompatible(const struct pipe_resource *src_resource, // IN
5627ec681f3Smrg                       const struct pipe_resource *dst_resource) // IN
5637ec681f3Smrg{
5647ec681f3Smrg   if (src_resource->format == dst_resource->format) {
5657ec681f3Smrg      /*
5667ec681f3Smrg       * Trivial.
5677ec681f3Smrg       */
5687ec681f3Smrg
5697ec681f3Smrg      return TRUE;
5707ec681f3Smrg   } else if (src_resource->target == PIPE_BUFFER &&
5717ec681f3Smrg              dst_resource->target == PIPE_BUFFER) {
5727ec681f3Smrg      /*
5737ec681f3Smrg       * Buffer resources are merely a collection of bytes.
5747ec681f3Smrg       */
5757ec681f3Smrg
5767ec681f3Smrg      return TRUE;
5777ec681f3Smrg   } else {
5787ec681f3Smrg      /*
5797ec681f3Smrg       * Check whether the formats are supported by
5807ec681f3Smrg       * the resource_copy_region method.
5817ec681f3Smrg       */
5827ec681f3Smrg
5837ec681f3Smrg      const struct util_format_description *src_format_desc;
5847ec681f3Smrg      const struct util_format_description *dst_format_desc;
5857ec681f3Smrg
5867ec681f3Smrg      src_format_desc = util_format_description(src_resource->format);
5877ec681f3Smrg      dst_format_desc = util_format_description(dst_resource->format);
5887ec681f3Smrg
5897ec681f3Smrg      assert(src_format_desc->block.width  == dst_format_desc->block.width);
5907ec681f3Smrg      assert(src_format_desc->block.height == dst_format_desc->block.height);
5917ec681f3Smrg      assert(src_format_desc->block.bits   == dst_format_desc->block.bits);
5927ec681f3Smrg
5937ec681f3Smrg      return util_is_format_compatible(src_format_desc, dst_format_desc);
5947ec681f3Smrg   }
5957ec681f3Smrg}
5967ec681f3Smrg
5977ec681f3Smrg
5987ec681f3Smrg/*
5997ec681f3Smrg * ----------------------------------------------------------------------
6007ec681f3Smrg *
6017ec681f3Smrg * ResourceCopy --
6027ec681f3Smrg *
6037ec681f3Smrg *    The ResourceCopy function copies an entire source
6047ec681f3Smrg *    resource to a destination resource.
6057ec681f3Smrg *
6067ec681f3Smrg * ----------------------------------------------------------------------
6077ec681f3Smrg */
6087ec681f3Smrg
6097ec681f3Smrgvoid APIENTRY
6107ec681f3SmrgResourceCopy(D3D10DDI_HDEVICE hDevice,          // IN
6117ec681f3Smrg             D3D10DDI_HRESOURCE hDstResource,   // IN
6127ec681f3Smrg             D3D10DDI_HRESOURCE hSrcResource)   // IN
6137ec681f3Smrg{
6147ec681f3Smrg   LOG_ENTRYPOINT();
6157ec681f3Smrg
6167ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
6177ec681f3Smrg   if (!CheckPredicate(pDevice)) {
6187ec681f3Smrg      return;
6197ec681f3Smrg   }
6207ec681f3Smrg
6217ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
6227ec681f3Smrg   Resource *pDstResource = CastResource(hDstResource);
6237ec681f3Smrg   Resource *pSrcResource = CastResource(hSrcResource);
6247ec681f3Smrg   struct pipe_resource *dst_resource = pDstResource->resource;
6257ec681f3Smrg   struct pipe_resource *src_resource = pSrcResource->resource;
6267ec681f3Smrg   bool compatible;
6277ec681f3Smrg
6287ec681f3Smrg   assert(dst_resource->target == src_resource->target);
6297ec681f3Smrg   assert(dst_resource->width0 == src_resource->width0);
6307ec681f3Smrg   assert(dst_resource->height0 == src_resource->height0);
6317ec681f3Smrg   assert(dst_resource->depth0 == src_resource->depth0);
6327ec681f3Smrg   assert(dst_resource->last_level == src_resource->last_level);
6337ec681f3Smrg   assert(dst_resource->array_size == src_resource->array_size);
6347ec681f3Smrg
6357ec681f3Smrg   compatible = areResourcesCompatible(src_resource, dst_resource);
6367ec681f3Smrg
6377ec681f3Smrg   /* could also use one 3d copy for arrays */
6387ec681f3Smrg   for (unsigned layer = 0; layer < dst_resource->array_size; ++layer) {
6397ec681f3Smrg      for (unsigned level = 0; level <= dst_resource->last_level; ++level) {
6407ec681f3Smrg         struct pipe_box box;
6417ec681f3Smrg         box.x = 0;
6427ec681f3Smrg         box.y = 0;
6437ec681f3Smrg         box.z = 0 + layer;
6447ec681f3Smrg         box.width  = u_minify(dst_resource->width0,  level);
6457ec681f3Smrg         box.height = u_minify(dst_resource->height0, level);
6467ec681f3Smrg         box.depth  = u_minify(dst_resource->depth0,  level);
6477ec681f3Smrg
6487ec681f3Smrg	 if (compatible) {
6497ec681f3Smrg            pipe->resource_copy_region(pipe,
6507ec681f3Smrg                                       dst_resource, level,
6517ec681f3Smrg                                       0, 0, layer,
6527ec681f3Smrg                                       src_resource, level,
6537ec681f3Smrg                                       &box);
6547ec681f3Smrg         } else {
6557ec681f3Smrg            util_resource_copy_region(pipe,
6567ec681f3Smrg                                      dst_resource, level,
6577ec681f3Smrg                                      0, 0, layer,
6587ec681f3Smrg                                      src_resource, level,
6597ec681f3Smrg                                      &box);
6607ec681f3Smrg         }
6617ec681f3Smrg      }
6627ec681f3Smrg   }
6637ec681f3Smrg}
6647ec681f3Smrg
6657ec681f3Smrg
6667ec681f3Smrg/*
6677ec681f3Smrg * ----------------------------------------------------------------------
6687ec681f3Smrg *
6697ec681f3Smrg * ResourceCopyRegion --
6707ec681f3Smrg *
6717ec681f3Smrg *    The ResourceCopyRegion function copies a source subresource
6727ec681f3Smrg *    region to a location on a destination subresource.
6737ec681f3Smrg *
6747ec681f3Smrg * ----------------------------------------------------------------------
6757ec681f3Smrg */
6767ec681f3Smrg
6777ec681f3Smrgvoid APIENTRY
6787ec681f3SmrgResourceCopyRegion(D3D10DDI_HDEVICE hDevice,                // IN
6797ec681f3Smrg                   D3D10DDI_HRESOURCE hDstResource,         // IN
6807ec681f3Smrg                   UINT DstSubResource,                     // IN
6817ec681f3Smrg                   UINT DstX,                               // IN
6827ec681f3Smrg                   UINT DstY,                               // IN
6837ec681f3Smrg                   UINT DstZ,                               // IN
6847ec681f3Smrg                   D3D10DDI_HRESOURCE hSrcResource,         // IN
6857ec681f3Smrg                   UINT SrcSubResource,                     // IN
6867ec681f3Smrg                   __in_opt const D3D10_DDI_BOX *pSrcBox)   // IN (optional)
6877ec681f3Smrg{
6887ec681f3Smrg   LOG_ENTRYPOINT();
6897ec681f3Smrg
6907ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
6917ec681f3Smrg   if (!CheckPredicate(pDevice)) {
6927ec681f3Smrg      return;
6937ec681f3Smrg   }
6947ec681f3Smrg
6957ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
6967ec681f3Smrg   Resource *pDstResource = CastResource(hDstResource);
6977ec681f3Smrg   Resource *pSrcResource = CastResource(hSrcResource);
6987ec681f3Smrg   struct pipe_resource *dst_resource = pDstResource->resource;
6997ec681f3Smrg   struct pipe_resource *src_resource = pSrcResource->resource;
7007ec681f3Smrg
7017ec681f3Smrg   unsigned dst_level = DstSubResource % (dst_resource->last_level + 1);
7027ec681f3Smrg   unsigned dst_layer = DstSubResource / (dst_resource->last_level + 1);
7037ec681f3Smrg   unsigned src_level = SrcSubResource % (src_resource->last_level + 1);
7047ec681f3Smrg   unsigned src_layer = SrcSubResource / (src_resource->last_level + 1);
7057ec681f3Smrg
7067ec681f3Smrg   struct pipe_box src_box;
7077ec681f3Smrg   if (pSrcBox) {
7087ec681f3Smrg      src_box.x = pSrcBox->left;
7097ec681f3Smrg      src_box.y = pSrcBox->top;
7107ec681f3Smrg      src_box.z = pSrcBox->front + src_layer;
7117ec681f3Smrg      src_box.width  = pSrcBox->right  - pSrcBox->left;
7127ec681f3Smrg      src_box.height = pSrcBox->bottom - pSrcBox->top;
7137ec681f3Smrg      src_box.depth  = pSrcBox->back   - pSrcBox->front;
7147ec681f3Smrg   } else {
7157ec681f3Smrg      src_box.x = 0;
7167ec681f3Smrg      src_box.y = 0;
7177ec681f3Smrg      src_box.z = 0 + src_layer;
7187ec681f3Smrg      src_box.width  = u_minify(src_resource->width0,  src_level);
7197ec681f3Smrg      src_box.height = u_minify(src_resource->height0, src_level);
7207ec681f3Smrg      src_box.depth  = u_minify(src_resource->depth0,  src_level);
7217ec681f3Smrg   }
7227ec681f3Smrg
7237ec681f3Smrg   if (areResourcesCompatible(src_resource, dst_resource)) {
7247ec681f3Smrg      pipe->resource_copy_region(pipe,
7257ec681f3Smrg                                 dst_resource, dst_level,
7267ec681f3Smrg                                 DstX, DstY, DstZ + dst_layer,
7277ec681f3Smrg                                 src_resource, src_level,
7287ec681f3Smrg                                 &src_box);
7297ec681f3Smrg   } else {
7307ec681f3Smrg      util_resource_copy_region(pipe,
7317ec681f3Smrg                                dst_resource, dst_level,
7327ec681f3Smrg                                DstX, DstY, DstZ + dst_layer,
7337ec681f3Smrg                                src_resource, src_level,
7347ec681f3Smrg                                &src_box);
7357ec681f3Smrg   }
7367ec681f3Smrg}
7377ec681f3Smrg
7387ec681f3Smrg
7397ec681f3Smrg/*
7407ec681f3Smrg * ----------------------------------------------------------------------
7417ec681f3Smrg *
7427ec681f3Smrg * ResourceResolveSubResource --
7437ec681f3Smrg *
7447ec681f3Smrg *    The ResourceResolveSubResource function resolves
7457ec681f3Smrg *    multiple samples to one pixel.
7467ec681f3Smrg *
7477ec681f3Smrg * ----------------------------------------------------------------------
7487ec681f3Smrg */
7497ec681f3Smrg
7507ec681f3Smrgvoid APIENTRY
7517ec681f3SmrgResourceResolveSubResource(D3D10DDI_HDEVICE hDevice,        // IN
7527ec681f3Smrg                           D3D10DDI_HRESOURCE hDstResource, // IN
7537ec681f3Smrg                           UINT DstSubResource,             // IN
7547ec681f3Smrg                           D3D10DDI_HRESOURCE hSrcResource, // IN
7557ec681f3Smrg                           UINT SrcSubResource,             // IN
7567ec681f3Smrg                           DXGI_FORMAT ResolveFormat)       // IN
7577ec681f3Smrg{
7587ec681f3Smrg   LOG_UNSUPPORTED_ENTRYPOINT();
7597ec681f3Smrg}
7607ec681f3Smrg
7617ec681f3Smrg
7627ec681f3Smrg/*
7637ec681f3Smrg * ----------------------------------------------------------------------
7647ec681f3Smrg *
7657ec681f3Smrg * ResourceIsStagingBusy --
7667ec681f3Smrg *
7677ec681f3Smrg *    The ResourceIsStagingBusy function determines whether a
7687ec681f3Smrg *    resource is currently being used by the graphics pipeline.
7697ec681f3Smrg *
7707ec681f3Smrg * ----------------------------------------------------------------------
7717ec681f3Smrg */
7727ec681f3Smrg
7737ec681f3SmrgBOOL APIENTRY
7747ec681f3SmrgResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice,       // IN
7757ec681f3Smrg                      D3D10DDI_HRESOURCE hResource)   // IN
7767ec681f3Smrg{
7777ec681f3Smrg   LOG_ENTRYPOINT();
7787ec681f3Smrg
7797ec681f3Smrg   /* ignore */
7807ec681f3Smrg
7817ec681f3Smrg   return FALSE;
7827ec681f3Smrg}
7837ec681f3Smrg
7847ec681f3Smrg
7857ec681f3Smrg/*
7867ec681f3Smrg * ----------------------------------------------------------------------
7877ec681f3Smrg *
7887ec681f3Smrg * ResourceReadAfterWriteHazard --
7897ec681f3Smrg *
7907ec681f3Smrg *    The ResourceReadAfterWriteHazard function informs the user-mode
7917ec681f3Smrg *    display driver that the specified resource was used as an output
7927ec681f3Smrg *    from the graphics processing unit (GPU) and that the resource
7937ec681f3Smrg *    will be used as an input to the GPU.
7947ec681f3Smrg *
7957ec681f3Smrg * ----------------------------------------------------------------------
7967ec681f3Smrg */
7977ec681f3Smrg
7987ec681f3Smrgvoid APIENTRY
7997ec681f3SmrgResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice,      // IN
8007ec681f3Smrg                             D3D10DDI_HRESOURCE hResource)  // IN
8017ec681f3Smrg{
8027ec681f3Smrg   LOG_ENTRYPOINT();
8037ec681f3Smrg
8047ec681f3Smrg   /* Not actually necessary */
8057ec681f3Smrg}
8067ec681f3Smrg
8077ec681f3Smrg
8087ec681f3Smrg/*
8097ec681f3Smrg * ----------------------------------------------------------------------
8107ec681f3Smrg *
8117ec681f3Smrg * ResourceUpdateSubResourceUP --
8127ec681f3Smrg *
8137ec681f3Smrg *    The ResourceUpdateSubresourceUP function updates a
8147ec681f3Smrg *    destination subresource region from a source
8157ec681f3Smrg *    system memory region.
8167ec681f3Smrg *
8177ec681f3Smrg * ----------------------------------------------------------------------
8187ec681f3Smrg */
8197ec681f3Smrg
8207ec681f3Smrgvoid APIENTRY
8217ec681f3SmrgResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice,                // IN
8227ec681f3Smrg                            D3D10DDI_HRESOURCE hDstResource,         // IN
8237ec681f3Smrg                            UINT DstSubResource,                     // IN
8247ec681f3Smrg                            __in_opt const D3D10_DDI_BOX *pDstBox,   // IN
8257ec681f3Smrg                            __in const void *pSysMemUP,              // IN
8267ec681f3Smrg                            UINT RowPitch,                           // IN
8277ec681f3Smrg                            UINT DepthPitch)                         // IN
8287ec681f3Smrg{
8297ec681f3Smrg   LOG_ENTRYPOINT();
8307ec681f3Smrg
8317ec681f3Smrg   Device *pDevice = CastDevice(hDevice);
8327ec681f3Smrg   if (!CheckPredicate(pDevice)) {
8337ec681f3Smrg      return;
8347ec681f3Smrg   }
8357ec681f3Smrg
8367ec681f3Smrg   struct pipe_context *pipe = pDevice->pipe;
8377ec681f3Smrg   struct pipe_resource *dst_resource = CastPipeResource(hDstResource);
8387ec681f3Smrg
8397ec681f3Smrg   unsigned level;
8407ec681f3Smrg   struct pipe_box box;
8417ec681f3Smrg
8427ec681f3Smrg   if (pDstBox) {
8437ec681f3Smrg      UINT DstMipLevels = dst_resource->last_level + 1;
8447ec681f3Smrg      level = DstSubResource % DstMipLevels;
8457ec681f3Smrg      unsigned dst_layer = DstSubResource / DstMipLevels;
8467ec681f3Smrg      box.x = pDstBox->left;
8477ec681f3Smrg      box.y = pDstBox->top;
8487ec681f3Smrg      box.z = pDstBox->front + dst_layer;
8497ec681f3Smrg      box.width  = pDstBox->right  - pDstBox->left;
8507ec681f3Smrg      box.height = pDstBox->bottom - pDstBox->top;
8517ec681f3Smrg      box.depth  = pDstBox->back   - pDstBox->front;
8527ec681f3Smrg   } else {
8537ec681f3Smrg      subResourceBox(dst_resource, DstSubResource, &level, &box);
8547ec681f3Smrg   }
8557ec681f3Smrg
8567ec681f3Smrg   struct pipe_transfer *transfer;
8577ec681f3Smrg   void *map;
8587ec681f3Smrg   map = pipe->transfer_map(pipe,
8597ec681f3Smrg                            dst_resource,
8607ec681f3Smrg                            level,
8617ec681f3Smrg                            PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
8627ec681f3Smrg                            &box,
8637ec681f3Smrg                            &transfer);
8647ec681f3Smrg   assert(map);
8657ec681f3Smrg   if (map) {
8667ec681f3Smrg      for (int z = 0; z < box.depth; ++z) {
8677ec681f3Smrg         ubyte *dst = (ubyte*)map + z*transfer->layer_stride;
8687ec681f3Smrg         const ubyte *src = (const ubyte*)pSysMemUP + z*DepthPitch;
8697ec681f3Smrg         util_copy_rect(dst,
8707ec681f3Smrg                        dst_resource->format,
8717ec681f3Smrg                        transfer->stride,
8727ec681f3Smrg                        0, 0, box.width, box.height,
8737ec681f3Smrg                        src,
8747ec681f3Smrg                        RowPitch,
8757ec681f3Smrg                        0, 0);
8767ec681f3Smrg      }
8777ec681f3Smrg      pipe_transfer_unmap(pipe, transfer);
8787ec681f3Smrg   }
8797ec681f3Smrg}
8807ec681f3Smrg
881