mesa/src/gallium/frontends/d3d10umd/OutputMerger.cpp
Mike Blumenkrantz 561fed955b d3d10umd: stop using pipe_surface::width/height
these were deleted months ago

Fixes: 9d359c6d10 ("gallium: delete pipe_surface::width and pipe_surface::height")

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35236>
2025-06-02 16:49:32 +00:00

998 lines
33 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.
*
**************************************************************************/
/*
* OutputMerger.cpp --
* Functions that manipulate the output merger state.
*/
#include "OutputMerger.h"
#include "State.h"
#include "Debug.h"
#include "Format.h"
#include "util/u_framebuffer.h"
#include "util/format/u_format.h"
/*
* ----------------------------------------------------------------------
*
* CalcPrivateRenderTargetViewSize --
*
* The CalcPrivateRenderTargetViewSize 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) for a render target view.
*
* ----------------------------------------------------------------------
*/
SIZE_T APIENTRY
CalcPrivateRenderTargetViewSize(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView) // IN
{
return sizeof(RenderTargetView);
}
/*
* ----------------------------------------------------------------------
*
* CreateRenderTargetView --
*
* The CreateRenderTargetView function creates a render target view.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
CreateRenderTargetView(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, // IN
D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN
D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
struct pipe_resource *resource = CastPipeResource(pCreateRenderTargetView->hDrvResource);
RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
struct pipe_surface desc;
memset(&desc, 0, sizeof desc);
desc.format = FormatTranslate(pCreateRenderTargetView->Format, false);
switch (pCreateRenderTargetView->ResourceDimension) {
case D3D10DDIRESOURCE_BUFFER:
desc.u.buf.first_element = pCreateRenderTargetView->Buffer.FirstElement;
desc.u.buf.last_element = pCreateRenderTargetView->Buffer.NumElements - 1 +
desc.u.buf.first_element;
break;
case D3D10DDIRESOURCE_TEXTURE1D:
ASSERT(pCreateRenderTargetView->Tex1D.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateRenderTargetView->Tex1D.MipSlice;
desc.u.tex.first_layer = pCreateRenderTargetView->Tex1D.FirstArraySlice;
desc.u.tex.last_layer = pCreateRenderTargetView->Tex1D.ArraySize - 1 +
desc.u.tex.first_layer;
break;
case D3D10DDIRESOURCE_TEXTURE2D:
ASSERT(pCreateRenderTargetView->Tex2D.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateRenderTargetView->Tex2D.MipSlice;
desc.u.tex.first_layer = pCreateRenderTargetView->Tex2D.FirstArraySlice;
desc.u.tex.last_layer = pCreateRenderTargetView->Tex2D.ArraySize - 1 +
desc.u.tex.first_layer;
break;
case D3D10DDIRESOURCE_TEXTURE3D:
desc.u.tex.level = pCreateRenderTargetView->Tex3D.MipSlice;
desc.u.tex.first_layer = pCreateRenderTargetView->Tex3D.FirstW;
desc.u.tex.last_layer = pCreateRenderTargetView->Tex3D.WSize - 1 +
desc.u.tex.first_layer;
break;
case D3D10DDIRESOURCE_TEXTURECUBE:
ASSERT(pCreateRenderTargetView->TexCube.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateRenderTargetView->TexCube.MipSlice;
desc.u.tex.first_layer = pCreateRenderTargetView->TexCube.FirstArraySlice;
desc.u.tex.last_layer = pCreateRenderTargetView->TexCube.ArraySize - 1 +
desc.u.tex.first_layer;;
break;
default:
ASSERT(0);
return;
}
pRTView->surface = pipe->create_surface(pipe, resource, &desc);
assert(pRTView->surface);
}
/*
* ----------------------------------------------------------------------
*
* DestroyRenderTargetView --
*
* The DestroyRenderTargetView function destroys the specified
* render target view object. The render target view object can
* be destoyed only if it is not currently bound to a display device.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HRENDERTARGETVIEW hRenderTargetView) // IN
{
LOG_ENTRYPOINT();
RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);
pipe_surface_reference(&pRTView->surface, NULL);
}
/*
* ----------------------------------------------------------------------
*
* ClearRenderTargetView --
*
* The ClearRenderTargetView function clears the specified
* render target view by setting it to a constant value.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
ClearRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN
FLOAT pColorRGBA[4]) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
struct pipe_surface *surface = CastPipeRenderTargetView(hRenderTargetView);
union pipe_color_union clear_color;
/*
* DX10 always uses float clear color but gallium does not.
* Conversion should just be ordinary conversion. Actual clamping will
* be done later but need to make sure values exceeding int/uint range
* are handled correctly.
*/
if (util_format_is_pure_integer(surface->format)) {
if (util_format_is_pure_sint(surface->format)) {
unsigned i;
/* If only MIN_INT/UINT32 in c++ code would work... */
int min_int32 = 0x80000000;
int max_int32 = 0x7fffffff;
for (i = 0; i < 4; i++) {
float value = pColorRGBA[i];
/* This is an expanded clamp to handle NaN and integer conversion. */
if (util_is_nan(value)) {
clear_color.i[i] = 0;
} else if (value <= (float)min_int32) {
clear_color.i[i] = min_int32;
} else if (value >= (float)max_int32) {
clear_color.i[i] = max_int32;
} else {
clear_color.i[i] = value;
}
}
}
else {
assert(util_format_is_pure_uint(surface->format));
unsigned i;
unsigned max_uint32 = 0xffffffffU;
for (i = 0; i < 4; i++) {
float value = pColorRGBA[i];
/* This is an expanded clamp to handle NaN and integer conversion. */
if (!(value >= 0.0f)) {
/* Handles NaN. */
clear_color.ui[i] = 0;
} else if (value >= (float)max_uint32) {
clear_color.ui[i] = max_uint32;
} else {
clear_color.ui[i] = value;
}
}
}
}
else {
clear_color.f[0] = pColorRGBA[0];
clear_color.f[1] = pColorRGBA[1];
clear_color.f[2] = pColorRGBA[2];
clear_color.f[3] = pColorRGBA[3];
}
pipe->clear_render_target(pipe,
surface,
&clear_color,
0, 0,
pipe_surface_width(surface),
pipe_surface_height(surface),
true);
}
/*
* ----------------------------------------------------------------------
*
* CalcPrivateDepthStencilViewSize --
*
* The CalcPrivateDepthStencilViewSize 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) for a depth stencil view.
*
* ----------------------------------------------------------------------
*/
SIZE_T APIENTRY
CalcPrivateDepthStencilViewSize(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView) // IN
{
return sizeof(DepthStencilView);
}
/*
* ----------------------------------------------------------------------
*
* CreateDepthStencilView --
*
* The CreateDepthStencilView function creates a depth stencil view.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
CreateDepthStencilView(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, // IN
D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN
D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
struct pipe_resource *resource = CastPipeResource(pCreateDepthStencilView->hDrvResource);
DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
struct pipe_surface desc;
memset(&desc, 0, sizeof desc);
desc.format = FormatTranslate(pCreateDepthStencilView->Format, true);
switch (pCreateDepthStencilView->ResourceDimension) {
case D3D10DDIRESOURCE_TEXTURE1D:
ASSERT(pCreateDepthStencilView->Tex1D.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateDepthStencilView->Tex1D.MipSlice;
desc.u.tex.first_layer = pCreateDepthStencilView->Tex1D.FirstArraySlice;
desc.u.tex.last_layer = pCreateDepthStencilView->Tex1D.ArraySize - 1 +
desc.u.tex.first_layer;
break;
case D3D10DDIRESOURCE_TEXTURE2D:
ASSERT(pCreateDepthStencilView->Tex2D.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateDepthStencilView->Tex2D.MipSlice;
desc.u.tex.first_layer = pCreateDepthStencilView->Tex2D.FirstArraySlice;
desc.u.tex.last_layer = pCreateDepthStencilView->Tex2D.ArraySize - 1 +
desc.u.tex.first_layer;
break;
case D3D10DDIRESOURCE_TEXTURECUBE:
ASSERT(pCreateDepthStencilView->TexCube.ArraySize != (UINT)-1);
desc.u.tex.level = pCreateDepthStencilView->TexCube.MipSlice;
desc.u.tex.first_layer = pCreateDepthStencilView->TexCube.FirstArraySlice;
desc.u.tex.last_layer = pCreateDepthStencilView->TexCube.ArraySize - 1 +
desc.u.tex.first_layer;
break;
default:
ASSERT(0);
return;
}
pDSView->surface = pipe->create_surface(pipe, resource, &desc);
assert(pDSView->surface);
}
/*
* ----------------------------------------------------------------------
*
* DestroyDepthStencilView --
*
* The DestroyDepthStencilView function destroys the specified
* depth stencil view object. The depth stencil view object can
* be destoyed only if it is not currently bound to a display device.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN
{
LOG_ENTRYPOINT();
DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);
pipe_surface_reference(&pDSView->surface, NULL);
}
/*
* ----------------------------------------------------------------------
*
* ClearDepthStencilView --
*
* The ClearDepthStencilView function clears the specified
* currently bound depth-stencil view.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
ClearDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN
UINT Flags, // IN
FLOAT Depth, // IN
UINT8 Stencil) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
struct pipe_surface *surface = CastPipeDepthStencilView(hDepthStencilView);
unsigned flags = 0;
if (Flags & D3D10_DDI_CLEAR_DEPTH) {
flags |= PIPE_CLEAR_DEPTH;
}
if (Flags & D3D10_DDI_CLEAR_STENCIL) {
flags |= PIPE_CLEAR_STENCIL;
}
pipe->clear_depth_stencil(pipe,
surface,
flags,
Depth,
Stencil,
0, 0,
pipe_surface_width(surface),
pipe_surface_height(surface),
true);
}
/*
* ----------------------------------------------------------------------
*
* CalcPrivateBlendStateSize --
*
* The CalcPrivateBlendStateSize 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) for a blend state.
*
* ----------------------------------------------------------------------
*/
SIZE_T APIENTRY
CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_DDI_BLEND_DESC *pBlendDesc) // IN
{
return sizeof(BlendState);
}
/*
* ----------------------------------------------------------------------
*
* CalcPrivateBlendStateSize1 --
*
* The CalcPrivateBlendStateSize1 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) for a blend state.
*
* ----------------------------------------------------------------------
*/
SIZE_T APIENTRY
CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_1_DDI_BLEND_DESC *pBlendDesc) // IN
{
return sizeof(BlendState);
}
/*
* ----------------------------------------------------------------------
*
* translateBlendOp --
*
* Translate blend function from svga3d to gallium representation.
*
* ----------------------------------------------------------------------
*/
static uint
translateBlendOp(D3D10_DDI_BLEND_OP op)
{
switch (op) {
case D3D10_DDI_BLEND_OP_ADD:
return PIPE_BLEND_ADD;
case D3D10_DDI_BLEND_OP_SUBTRACT:
return PIPE_BLEND_SUBTRACT;
case D3D10_DDI_BLEND_OP_REV_SUBTRACT:
return PIPE_BLEND_REVERSE_SUBTRACT;
case D3D10_DDI_BLEND_OP_MIN:
return PIPE_BLEND_MIN;
case D3D10_DDI_BLEND_OP_MAX:
return PIPE_BLEND_MAX;
default:
assert(0);
return PIPE_BLEND_ADD;
}
}
/*
* ----------------------------------------------------------------------
*
* translateBlend --
*
* Translate blend factor from svga3d to gallium representation.
*
* ----------------------------------------------------------------------
*/
static uint
translateBlend(Device *pDevice,
D3D10_DDI_BLEND blend)
{
if (!pDevice->max_dual_source_render_targets) {
switch (blend) {
case D3D10_DDI_BLEND_SRC1_COLOR:
case D3D10_DDI_BLEND_SRC1_ALPHA:
LOG_UNSUPPORTED(true);
return D3D10_DDI_BLEND_ZERO;
case D3D10_DDI_BLEND_INV_SRC1_COLOR:
case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
LOG_UNSUPPORTED(true);
return D3D10_DDI_BLEND_ONE;
default:
break;
}
}
switch (blend) {
case D3D10_DDI_BLEND_ZERO:
return PIPE_BLENDFACTOR_ZERO;
case D3D10_DDI_BLEND_ONE:
return PIPE_BLENDFACTOR_ONE;
case D3D10_DDI_BLEND_SRC_COLOR:
return PIPE_BLENDFACTOR_SRC_COLOR;
case D3D10_DDI_BLEND_INV_SRC_COLOR:
return PIPE_BLENDFACTOR_INV_SRC_COLOR;
case D3D10_DDI_BLEND_SRC_ALPHA:
return PIPE_BLENDFACTOR_SRC_ALPHA;
case D3D10_DDI_BLEND_INV_SRC_ALPHA:
return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
case D3D10_DDI_BLEND_DEST_ALPHA:
return PIPE_BLENDFACTOR_DST_ALPHA;
case D3D10_DDI_BLEND_INV_DEST_ALPHA:
return PIPE_BLENDFACTOR_INV_DST_ALPHA;
case D3D10_DDI_BLEND_DEST_COLOR:
return PIPE_BLENDFACTOR_DST_COLOR;
case D3D10_DDI_BLEND_INV_DEST_COLOR:
return PIPE_BLENDFACTOR_INV_DST_COLOR;
case D3D10_DDI_BLEND_SRC_ALPHASAT:
return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
case D3D10_DDI_BLEND_BLEND_FACTOR:
return PIPE_BLENDFACTOR_CONST_COLOR;
case D3D10_DDI_BLEND_INVBLEND_FACTOR:
return PIPE_BLENDFACTOR_INV_CONST_COLOR;
case D3D10_DDI_BLEND_SRC1_COLOR:
return PIPE_BLENDFACTOR_SRC1_COLOR;
case D3D10_DDI_BLEND_INV_SRC1_COLOR:
return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
case D3D10_DDI_BLEND_SRC1_ALPHA:
return PIPE_BLENDFACTOR_SRC1_ALPHA;
case D3D10_DDI_BLEND_INV_SRC1_ALPHA:
return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
default:
assert(0);
return PIPE_BLENDFACTOR_ONE;
}
}
/*
* ----------------------------------------------------------------------
*
* CreateBlendState --
*
* The CreateBlendState function creates a blend state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
CreateBlendState(D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_DDI_BLEND_DESC *pBlendDesc, // IN
D3D10DDI_HBLENDSTATE hBlendState, // IN
D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN
{
unsigned i;
LOG_ENTRYPOINT();
Device *pDevice = CastDevice(hDevice);
struct pipe_context *pipe = pDevice->pipe;
BlendState *pBlendState = CastBlendState(hBlendState);
struct pipe_blend_state state;
memset(&state, 0, sizeof state);
for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
state.rt[i].blend_enable = pBlendDesc->BlendEnable[i];
state.rt[i].colormask = pBlendDesc->RenderTargetWriteMask[i];
if (pBlendDesc->BlendEnable[0] != pBlendDesc->BlendEnable[i] ||
pBlendDesc->RenderTargetWriteMask[0] != pBlendDesc->RenderTargetWriteMask[i]) {
state.independent_blend_enable = 1;
}
}
state.rt[0].rgb_func = translateBlendOp(pBlendDesc->BlendOp);
if (pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MIN ||
pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MAX) {
state.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
state.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
} else {
state.rt[0].rgb_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlend);
state.rt[0].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlend);
}
state.rt[0].alpha_func = translateBlendOp(pBlendDesc->BlendOpAlpha);
if (pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
state.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
state.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
} else {
state.rt[0].alpha_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlendAlpha);
state.rt[0].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlendAlpha);
}
/*
* Propagate to all the other rendertargets
*/
for (i = 1; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
state.rt[i].rgb_func = state.rt[0].rgb_func;
state.rt[i].rgb_src_factor = state.rt[0].rgb_src_factor;
state.rt[i].rgb_dst_factor = state.rt[0].rgb_dst_factor;
state.rt[i].alpha_func = state.rt[0].alpha_func;
state.rt[i].alpha_src_factor = state.rt[0].alpha_src_factor;
state.rt[i].alpha_dst_factor = state.rt[0].alpha_dst_factor;
}
state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
pBlendState->handle = pipe->create_blend_state(pipe, &state);
}
/*
* ----------------------------------------------------------------------
*
* CreateBlendState1 --
*
* The CreateBlendState1 function creates a blend state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
CreateBlendState1(D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_1_DDI_BLEND_DESC *pBlendDesc, // IN
D3D10DDI_HBLENDSTATE hBlendState, // IN
D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN
{
unsigned i;
LOG_ENTRYPOINT();
Device *pDevice = CastDevice(hDevice);
struct pipe_context *pipe = pDevice->pipe;
BlendState *pBlendState = CastBlendState(hBlendState);
struct pipe_blend_state state;
memset(&state, 0, sizeof state);
state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;
state.independent_blend_enable = pBlendDesc->IndependentBlendEnable;
for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {
state.rt[i].blend_enable = pBlendDesc->RenderTarget[i].BlendEnable;
state.rt[i].colormask = pBlendDesc->RenderTarget[i].RenderTargetWriteMask;
state.rt[i].rgb_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOp);
if (pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MIN ||
pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MAX) {
state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
} else {
state.rt[i].rgb_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlend);
state.rt[i].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlend);
}
state.rt[i].alpha_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOpAlpha);
if (pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||
pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {
state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
} else {
state.rt[i].alpha_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlendAlpha);
state.rt[i].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlendAlpha);
}
}
pBlendState->handle = pipe->create_blend_state(pipe, &state);
}
/*
* ----------------------------------------------------------------------
*
* DestroyBlendState --
*
* The DestroyBlendState function destroys the specified blend
* state object. The blend state object can be destoyed only if
* it is not currently bound to a display device.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
DestroyBlendState(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HBLENDSTATE hBlendState) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
BlendState *pBlendState = CastBlendState(hBlendState);
pipe->delete_blend_state(pipe, pBlendState->handle);
}
/*
* ----------------------------------------------------------------------
*
* SetBlendState --
*
* The SetBlendState function sets a blend state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
SetBlendState(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HBLENDSTATE hState, // IN
const FLOAT pBlendFactor[4], // IN
UINT SampleMask) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
void *state = CastPipeBlendState(hState);
pipe->bind_blend_state(pipe, state);
struct pipe_blend_color color;
color.color[0] = pBlendFactor[0];
color.color[1] = pBlendFactor[1];
color.color[2] = pBlendFactor[2];
color.color[3] = pBlendFactor[3];
pipe->set_blend_color(pipe, &color);
pipe->set_sample_mask(pipe, SampleMask);
}
/*
* ----------------------------------------------------------------------
*
* SetRenderTargets --
*
* Set the rendertargets.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
SetRenderTargets(D3D10DDI_HDEVICE hDevice, // IN
__in_ecount (NumViews)
const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, // IN
UINT RTargets, // IN
UINT ClearTargets, // IN
D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN
{
LOG_ENTRYPOINT();
Device *pDevice = CastDevice(hDevice);
struct pipe_context *pipe = pDevice->pipe;
pDevice->fb.nr_cbufs = 0;
for (unsigned i = 0; i < RTargets; ++i) {
pipe_surface_reference(&pDevice->fb.cbufs[i],
CastPipeRenderTargetView(phRenderTargetView[i]));
if (pDevice->fb.cbufs[i]) {
pDevice->fb.nr_cbufs = i + 1;
}
}
for (unsigned i = RTargets; i < PIPE_MAX_COLOR_BUFS; ++i) {
pipe_surface_reference(&pDevice->fb.cbufs[i], NULL);
}
pipe_surface_reference(&pDevice->fb.zsbuf,
CastPipeDepthStencilView(hDepthStencilView));
/*
* Calculate the width/height fields for this framebuffer. D3D10
* actually specifies that they be identical for all bound views.
*/
unsigned width, height;
util_framebuffer_min_size(&pDevice->fb, &width, &height);
pDevice->fb.width = width;
pDevice->fb.height = height;
pipe->set_framebuffer_state(pipe, &pDevice->fb);
}
/*
* ----------------------------------------------------------------------
*
* CalcPrivateDepthStencilStateSize --
*
* The CalcPrivateDepthStencilStateSize 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) for a depth stencil state.
*
* ----------------------------------------------------------------------
*/
SIZE_T APIENTRY
CalcPrivateDepthStencilStateSize(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc) // IN
{
return sizeof(DepthStencilState);
}
/*
* ----------------------------------------------------------------------
*
* translateComparison --
*
* Translate comparison function from DX10 to gallium representation.
*
* ----------------------------------------------------------------------
*/
static uint
translateComparison(D3D10_DDI_COMPARISON_FUNC Func)
{
switch (Func) {
case D3D10_DDI_COMPARISON_NEVER:
return PIPE_FUNC_NEVER;
case D3D10_DDI_COMPARISON_LESS:
return PIPE_FUNC_LESS;
case D3D10_DDI_COMPARISON_EQUAL:
return PIPE_FUNC_EQUAL;
case D3D10_DDI_COMPARISON_LESS_EQUAL:
return PIPE_FUNC_LEQUAL;
case D3D10_DDI_COMPARISON_GREATER:
return PIPE_FUNC_GREATER;
case D3D10_DDI_COMPARISON_NOT_EQUAL:
return PIPE_FUNC_NOTEQUAL;
case D3D10_DDI_COMPARISON_GREATER_EQUAL:
return PIPE_FUNC_GEQUAL;
case D3D10_DDI_COMPARISON_ALWAYS:
return PIPE_FUNC_ALWAYS;
default:
assert(0);
return PIPE_FUNC_ALWAYS;
}
}
/*
* ----------------------------------------------------------------------
*
* translateStencilOp --
*
* Translate stencil op from DX10 to gallium representation.
*
* ----------------------------------------------------------------------
*/
static uint
translateStencilOp(D3D10_DDI_STENCIL_OP StencilOp)
{
switch (StencilOp) {
case D3D10_DDI_STENCIL_OP_KEEP:
return PIPE_STENCIL_OP_KEEP;
case D3D10_DDI_STENCIL_OP_ZERO:
return PIPE_STENCIL_OP_ZERO;
case D3D10_DDI_STENCIL_OP_REPLACE:
return PIPE_STENCIL_OP_REPLACE;
case D3D10_DDI_STENCIL_OP_INCR_SAT:
return PIPE_STENCIL_OP_INCR;
case D3D10_DDI_STENCIL_OP_DECR_SAT:
return PIPE_STENCIL_OP_DECR;
case D3D10_DDI_STENCIL_OP_INVERT:
return PIPE_STENCIL_OP_INVERT;
case D3D10_DDI_STENCIL_OP_INCR:
return PIPE_STENCIL_OP_INCR_WRAP;
case D3D10_DDI_STENCIL_OP_DECR:
return PIPE_STENCIL_OP_DECR_WRAP;
default:
assert(0);
return PIPE_STENCIL_OP_KEEP;
}
}
/*
* ----------------------------------------------------------------------
*
* CreateDepthStencilState --
*
* The CreateDepthStencilState function creates a depth stencil state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
CreateDepthStencilState(
D3D10DDI_HDEVICE hDevice, // IN
__in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, // IN
D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState, // IN
D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
struct pipe_depth_stencil_alpha_state state;
memset(&state, 0, sizeof state);
/* Depth. */
state.depth_enabled = (pDepthStencilDesc->DepthEnable ? 1 : 0);
state.depth_writemask = (pDepthStencilDesc->DepthWriteMask ? 1 : 0);
state.depth_func = translateComparison(pDepthStencilDesc->DepthFunc);
/* Stencil. */
if (pDepthStencilDesc->StencilEnable) {
struct pipe_stencil_state *face0 = &state.stencil[0];
struct pipe_stencil_state *face1 = &state.stencil[1];
face0->enabled = 1;
face0->func = translateComparison(pDepthStencilDesc->FrontFace.StencilFunc);
face0->fail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilFailOp);
face0->zpass_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilPassOp);
face0->zfail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilDepthFailOp);
face0->valuemask = pDepthStencilDesc->StencilReadMask;
face0->writemask = pDepthStencilDesc->StencilWriteMask;
face1->enabled = 1;
face1->func = translateComparison(pDepthStencilDesc->BackFace.StencilFunc);
face1->fail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilFailOp);
face1->zpass_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilPassOp);
face1->zfail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilDepthFailOp);
face1->valuemask = pDepthStencilDesc->StencilReadMask;
face1->writemask = pDepthStencilDesc->StencilWriteMask;
#if MESA_DEBUG
if (!pDepthStencilDesc->FrontEnable) {
ASSERT(face0->func == PIPE_FUNC_ALWAYS);
ASSERT(face0->fail_op == PIPE_STENCIL_OP_KEEP);
ASSERT(face0->zpass_op == PIPE_STENCIL_OP_KEEP);
ASSERT(face0->zfail_op == PIPE_STENCIL_OP_KEEP);
}
if (!pDepthStencilDesc->BackEnable) {
ASSERT(face1->func == PIPE_FUNC_ALWAYS);
ASSERT(face1->fail_op == PIPE_STENCIL_OP_KEEP);
ASSERT(face1->zpass_op == PIPE_STENCIL_OP_KEEP);
ASSERT(face1->zfail_op == PIPE_STENCIL_OP_KEEP);
}
#endif
}
pDepthStencilState->handle =
pipe->create_depth_stencil_alpha_state(pipe, &state);
}
/*
* ----------------------------------------------------------------------
*
* DestroyDepthStencilState --
*
* The DestroyDepthStencilState function destroy a depth stencil state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);
pipe->delete_depth_stencil_alpha_state(pipe, pDepthStencilState->handle);
}
/*
* ----------------------------------------------------------------------
*
* SetDepthStencilState --
*
* The SetDepthStencilState function sets a depth-stencil state.
*
* ----------------------------------------------------------------------
*/
void APIENTRY
SetDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN
D3D10DDI_HDEPTHSTENCILSTATE hState, // IN
UINT StencilRef) // IN
{
LOG_ENTRYPOINT();
struct pipe_context *pipe = CastPipeContext(hDevice);
void *state = CastPipeDepthStencilState(hState);
struct pipe_stencil_ref psr;
psr.ref_value[0] = StencilRef;
psr.ref_value[1] = StencilRef;
pipe->bind_depth_stencil_alpha_state(pipe, state);
pipe->set_stencil_ref(pipe, psr);
}