/************************************************************************** * * Copyright 2012-2021 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * **************************************************************************/ /* * Resource.cpp -- * Functions that manipulate GPU resources. */ #include "Resource.h" #include "Format.h" #include "State.h" #include "Query.h" #include "Debug.h" #include "util/u_math.h" #include "util/u_rect.h" #include "util/u_surface.h" /* * ---------------------------------------------------------------------- * * CalcPrivateResourceSize -- * * The CalcPrivateResourceSize function determines the size of * the user-mode display driver's private region of memory * (that is, the size of internal driver structures, not the * size of the resource video memory). * * ---------------------------------------------------------------------- */ SIZE_T APIENTRY CalcPrivateResourceSize(D3D10DDI_HDEVICE hDevice, // IN __in const D3D10DDIARG_CREATERESOURCE *pCreateResource) // IN { LOG_ENTRYPOINT(); return sizeof(Resource); } static unsigned translate_resource_usage( unsigned usage ) { unsigned resource_usage = 0; switch (usage) { case D3D10_DDI_USAGE_DEFAULT: resource_usage = PIPE_USAGE_DEFAULT; break; case D3D10_DDI_USAGE_IMMUTABLE: resource_usage = PIPE_USAGE_IMMUTABLE; break; case D3D10_DDI_USAGE_DYNAMIC: resource_usage = PIPE_USAGE_DYNAMIC; break; case D3D10_DDI_USAGE_STAGING: resource_usage = PIPE_USAGE_STAGING; break; default: assert(0); break; } return resource_usage; } static unsigned translate_resource_flags(UINT flags) { unsigned bind = 0; if (flags & D3D10_DDI_BIND_VERTEX_BUFFER) bind |= PIPE_BIND_VERTEX_BUFFER; if (flags & D3D10_DDI_BIND_INDEX_BUFFER) bind |= PIPE_BIND_INDEX_BUFFER; if (flags & D3D10_DDI_BIND_CONSTANT_BUFFER) bind |= PIPE_BIND_CONSTANT_BUFFER; if (flags & D3D10_DDI_BIND_SHADER_RESOURCE) bind |= PIPE_BIND_SAMPLER_VIEW; if (flags & D3D10_DDI_BIND_RENDER_TARGET) bind |= PIPE_BIND_RENDER_TARGET; if (flags & D3D10_DDI_BIND_DEPTH_STENCIL) bind |= PIPE_BIND_DEPTH_STENCIL; if (flags & D3D10_DDI_BIND_STREAM_OUTPUT) bind |= PIPE_BIND_STREAM_OUTPUT; return bind; } static enum pipe_texture_target translate_texture_target( D3D10DDIRESOURCE_TYPE ResourceDimension, UINT ArraySize) { assert(ArraySize >= 1); switch(ResourceDimension) { case D3D10DDIRESOURCE_BUFFER: assert(ArraySize == 1); return PIPE_BUFFER; case D3D10DDIRESOURCE_TEXTURE1D: return ArraySize > 1 ? PIPE_TEXTURE_1D_ARRAY : PIPE_TEXTURE_1D; case D3D10DDIRESOURCE_TEXTURE2D: return ArraySize > 1 ? PIPE_TEXTURE_2D_ARRAY : PIPE_TEXTURE_2D; case D3D10DDIRESOURCE_TEXTURE3D: assert(ArraySize == 1); return PIPE_TEXTURE_3D; case D3D10DDIRESOURCE_TEXTURECUBE: assert(ArraySize % 6 == 0); return ArraySize > 6 ? PIPE_TEXTURE_CUBE_ARRAY : PIPE_TEXTURE_CUBE; default: assert(0); return PIPE_TEXTURE_1D; } } static void subResourceBox(struct pipe_resource *resource, // IN UINT SubResource, // IN unsigned *pLevel, // OUT struct pipe_box *pBox) // OUT { UINT MipLevels = resource->last_level + 1; unsigned layer; unsigned width; unsigned height; unsigned depth; *pLevel = SubResource % MipLevels; layer = SubResource / MipLevels; width = u_minify(resource->width0, *pLevel); height = u_minify(resource->height0, *pLevel); depth = u_minify(resource->depth0, *pLevel); pBox->x = 0; pBox->y = 0; pBox->z = 0 + layer; pBox->width = width; pBox->height = height; pBox->depth = depth; } /* * ---------------------------------------------------------------------- * * CreateResource -- * * The CreateResource function creates a resource. * * ---------------------------------------------------------------------- */ void APIENTRY CreateResource(D3D10DDI_HDEVICE hDevice, // IN __in const D3D10DDIARG_CREATERESOURCE *pCreateResource, // IN D3D10DDI_HRESOURCE hResource, // IN D3D10DDI_HRTRESOURCE hRTResource) // IN { LOG_ENTRYPOINT(); if ((pCreateResource->MiscFlags & D3D10_DDI_RESOURCE_MISC_SHARED) || (pCreateResource->pPrimaryDesc && pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) { DebugPrintf("%s(%dx%dx%d hResource=%p)\n", __FUNCTION__, pCreateResource->pMipInfoList[0].TexelWidth, pCreateResource->pMipInfoList[0].TexelHeight, pCreateResource->pMipInfoList[0].TexelDepth, hResource.pDrvPrivate); DebugPrintf(" ResourceDimension = %u\n", pCreateResource->ResourceDimension); DebugPrintf(" Usage = %u\n", pCreateResource->Usage); DebugPrintf(" BindFlags = 0x%x\n", pCreateResource->BindFlags); DebugPrintf(" MapFlags = 0x%x\n", pCreateResource->MapFlags); DebugPrintf(" MiscFlags = 0x%x\n", pCreateResource->MiscFlags); DebugPrintf(" Format = %s\n", FormatToName(pCreateResource->Format)); DebugPrintf(" SampleDesc.Count = %u\n", pCreateResource->SampleDesc.Count); DebugPrintf(" SampleDesc.Quality = %u\n", pCreateResource->SampleDesc.Quality); DebugPrintf(" MipLevels = %u\n", pCreateResource->MipLevels); DebugPrintf(" ArraySize = %u\n", pCreateResource->ArraySize); DebugPrintf(" pPrimaryDesc = %p\n", pCreateResource->pPrimaryDesc); if (pCreateResource->pPrimaryDesc) { DebugPrintf(" Flags = 0x%x\n", pCreateResource->pPrimaryDesc->Flags); DebugPrintf(" VidPnSourceId = %u\n", pCreateResource->pPrimaryDesc->VidPnSourceId); DebugPrintf(" ModeDesc.Width = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Width); DebugPrintf(" ModeDesc.Height = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Height); DebugPrintf(" ModeDesc.Format = %u)\n", pCreateResource->pPrimaryDesc->ModeDesc.Format); DebugPrintf(" ModeDesc.RefreshRate.Numerator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Numerator); DebugPrintf(" ModeDesc.RefreshRate.Denominator = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.RefreshRate.Denominator); DebugPrintf(" ModeDesc.ScanlineOrdering = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.ScanlineOrdering); DebugPrintf(" ModeDesc.Rotation = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Rotation); DebugPrintf(" ModeDesc.Scaling = %u\n", pCreateResource->pPrimaryDesc->ModeDesc.Scaling); DebugPrintf(" DriverFlags = 0x%x\n", pCreateResource->pPrimaryDesc->DriverFlags); } } struct pipe_context *pipe = CastPipeContext(hDevice); struct pipe_screen *screen = pipe->screen; Resource *pResource = CastResource(hResource); memset(pResource, 0, sizeof *pResource); #if 0 if (pCreateResource->pPrimaryDesc) { pCreateResource->pPrimaryDesc->DriverFlags = DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT; if (!(pCreateResource->pPrimaryDesc->DriverFlags & DXGI_DDI_PRIMARY_OPTIONAL)) { // http://msdn.microsoft.com/en-us/library/windows/hardware/ff568846.aspx SetError(hDevice, DXGI_DDI_ERR_UNSUPPORTED); return; } } #endif pResource->Format = pCreateResource->Format; pResource->MipLevels = pCreateResource->MipLevels; struct pipe_resource templat; memset(&templat, 0, sizeof templat); templat.target = translate_texture_target( pCreateResource->ResourceDimension, pCreateResource->ArraySize ); if (pCreateResource->Format == DXGI_FORMAT_UNKNOWN) { assert(pCreateResource->ResourceDimension == D3D10DDIRESOURCE_BUFFER); templat.format = PIPE_FORMAT_R8_UINT; } else { BOOL bindDepthStencil = !!(pCreateResource->BindFlags & D3D10_DDI_BIND_DEPTH_STENCIL); templat.format = FormatTranslate(pCreateResource->Format, bindDepthStencil); } templat.width0 = pCreateResource->pMipInfoList[0].TexelWidth; templat.height0 = pCreateResource->pMipInfoList[0].TexelHeight; templat.depth0 = pCreateResource->pMipInfoList[0].TexelDepth; templat.array_size = pCreateResource->ArraySize; templat.last_level = pCreateResource->MipLevels - 1; templat.nr_samples = pCreateResource->SampleDesc.Count; templat.nr_storage_samples = pCreateResource->SampleDesc.Count; templat.bind = translate_resource_flags(pCreateResource->BindFlags); templat.usage = translate_resource_usage(pCreateResource->Usage); if (templat.target != PIPE_BUFFER) { if (!screen->is_format_supported(screen, templat.format, templat.target, templat.nr_samples, templat.nr_storage_samples, templat.bind)) { debug_printf("%s: unsupported format %s\n", __FUNCTION__, util_format_name(templat.format)); SetError(hDevice, E_OUTOFMEMORY); return; } } pResource->resource = screen->resource_create(screen, &templat); if (!pResource) { DebugPrintf("%s: failed to create resource\n", __FUNCTION__); SetError(hDevice, E_OUTOFMEMORY); return; } pResource->NumSubResources = pCreateResource->MipLevels * pCreateResource->ArraySize; pResource->transfers = (struct pipe_transfer **)calloc(pResource->NumSubResources, sizeof *pResource->transfers); if (pCreateResource->pInitialDataUP) { for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) { const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP = &pCreateResource->pInitialDataUP[SubResource]; unsigned level; struct pipe_box box; subResourceBox(pResource->resource, SubResource, &level, &box); struct pipe_transfer *transfer; void *map; map = pipe->transfer_map(pipe, pResource->resource, level, PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED, &box, &transfer); assert(map); if (map) { for (int z = 0; z < box.depth; ++z) { ubyte *dst = (ubyte*)map + z*transfer->layer_stride; const ubyte *src = (const ubyte*)pInitialDataUP->pSysMem + z*pInitialDataUP->SysMemSlicePitch; util_copy_rect(dst, templat.format, transfer->stride, 0, 0, box.width, box.height, src, pInitialDataUP->SysMemPitch, 0, 0); } pipe_transfer_unmap(pipe, transfer); } } } } /* * ---------------------------------------------------------------------- * * CalcPrivateOpenedResourceSize -- * * The CalcPrivateOpenedResourceSize function determines the size * of the user-mode display driver's private shared region of memory * (that is, the size of internal driver structures, not the size * of the resource video memory) for an opened resource. * * ---------------------------------------------------------------------- */ SIZE_T APIENTRY CalcPrivateOpenedResourceSize(D3D10DDI_HDEVICE hDevice, // IN __in const D3D10DDIARG_OPENRESOURCE *pOpenResource) // IN { return sizeof(Resource); } /* * ---------------------------------------------------------------------- * * OpenResource -- * * The OpenResource function opens a shared resource. * * ---------------------------------------------------------------------- */ void APIENTRY OpenResource(D3D10DDI_HDEVICE hDevice, // IN __in const D3D10DDIARG_OPENRESOURCE *pOpenResource, // IN D3D10DDI_HRESOURCE hResource, // IN D3D10DDI_HRTRESOURCE hRTResource) // IN { LOG_UNSUPPORTED_ENTRYPOINT(); SetError(hDevice, E_OUTOFMEMORY); } /* * ---------------------------------------------------------------------- * * DestroyResource -- * * The DestroyResource function destroys the specified resource * object. The resource object can be destoyed only if it is not * currently bound to a display device, and if all views that * refer to the resource are also destroyed. * * ---------------------------------------------------------------------- */ void APIENTRY DestroyResource(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hResource) // IN { LOG_ENTRYPOINT(); struct pipe_context *pipe = CastPipeContext(hDevice); Resource *pResource = CastResource(hResource); if (pResource->so_target) { pipe_so_target_reference(&pResource->so_target, NULL); } for (UINT SubResource = 0; SubResource < pResource->NumSubResources; ++SubResource) { if (pResource->transfers[SubResource]) { pipe_transfer_unmap(pipe, pResource->transfers[SubResource]); pResource->transfers[SubResource] = NULL; } } free(pResource->transfers); pipe_resource_reference(&pResource->resource, NULL); } /* * ---------------------------------------------------------------------- * * ResourceMap -- * * The ResourceMap function maps a subresource of a resource. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceMap(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hResource, // IN UINT SubResource, // IN D3D10_DDI_MAP DDIMap, // IN UINT Flags, // IN __out D3D10DDI_MAPPED_SUBRESOURCE *pMappedSubResource) // OUT { LOG_ENTRYPOINT(); struct pipe_context *pipe = CastPipeContext(hDevice); Resource *pResource = CastResource(hResource); struct pipe_resource *resource = pResource->resource; unsigned usage; switch (DDIMap) { case D3D10_DDI_MAP_READ: usage = PIPE_MAP_READ; break; case D3D10_DDI_MAP_READWRITE: usage = PIPE_MAP_READ | PIPE_MAP_WRITE; break; case D3D10_DDI_MAP_WRITE: usage = PIPE_MAP_WRITE; break; case D3D10_DDI_MAP_WRITE_DISCARD: usage = PIPE_MAP_WRITE; if (resource->last_level == 0 && resource->array_size == 1) { usage |= PIPE_MAP_DISCARD_WHOLE_RESOURCE; } else { usage |= PIPE_MAP_DISCARD_RANGE; } break; case D3D10_DDI_MAP_WRITE_NOOVERWRITE: usage = PIPE_MAP_WRITE | PIPE_MAP_UNSYNCHRONIZED; break; default: assert(0); return; } assert(SubResource < pResource->NumSubResources); unsigned level; struct pipe_box box; subResourceBox(resource, SubResource, &level, &box); assert(!pResource->transfers[SubResource]); void *map; map = pipe->transfer_map(pipe, resource, level, usage, &box, &pResource->transfers[SubResource]); if (!map) { DebugPrintf("%s: failed to map resource\n", __FUNCTION__); SetError(hDevice, E_FAIL); return; } pMappedSubResource->pData = map; pMappedSubResource->RowPitch = pResource->transfers[SubResource]->stride; pMappedSubResource->DepthPitch = pResource->transfers[SubResource]->layer_stride; } /* * ---------------------------------------------------------------------- * * ResourceUnmap -- * * The ResourceUnmap function unmaps a subresource of a resource. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceUnmap(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hResource, // IN UINT SubResource) // IN { LOG_ENTRYPOINT(); struct pipe_context *pipe = CastPipeContext(hDevice); Resource *pResource = CastResource(hResource); assert(SubResource < pResource->NumSubResources); if (pResource->transfers[SubResource]) { pipe_transfer_unmap(pipe, pResource->transfers[SubResource]); pResource->transfers[SubResource] = NULL; } } /* *---------------------------------------------------------------------- * * areResourcesCompatible -- * * Check whether two resources can be safely passed to * pipe_context::resource_copy_region method. * * Results: * As above. * * Side effects: * None. * *---------------------------------------------------------------------- */ static bool areResourcesCompatible(const struct pipe_resource *src_resource, // IN const struct pipe_resource *dst_resource) // IN { if (src_resource->format == dst_resource->format) { /* * Trivial. */ return TRUE; } else if (src_resource->target == PIPE_BUFFER && dst_resource->target == PIPE_BUFFER) { /* * Buffer resources are merely a collection of bytes. */ return TRUE; } else { /* * Check whether the formats are supported by * the resource_copy_region method. */ const struct util_format_description *src_format_desc; const struct util_format_description *dst_format_desc; src_format_desc = util_format_description(src_resource->format); dst_format_desc = util_format_description(dst_resource->format); assert(src_format_desc->block.width == dst_format_desc->block.width); assert(src_format_desc->block.height == dst_format_desc->block.height); assert(src_format_desc->block.bits == dst_format_desc->block.bits); return util_is_format_compatible(src_format_desc, dst_format_desc); } } /* * ---------------------------------------------------------------------- * * ResourceCopy -- * * The ResourceCopy function copies an entire source * resource to a destination resource. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceCopy(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hDstResource, // IN D3D10DDI_HRESOURCE hSrcResource) // IN { LOG_ENTRYPOINT(); Device *pDevice = CastDevice(hDevice); if (!CheckPredicate(pDevice)) { return; } struct pipe_context *pipe = pDevice->pipe; Resource *pDstResource = CastResource(hDstResource); Resource *pSrcResource = CastResource(hSrcResource); struct pipe_resource *dst_resource = pDstResource->resource; struct pipe_resource *src_resource = pSrcResource->resource; bool compatible; assert(dst_resource->target == src_resource->target); assert(dst_resource->width0 == src_resource->width0); assert(dst_resource->height0 == src_resource->height0); assert(dst_resource->depth0 == src_resource->depth0); assert(dst_resource->last_level == src_resource->last_level); assert(dst_resource->array_size == src_resource->array_size); compatible = areResourcesCompatible(src_resource, dst_resource); /* could also use one 3d copy for arrays */ for (unsigned layer = 0; layer < dst_resource->array_size; ++layer) { for (unsigned level = 0; level <= dst_resource->last_level; ++level) { struct pipe_box box; box.x = 0; box.y = 0; box.z = 0 + layer; box.width = u_minify(dst_resource->width0, level); box.height = u_minify(dst_resource->height0, level); box.depth = u_minify(dst_resource->depth0, level); if (compatible) { pipe->resource_copy_region(pipe, dst_resource, level, 0, 0, layer, src_resource, level, &box); } else { util_resource_copy_region(pipe, dst_resource, level, 0, 0, layer, src_resource, level, &box); } } } } /* * ---------------------------------------------------------------------- * * ResourceCopyRegion -- * * The ResourceCopyRegion function copies a source subresource * region to a location on a destination subresource. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceCopyRegion(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hDstResource, // IN UINT DstSubResource, // IN UINT DstX, // IN UINT DstY, // IN UINT DstZ, // IN D3D10DDI_HRESOURCE hSrcResource, // IN UINT SrcSubResource, // IN __in_opt const D3D10_DDI_BOX *pSrcBox) // IN (optional) { LOG_ENTRYPOINT(); Device *pDevice = CastDevice(hDevice); if (!CheckPredicate(pDevice)) { return; } struct pipe_context *pipe = pDevice->pipe; Resource *pDstResource = CastResource(hDstResource); Resource *pSrcResource = CastResource(hSrcResource); struct pipe_resource *dst_resource = pDstResource->resource; struct pipe_resource *src_resource = pSrcResource->resource; unsigned dst_level = DstSubResource % (dst_resource->last_level + 1); unsigned dst_layer = DstSubResource / (dst_resource->last_level + 1); unsigned src_level = SrcSubResource % (src_resource->last_level + 1); unsigned src_layer = SrcSubResource / (src_resource->last_level + 1); struct pipe_box src_box; if (pSrcBox) { src_box.x = pSrcBox->left; src_box.y = pSrcBox->top; src_box.z = pSrcBox->front + src_layer; src_box.width = pSrcBox->right - pSrcBox->left; src_box.height = pSrcBox->bottom - pSrcBox->top; src_box.depth = pSrcBox->back - pSrcBox->front; } else { src_box.x = 0; src_box.y = 0; src_box.z = 0 + src_layer; src_box.width = u_minify(src_resource->width0, src_level); src_box.height = u_minify(src_resource->height0, src_level); src_box.depth = u_minify(src_resource->depth0, src_level); } if (areResourcesCompatible(src_resource, dst_resource)) { pipe->resource_copy_region(pipe, dst_resource, dst_level, DstX, DstY, DstZ + dst_layer, src_resource, src_level, &src_box); } else { util_resource_copy_region(pipe, dst_resource, dst_level, DstX, DstY, DstZ + dst_layer, src_resource, src_level, &src_box); } } /* * ---------------------------------------------------------------------- * * ResourceResolveSubResource -- * * The ResourceResolveSubResource function resolves * multiple samples to one pixel. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceResolveSubResource(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hDstResource, // IN UINT DstSubResource, // IN D3D10DDI_HRESOURCE hSrcResource, // IN UINT SrcSubResource, // IN DXGI_FORMAT ResolveFormat) // IN { LOG_UNSUPPORTED_ENTRYPOINT(); } /* * ---------------------------------------------------------------------- * * ResourceIsStagingBusy -- * * The ResourceIsStagingBusy function determines whether a * resource is currently being used by the graphics pipeline. * * ---------------------------------------------------------------------- */ BOOL APIENTRY ResourceIsStagingBusy(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hResource) // IN { LOG_ENTRYPOINT(); /* ignore */ return FALSE; } /* * ---------------------------------------------------------------------- * * ResourceReadAfterWriteHazard -- * * The ResourceReadAfterWriteHazard function informs the user-mode * display driver that the specified resource was used as an output * from the graphics processing unit (GPU) and that the resource * will be used as an input to the GPU. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hResource) // IN { LOG_ENTRYPOINT(); /* Not actually necessary */ } /* * ---------------------------------------------------------------------- * * ResourceUpdateSubResourceUP -- * * The ResourceUpdateSubresourceUP function updates a * destination subresource region from a source * system memory region. * * ---------------------------------------------------------------------- */ void APIENTRY ResourceUpdateSubResourceUP(D3D10DDI_HDEVICE hDevice, // IN D3D10DDI_HRESOURCE hDstResource, // IN UINT DstSubResource, // IN __in_opt const D3D10_DDI_BOX *pDstBox, // IN __in const void *pSysMemUP, // IN UINT RowPitch, // IN UINT DepthPitch) // IN { LOG_ENTRYPOINT(); Device *pDevice = CastDevice(hDevice); if (!CheckPredicate(pDevice)) { return; } struct pipe_context *pipe = pDevice->pipe; struct pipe_resource *dst_resource = CastPipeResource(hDstResource); unsigned level; struct pipe_box box; if (pDstBox) { UINT DstMipLevels = dst_resource->last_level + 1; level = DstSubResource % DstMipLevels; unsigned dst_layer = DstSubResource / DstMipLevels; box.x = pDstBox->left; box.y = pDstBox->top; box.z = pDstBox->front + dst_layer; box.width = pDstBox->right - pDstBox->left; box.height = pDstBox->bottom - pDstBox->top; box.depth = pDstBox->back - pDstBox->front; } else { subResourceBox(dst_resource, DstSubResource, &level, &box); } struct pipe_transfer *transfer; void *map; map = pipe->transfer_map(pipe, dst_resource, level, PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE, &box, &transfer); assert(map); if (map) { for (int z = 0; z < box.depth; ++z) { ubyte *dst = (ubyte*)map + z*transfer->layer_stride; const ubyte *src = (const ubyte*)pSysMemUP + z*DepthPitch; util_copy_rect(dst, dst_resource->format, transfer->stride, 0, 0, box.width, box.height, src, RowPitch, 0, 0); } pipe_transfer_unmap(pipe, transfer); } }