938 lines
31 KiB
C++
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);
|
|
}
|
|
}
|
|
}
|
|
|