mesa/src/gallium/frontends/d3d10umd/Resource.cpp

938 lines
31 KiB
C++

/**************************************************************************
*
* 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 );
pResource->buffer = templat.target == PIPE_BUFFER;
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) {
if (pResource->buffer) {
assert(pResource->NumSubResources == 1);
const D3D10_DDIARG_SUBRESOURCE_UP* pInitialDataUP =
&pCreateResource->pInitialDataUP[0];
unsigned level;
struct pipe_box box;
subResourceBox(pResource->resource, 0, &level, &box);
struct pipe_transfer *transfer;
void *map;
map = pipe->buffer_map(pipe,
pResource->resource,
level,
PIPE_MAP_WRITE |
PIPE_MAP_UNSYNCHRONIZED,
&box,
&transfer);
assert(map);
if (map) {
memcpy(map, pInitialDataUP->pSysMem, box.width);
pipe_buffer_unmap(pipe, transfer);
}
} else {
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->texture_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_texture_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]) {
if (pResource->buffer) {
pipe_buffer_unmap(pipe, pResource->transfers[SubResource]);
} else {
pipe_texture_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;
if (pResource->buffer) {
map = pipe->buffer_map(pipe,
resource,
level,
usage,
&box,
&pResource->transfers[SubResource]);
} else {
map = pipe->texture_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]) {
if (pResource->buffer) {
pipe_buffer_unmap(pipe, pResource->transfers[SubResource]);
} else {
pipe_texture_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;
Resource *pDstResource = CastResource(hDstResource);
struct pipe_resource *dst_resource = pDstResource->resource;
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;
if (pDstResource->buffer) {
map = pipe->buffer_map(pipe,
dst_resource,
level,
PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE,
&box,
&transfer);
} else {
map = pipe->texture_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);
}
if (pDstResource->buffer) {
pipe_buffer_unmap(pipe, transfer);
} else {
pipe_texture_unmap(pipe, transfer);
}
}
}