Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/OutputMerger.cpp
4565 views
/**************************************************************************1*2* Copyright 2012-2021 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19* USE OR OTHER DEALINGS IN THE SOFTWARE.20*21* The above copyright notice and this permission notice (including the22* next paragraph) shall be included in all copies or substantial portions23* of the Software.24*25**************************************************************************/2627/*28* OutputMerger.cpp --29* Functions that manipulate the output merger state.30*/313233#include "OutputMerger.h"34#include "State.h"3536#include "Debug.h"37#include "Format.h"3839#include "util/u_framebuffer.h"40#include "util/format/u_format.h"414243/*44* ----------------------------------------------------------------------45*46* CalcPrivateRenderTargetViewSize --47*48* The CalcPrivateRenderTargetViewSize function determines the size49* of the user-mode display driver's private region of memory50* (that is, the size of internal driver structures, not the size51* of the resource video memory) for a render target view.52*53* ----------------------------------------------------------------------54*/555657SIZE_T APIENTRY58CalcPrivateRenderTargetViewSize(59D3D10DDI_HDEVICE hDevice, // IN60__in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView) // IN61{62return sizeof(RenderTargetView);63}646566/*67* ----------------------------------------------------------------------68*69* CreateRenderTargetView --70*71* The CreateRenderTargetView function creates a render target view.72*73* ----------------------------------------------------------------------74*/7576void APIENTRY77CreateRenderTargetView(78D3D10DDI_HDEVICE hDevice, // IN79__in const D3D10DDIARG_CREATERENDERTARGETVIEW *pCreateRenderTargetView, // IN80D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN81D3D10DDI_HRTRENDERTARGETVIEW hRTRenderTargetView) // IN82{83LOG_ENTRYPOINT();8485struct pipe_context *pipe = CastPipeContext(hDevice);86struct pipe_resource *resource = CastPipeResource(pCreateRenderTargetView->hDrvResource);87RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);8889struct pipe_surface desc;9091memset(&desc, 0, sizeof desc);92desc.format = FormatTranslate(pCreateRenderTargetView->Format, FALSE);9394switch (pCreateRenderTargetView->ResourceDimension) {95case D3D10DDIRESOURCE_BUFFER:96desc.u.buf.first_element = pCreateRenderTargetView->Buffer.FirstElement;97desc.u.buf.last_element = pCreateRenderTargetView->Buffer.NumElements - 1 +98desc.u.buf.first_element;99break;100case D3D10DDIRESOURCE_TEXTURE1D:101ASSERT(pCreateRenderTargetView->Tex1D.ArraySize != (UINT)-1);102desc.u.tex.level = pCreateRenderTargetView->Tex1D.MipSlice;103desc.u.tex.first_layer = pCreateRenderTargetView->Tex1D.FirstArraySlice;104desc.u.tex.last_layer = pCreateRenderTargetView->Tex1D.ArraySize - 1 +105desc.u.tex.first_layer;106break;107case D3D10DDIRESOURCE_TEXTURE2D:108ASSERT(pCreateRenderTargetView->Tex2D.ArraySize != (UINT)-1);109desc.u.tex.level = pCreateRenderTargetView->Tex2D.MipSlice;110desc.u.tex.first_layer = pCreateRenderTargetView->Tex2D.FirstArraySlice;111desc.u.tex.last_layer = pCreateRenderTargetView->Tex2D.ArraySize - 1 +112desc.u.tex.first_layer;113break;114case D3D10DDIRESOURCE_TEXTURE3D:115desc.u.tex.level = pCreateRenderTargetView->Tex3D.MipSlice;116desc.u.tex.first_layer = pCreateRenderTargetView->Tex3D.FirstW;117desc.u.tex.last_layer = pCreateRenderTargetView->Tex3D.WSize - 1 +118desc.u.tex.first_layer;119break;120case D3D10DDIRESOURCE_TEXTURECUBE:121ASSERT(pCreateRenderTargetView->TexCube.ArraySize != (UINT)-1);122desc.u.tex.level = pCreateRenderTargetView->TexCube.MipSlice;123desc.u.tex.first_layer = pCreateRenderTargetView->TexCube.FirstArraySlice;124desc.u.tex.last_layer = pCreateRenderTargetView->TexCube.ArraySize - 1 +125desc.u.tex.first_layer;;126break;127default:128ASSERT(0);129return;130}131132pRTView->surface = pipe->create_surface(pipe, resource, &desc);133assert(pRTView->surface);134}135136137/*138* ----------------------------------------------------------------------139*140* DestroyRenderTargetView --141*142* The DestroyRenderTargetView function destroys the specified143* render target view object. The render target view object can144* be destoyed only if it is not currently bound to a display device.145*146* ----------------------------------------------------------------------147*/148149void APIENTRY150DestroyRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN151D3D10DDI_HRENDERTARGETVIEW hRenderTargetView) // IN152{153LOG_ENTRYPOINT();154155RenderTargetView *pRTView = CastRenderTargetView(hRenderTargetView);156157pipe_surface_reference(&pRTView->surface, NULL);158}159160161/*162* ----------------------------------------------------------------------163*164* ClearRenderTargetView --165*166* The ClearRenderTargetView function clears the specified167* render target view by setting it to a constant value.168*169* ----------------------------------------------------------------------170*/171172void APIENTRY173ClearRenderTargetView(D3D10DDI_HDEVICE hDevice, // IN174D3D10DDI_HRENDERTARGETVIEW hRenderTargetView, // IN175FLOAT pColorRGBA[4]) // IN176{177LOG_ENTRYPOINT();178179struct pipe_context *pipe = CastPipeContext(hDevice);180struct pipe_surface *surface = CastPipeRenderTargetView(hRenderTargetView);181union pipe_color_union clear_color;182183/*184* DX10 always uses float clear color but gallium does not.185* Conversion should just be ordinary conversion. Actual clamping will186* be done later but need to make sure values exceeding int/uint range187* are handled correctly.188*/189if (util_format_is_pure_integer(surface->format)) {190if (util_format_is_pure_sint(surface->format)) {191unsigned i;192/* If only MIN_INT/UINT32 in c++ code would work... */193int min_int32 = 0x80000000;194int max_int32 = 0x7fffffff;195for (i = 0; i < 4; i++) {196float value = pColorRGBA[i];197/* This is an expanded clamp to handle NaN and integer conversion. */198if (util_is_nan(value)) {199clear_color.i[i] = 0;200} else if (value <= (float)min_int32) {201clear_color.i[i] = min_int32;202} else if (value >= (float)max_int32) {203clear_color.i[i] = max_int32;204} else {205clear_color.i[i] = value;206}207}208}209else {210assert(util_format_is_pure_uint(surface->format));211unsigned i;212unsigned max_uint32 = 0xffffffffU;213for (i = 0; i < 4; i++) {214float value = pColorRGBA[i];215/* This is an expanded clamp to handle NaN and integer conversion. */216if (!(value >= 0.0f)) {217/* Handles NaN. */218clear_color.ui[i] = 0;219} else if (value >= (float)max_uint32) {220clear_color.ui[i] = max_uint32;221} else {222clear_color.ui[i] = value;223}224}225}226}227else {228clear_color.f[0] = pColorRGBA[0];229clear_color.f[1] = pColorRGBA[1];230clear_color.f[2] = pColorRGBA[2];231clear_color.f[3] = pColorRGBA[3];232}233234pipe->clear_render_target(pipe,235surface,236&clear_color,2370, 0,238surface->width,239surface->height,240TRUE);241}242243244/*245* ----------------------------------------------------------------------246*247* CalcPrivateDepthStencilViewSize --248*249* The CalcPrivateDepthStencilViewSize function determines the size250* of the user-mode display driver's private region of memory251* (that is, the size of internal driver structures, not the size252* of the resource video memory) for a depth stencil view.253*254* ----------------------------------------------------------------------255*/256257SIZE_T APIENTRY258CalcPrivateDepthStencilViewSize(259D3D10DDI_HDEVICE hDevice, // IN260__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView) // IN261{262return sizeof(DepthStencilView);263}264265266/*267* ----------------------------------------------------------------------268*269* CreateDepthStencilView --270*271* The CreateDepthStencilView function creates a depth stencil view.272*273* ----------------------------------------------------------------------274*/275276void APIENTRY277CreateDepthStencilView(278D3D10DDI_HDEVICE hDevice, // IN279__in const D3D10DDIARG_CREATEDEPTHSTENCILVIEW *pCreateDepthStencilView, // IN280D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN281D3D10DDI_HRTDEPTHSTENCILVIEW hRTDepthStencilView) // IN282{283LOG_ENTRYPOINT();284285struct pipe_context *pipe = CastPipeContext(hDevice);286struct pipe_resource *resource = CastPipeResource(pCreateDepthStencilView->hDrvResource);287DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);288289struct pipe_surface desc;290291memset(&desc, 0, sizeof desc);292desc.format = FormatTranslate(pCreateDepthStencilView->Format, TRUE);293294switch (pCreateDepthStencilView->ResourceDimension) {295case D3D10DDIRESOURCE_TEXTURE1D:296ASSERT(pCreateDepthStencilView->Tex1D.ArraySize != (UINT)-1);297desc.u.tex.level = pCreateDepthStencilView->Tex1D.MipSlice;298desc.u.tex.first_layer = pCreateDepthStencilView->Tex1D.FirstArraySlice;299desc.u.tex.last_layer = pCreateDepthStencilView->Tex1D.ArraySize - 1 +300desc.u.tex.first_layer;301break;302case D3D10DDIRESOURCE_TEXTURE2D:303ASSERT(pCreateDepthStencilView->Tex2D.ArraySize != (UINT)-1);304desc.u.tex.level = pCreateDepthStencilView->Tex2D.MipSlice;305desc.u.tex.first_layer = pCreateDepthStencilView->Tex2D.FirstArraySlice;306desc.u.tex.last_layer = pCreateDepthStencilView->Tex2D.ArraySize - 1 +307desc.u.tex.first_layer;308break;309case D3D10DDIRESOURCE_TEXTURECUBE:310ASSERT(pCreateDepthStencilView->TexCube.ArraySize != (UINT)-1);311desc.u.tex.level = pCreateDepthStencilView->TexCube.MipSlice;312desc.u.tex.first_layer = pCreateDepthStencilView->TexCube.FirstArraySlice;313desc.u.tex.last_layer = pCreateDepthStencilView->TexCube.ArraySize - 1 +314desc.u.tex.first_layer;315break;316default:317ASSERT(0);318return;319}320321pDSView->surface = pipe->create_surface(pipe, resource, &desc);322assert(pDSView->surface);323}324325326/*327* ----------------------------------------------------------------------328*329* DestroyDepthStencilView --330*331* The DestroyDepthStencilView function destroys the specified332* depth stencil view object. The depth stencil view object can333* be destoyed only if it is not currently bound to a display device.334*335* ----------------------------------------------------------------------336*/337338void APIENTRY339DestroyDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN340D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN341{342LOG_ENTRYPOINT();343344DepthStencilView *pDSView = CastDepthStencilView(hDepthStencilView);345346pipe_surface_reference(&pDSView->surface, NULL);347}348349350/*351* ----------------------------------------------------------------------352*353* ClearDepthStencilView --354*355* The ClearDepthStencilView function clears the specified356* currently bound depth-stencil view.357*358* ----------------------------------------------------------------------359*/360361void APIENTRY362ClearDepthStencilView(D3D10DDI_HDEVICE hDevice, // IN363D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView, // IN364UINT Flags, // IN365FLOAT Depth, // IN366UINT8 Stencil) // IN367{368LOG_ENTRYPOINT();369370struct pipe_context *pipe = CastPipeContext(hDevice);371struct pipe_surface *surface = CastPipeDepthStencilView(hDepthStencilView);372373unsigned flags = 0;374if (Flags & D3D10_DDI_CLEAR_DEPTH) {375flags |= PIPE_CLEAR_DEPTH;376}377if (Flags & D3D10_DDI_CLEAR_STENCIL) {378flags |= PIPE_CLEAR_STENCIL;379}380381pipe->clear_depth_stencil(pipe,382surface,383flags,384Depth,385Stencil,3860, 0,387surface->width,388surface->height,389TRUE);390}391392393/*394* ----------------------------------------------------------------------395*396* CalcPrivateBlendStateSize --397*398* The CalcPrivateBlendStateSize function determines the size of399* the user-mode display driver's private region of memory (that400* is, the size of internal driver structures, not the size of401* the resource video memory) for a blend state.402*403* ----------------------------------------------------------------------404*/405406SIZE_T APIENTRY407CalcPrivateBlendStateSize(D3D10DDI_HDEVICE hDevice, // IN408__in const D3D10_DDI_BLEND_DESC *pBlendDesc) // IN409{410return sizeof(BlendState);411}412413414/*415* ----------------------------------------------------------------------416*417* CalcPrivateBlendStateSize1 --418*419* The CalcPrivateBlendStateSize function determines the size of420* the user-mode display driver's private region of memory (that421* is, the size of internal driver structures, not the size of422* the resource video memory) for a blend state.423*424* ----------------------------------------------------------------------425*/426427SIZE_T APIENTRY428CalcPrivateBlendStateSize1(D3D10DDI_HDEVICE hDevice, // IN429__in const D3D10_1_DDI_BLEND_DESC *pBlendDesc) // IN430{431return sizeof(BlendState);432}433434435/*436* ----------------------------------------------------------------------437*438* translateBlend --439*440* Translate blend function from svga3d to gallium representation.441*442* ----------------------------------------------------------------------443*/444static uint445translateBlendOp(D3D10_DDI_BLEND_OP op)446{447switch (op) {448case D3D10_DDI_BLEND_OP_ADD:449return PIPE_BLEND_ADD;450case D3D10_DDI_BLEND_OP_SUBTRACT:451return PIPE_BLEND_SUBTRACT;452case D3D10_DDI_BLEND_OP_REV_SUBTRACT:453return PIPE_BLEND_REVERSE_SUBTRACT;454case D3D10_DDI_BLEND_OP_MIN:455return PIPE_BLEND_MIN;456case D3D10_DDI_BLEND_OP_MAX:457return PIPE_BLEND_MAX;458default:459assert(0);460return PIPE_BLEND_ADD;461}462}463464465/*466* ----------------------------------------------------------------------467*468* translateBlend --469*470* Translate blend factor from svga3d to gallium representation.471*472* ----------------------------------------------------------------------473*/474static uint475translateBlend(Device *pDevice,476D3D10_DDI_BLEND blend)477{478if (!pDevice->max_dual_source_render_targets) {479switch (blend) {480case D3D10_DDI_BLEND_SRC1_COLOR:481case D3D10_DDI_BLEND_SRC1_ALPHA:482LOG_UNSUPPORTED(TRUE);483return D3D10_DDI_BLEND_ZERO;484case D3D10_DDI_BLEND_INV_SRC1_COLOR:485case D3D10_DDI_BLEND_INV_SRC1_ALPHA:486LOG_UNSUPPORTED(TRUE);487return D3D10_DDI_BLEND_ONE;488default:489break;490}491}492493switch (blend) {494case D3D10_DDI_BLEND_ZERO:495return PIPE_BLENDFACTOR_ZERO;496case D3D10_DDI_BLEND_ONE:497return PIPE_BLENDFACTOR_ONE;498case D3D10_DDI_BLEND_SRC_COLOR:499return PIPE_BLENDFACTOR_SRC_COLOR;500case D3D10_DDI_BLEND_INV_SRC_COLOR:501return PIPE_BLENDFACTOR_INV_SRC_COLOR;502case D3D10_DDI_BLEND_SRC_ALPHA:503return PIPE_BLENDFACTOR_SRC_ALPHA;504case D3D10_DDI_BLEND_INV_SRC_ALPHA:505return PIPE_BLENDFACTOR_INV_SRC_ALPHA;506case D3D10_DDI_BLEND_DEST_ALPHA:507return PIPE_BLENDFACTOR_DST_ALPHA;508case D3D10_DDI_BLEND_INV_DEST_ALPHA:509return PIPE_BLENDFACTOR_INV_DST_ALPHA;510case D3D10_DDI_BLEND_DEST_COLOR:511return PIPE_BLENDFACTOR_DST_COLOR;512case D3D10_DDI_BLEND_INV_DEST_COLOR:513return PIPE_BLENDFACTOR_INV_DST_COLOR;514case D3D10_DDI_BLEND_SRC_ALPHASAT:515return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;516case D3D10_DDI_BLEND_BLEND_FACTOR:517return PIPE_BLENDFACTOR_CONST_COLOR;518case D3D10_DDI_BLEND_INVBLEND_FACTOR:519return PIPE_BLENDFACTOR_INV_CONST_COLOR;520case D3D10_DDI_BLEND_SRC1_COLOR:521return PIPE_BLENDFACTOR_SRC1_COLOR;522case D3D10_DDI_BLEND_INV_SRC1_COLOR:523return PIPE_BLENDFACTOR_INV_SRC1_COLOR;524case D3D10_DDI_BLEND_SRC1_ALPHA:525return PIPE_BLENDFACTOR_SRC1_ALPHA;526case D3D10_DDI_BLEND_INV_SRC1_ALPHA:527return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;528default:529assert(0);530return PIPE_BLENDFACTOR_ONE;531}532}533534535/*536* ----------------------------------------------------------------------537*538* CreateBlendState --539*540* The CreateBlendState function creates a blend state.541*542* ----------------------------------------------------------------------543*/544545void APIENTRY546CreateBlendState(D3D10DDI_HDEVICE hDevice, // IN547__in const D3D10_DDI_BLEND_DESC *pBlendDesc, // IN548D3D10DDI_HBLENDSTATE hBlendState, // IN549D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN550{551unsigned i;552553LOG_ENTRYPOINT();554555Device *pDevice = CastDevice(hDevice);556struct pipe_context *pipe = pDevice->pipe;557BlendState *pBlendState = CastBlendState(hBlendState);558559struct pipe_blend_state state;560memset(&state, 0, sizeof state);561562for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {563state.rt[i].blend_enable = pBlendDesc->BlendEnable[i];564state.rt[i].colormask = pBlendDesc->RenderTargetWriteMask[i];565566if (pBlendDesc->BlendEnable[0] != pBlendDesc->BlendEnable[i] ||567pBlendDesc->RenderTargetWriteMask[0] != pBlendDesc->RenderTargetWriteMask[i]) {568state.independent_blend_enable = 1;569}570}571572state.rt[0].rgb_func = translateBlendOp(pBlendDesc->BlendOp);573if (pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MIN ||574pBlendDesc->BlendOp == D3D10_DDI_BLEND_OP_MAX) {575state.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;576state.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;577} else {578state.rt[0].rgb_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlend);579state.rt[0].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlend);580}581582state.rt[0].alpha_func = translateBlendOp(pBlendDesc->BlendOpAlpha);583if (pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||584pBlendDesc->BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {585state.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;586state.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;587} else {588state.rt[0].alpha_src_factor = translateBlend(pDevice, pBlendDesc->SrcBlendAlpha);589state.rt[0].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->DestBlendAlpha);590}591592/*593* Propagate to all the other rendertargets594*/595for (i = 1; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {596state.rt[i].rgb_func = state.rt[0].rgb_func;597state.rt[i].rgb_src_factor = state.rt[0].rgb_src_factor;598state.rt[i].rgb_dst_factor = state.rt[0].rgb_dst_factor;599state.rt[i].alpha_func = state.rt[0].alpha_func;600state.rt[i].alpha_src_factor = state.rt[0].alpha_src_factor;601state.rt[i].alpha_dst_factor = state.rt[0].alpha_dst_factor;602}603604state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;605606pBlendState->handle = pipe->create_blend_state(pipe, &state);607}608609610/*611* ----------------------------------------------------------------------612*613* CreateBlendState1 --614*615* The CreateBlendState function creates a blend state.616*617* ----------------------------------------------------------------------618*/619620void APIENTRY621CreateBlendState1(D3D10DDI_HDEVICE hDevice, // IN622__in const D3D10_1_DDI_BLEND_DESC *pBlendDesc, // IN623D3D10DDI_HBLENDSTATE hBlendState, // IN624D3D10DDI_HRTBLENDSTATE hRTBlendState) // IN625{626unsigned i;627628LOG_ENTRYPOINT();629630Device *pDevice = CastDevice(hDevice);631struct pipe_context *pipe = pDevice->pipe;632BlendState *pBlendState = CastBlendState(hBlendState);633634struct pipe_blend_state state;635memset(&state, 0, sizeof state);636637state.alpha_to_coverage = pBlendDesc->AlphaToCoverageEnable;638state.independent_blend_enable = pBlendDesc->IndependentBlendEnable;639640for (i = 0; i < MIN2(PIPE_MAX_COLOR_BUFS, D3D10_DDI_SIMULTANEOUS_RENDER_TARGET_COUNT); ++i) {641state.rt[i].blend_enable = pBlendDesc->RenderTarget[i].BlendEnable;642state.rt[i].colormask = pBlendDesc->RenderTarget[i].RenderTargetWriteMask;643644state.rt[i].rgb_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOp);645if (pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MIN ||646pBlendDesc->RenderTarget[i].BlendOp == D3D10_DDI_BLEND_OP_MAX) {647state.rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;648state.rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;649} else {650state.rt[i].rgb_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlend);651state.rt[i].rgb_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlend);652}653654state.rt[i].alpha_func = translateBlendOp(pBlendDesc->RenderTarget[i].BlendOpAlpha);655if (pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MIN ||656pBlendDesc->RenderTarget[i].BlendOpAlpha == D3D10_DDI_BLEND_OP_MAX) {657state.rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;658state.rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;659} else {660state.rt[i].alpha_src_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].SrcBlendAlpha);661state.rt[i].alpha_dst_factor = translateBlend(pDevice, pBlendDesc->RenderTarget[i].DestBlendAlpha);662}663}664665pBlendState->handle = pipe->create_blend_state(pipe, &state);666}667668669/*670* ----------------------------------------------------------------------671*672* DestroyBlendState --673*674* The DestroyBlendState function destroys the specified blend675* state object. The blend state object can be destoyed only if676* it is not currently bound to a display device.677*678* ----------------------------------------------------------------------679*/680681void APIENTRY682DestroyBlendState(D3D10DDI_HDEVICE hDevice, // IN683D3D10DDI_HBLENDSTATE hBlendState) // IN684{685LOG_ENTRYPOINT();686687struct pipe_context *pipe = CastPipeContext(hDevice);688BlendState *pBlendState = CastBlendState(hBlendState);689690pipe->delete_blend_state(pipe, pBlendState->handle);691}692693694/*695* ----------------------------------------------------------------------696*697* SetBlendState --698*699* The SetBlendState function sets a blend state.700*701* ----------------------------------------------------------------------702*/703704void APIENTRY705SetBlendState(D3D10DDI_HDEVICE hDevice, // IN706D3D10DDI_HBLENDSTATE hState, // IN707const FLOAT pBlendFactor[4], // IN708UINT SampleMask) // IN709{710LOG_ENTRYPOINT();711712struct pipe_context *pipe = CastPipeContext(hDevice);713void *state = CastPipeBlendState(hState);714715pipe->bind_blend_state(pipe, state);716717struct pipe_blend_color color;718color.color[0] = pBlendFactor[0];719color.color[1] = pBlendFactor[1];720color.color[2] = pBlendFactor[2];721color.color[3] = pBlendFactor[3];722723pipe->set_blend_color(pipe, &color);724725pipe->set_sample_mask(pipe, SampleMask);726}727728729/*730* ----------------------------------------------------------------------731*732* SetRenderTargets --733*734* Set the rendertargets.735*736* ----------------------------------------------------------------------737*/738739void APIENTRY740SetRenderTargets(D3D10DDI_HDEVICE hDevice, // IN741__in_ecount (NumViews)742const D3D10DDI_HRENDERTARGETVIEW *phRenderTargetView, // IN743UINT RTargets, // IN744UINT ClearTargets, // IN745D3D10DDI_HDEPTHSTENCILVIEW hDepthStencilView) // IN746{747LOG_ENTRYPOINT();748749Device *pDevice = CastDevice(hDevice);750751struct pipe_context *pipe = pDevice->pipe;752753pDevice->fb.nr_cbufs = 0;754for (unsigned i = 0; i < RTargets; ++i) {755pipe_surface_reference(&pDevice->fb.cbufs[i],756CastPipeRenderTargetView(phRenderTargetView[i]));757if (pDevice->fb.cbufs[i]) {758pDevice->fb.nr_cbufs = i + 1;759}760}761762for (unsigned i = RTargets; i < PIPE_MAX_COLOR_BUFS; ++i) {763pipe_surface_reference(&pDevice->fb.cbufs[i], NULL);764}765766pipe_surface_reference(&pDevice->fb.zsbuf,767CastPipeDepthStencilView(hDepthStencilView));768769/*770* Calculate the width/height fields for this framebuffer. D3D10771* actually specifies that they be identical for all bound views.772*/773unsigned width, height;774util_framebuffer_min_size(&pDevice->fb, &width, &height);775pDevice->fb.width = width;776pDevice->fb.height = height;777778pipe->set_framebuffer_state(pipe, &pDevice->fb);779}780781782/*783* ----------------------------------------------------------------------784*785* CalcPrivateDepthStencilStateSize --786*787* The CalcPrivateDepthStencilStateSize function determines the size788* of the user-mode display driver's private region of memory (that789* is, the size of internal driver structures, not the size of the790* resource video memory) for a depth stencil state.791*792* ----------------------------------------------------------------------793*/794795SIZE_T APIENTRY796CalcPrivateDepthStencilStateSize(797D3D10DDI_HDEVICE hDevice, // IN798__in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc) // IN799{800return sizeof(DepthStencilState);801}802803804/*805* ----------------------------------------------------------------------806*807* translateComparison --808*809* Translate comparison function from DX10 to gallium representation.810*811* ----------------------------------------------------------------------812*/813static uint814translateComparison(D3D10_DDI_COMPARISON_FUNC Func)815{816switch (Func) {817case D3D10_DDI_COMPARISON_NEVER:818return PIPE_FUNC_NEVER;819case D3D10_DDI_COMPARISON_LESS:820return PIPE_FUNC_LESS;821case D3D10_DDI_COMPARISON_EQUAL:822return PIPE_FUNC_EQUAL;823case D3D10_DDI_COMPARISON_LESS_EQUAL:824return PIPE_FUNC_LEQUAL;825case D3D10_DDI_COMPARISON_GREATER:826return PIPE_FUNC_GREATER;827case D3D10_DDI_COMPARISON_NOT_EQUAL:828return PIPE_FUNC_NOTEQUAL;829case D3D10_DDI_COMPARISON_GREATER_EQUAL:830return PIPE_FUNC_GEQUAL;831case D3D10_DDI_COMPARISON_ALWAYS:832return PIPE_FUNC_ALWAYS;833default:834assert(0);835return PIPE_FUNC_ALWAYS;836}837}838839840/*841* ----------------------------------------------------------------------842*843* translateStencilOp --844*845* Translate stencil op from DX10 to gallium representation.846*847* ----------------------------------------------------------------------848*/849static uint850translateStencilOp(D3D10_DDI_STENCIL_OP StencilOp)851{852switch (StencilOp) {853case D3D10_DDI_STENCIL_OP_KEEP:854return PIPE_STENCIL_OP_KEEP;855case D3D10_DDI_STENCIL_OP_ZERO:856return PIPE_STENCIL_OP_ZERO;857case D3D10_DDI_STENCIL_OP_REPLACE:858return PIPE_STENCIL_OP_REPLACE;859case D3D10_DDI_STENCIL_OP_INCR_SAT:860return PIPE_STENCIL_OP_INCR;861case D3D10_DDI_STENCIL_OP_DECR_SAT:862return PIPE_STENCIL_OP_DECR;863case D3D10_DDI_STENCIL_OP_INVERT:864return PIPE_STENCIL_OP_INVERT;865case D3D10_DDI_STENCIL_OP_INCR:866return PIPE_STENCIL_OP_INCR_WRAP;867case D3D10_DDI_STENCIL_OP_DECR:868return PIPE_STENCIL_OP_DECR_WRAP;869default:870assert(0);871return PIPE_STENCIL_OP_KEEP;872}873}874875876/*877* ----------------------------------------------------------------------878*879* CreateDepthStencilState --880*881* The CreateDepthStencilState function creates a depth stencil state.882*883* ----------------------------------------------------------------------884*/885886void APIENTRY887CreateDepthStencilState(888D3D10DDI_HDEVICE hDevice, // IN889__in const D3D10_DDI_DEPTH_STENCIL_DESC *pDepthStencilDesc, // IN890D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState, // IN891D3D10DDI_HRTDEPTHSTENCILSTATE hRTDepthStencilState) // IN892{893LOG_ENTRYPOINT();894895struct pipe_context *pipe = CastPipeContext(hDevice);896DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);897898struct pipe_depth_stencil_alpha_state state;899memset(&state, 0, sizeof state);900901/* Depth. */902state.depth_enabled = (pDepthStencilDesc->DepthEnable ? 1 : 0);903state.depth_writemask = (pDepthStencilDesc->DepthWriteMask ? 1 : 0);904state.depth_func = translateComparison(pDepthStencilDesc->DepthFunc);905906/* Stencil. */907if (pDepthStencilDesc->StencilEnable) {908struct pipe_stencil_state *face0 = &state.stencil[0];909struct pipe_stencil_state *face1 = &state.stencil[1];910911face0->enabled = 1;912face0->func = translateComparison(pDepthStencilDesc->FrontFace.StencilFunc);913face0->fail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilFailOp);914face0->zpass_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilPassOp);915face0->zfail_op = translateStencilOp(pDepthStencilDesc->FrontFace.StencilDepthFailOp);916face0->valuemask = pDepthStencilDesc->StencilReadMask;917face0->writemask = pDepthStencilDesc->StencilWriteMask;918919face1->enabled = 1;920face1->func = translateComparison(pDepthStencilDesc->BackFace.StencilFunc);921face1->fail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilFailOp);922face1->zpass_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilPassOp);923face1->zfail_op = translateStencilOp(pDepthStencilDesc->BackFace.StencilDepthFailOp);924face1->valuemask = pDepthStencilDesc->StencilReadMask;925face1->writemask = pDepthStencilDesc->StencilWriteMask;926#ifdef DEBUG927if (!pDepthStencilDesc->FrontEnable) {928ASSERT(face0->func == PIPE_FUNC_ALWAYS);929ASSERT(face0->fail_op == PIPE_STENCIL_OP_KEEP);930ASSERT(face0->zpass_op == PIPE_STENCIL_OP_KEEP);931ASSERT(face0->zfail_op == PIPE_STENCIL_OP_KEEP);932}933934if (!pDepthStencilDesc->BackEnable) {935ASSERT(face1->func == PIPE_FUNC_ALWAYS);936ASSERT(face1->fail_op == PIPE_STENCIL_OP_KEEP);937ASSERT(face1->zpass_op == PIPE_STENCIL_OP_KEEP);938ASSERT(face1->zfail_op == PIPE_STENCIL_OP_KEEP);939}940#endif941}942943pDepthStencilState->handle =944pipe->create_depth_stencil_alpha_state(pipe, &state);945}946947948/*949* ----------------------------------------------------------------------950*951* DestroyDepthStencilState --952*953* The CreateDepthStencilState function creates a depth stencil state.954*955* ----------------------------------------------------------------------956*/957958void APIENTRY959DestroyDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN960D3D10DDI_HDEPTHSTENCILSTATE hDepthStencilState) // IN961{962LOG_ENTRYPOINT();963964struct pipe_context *pipe = CastPipeContext(hDevice);965DepthStencilState *pDepthStencilState = CastDepthStencilState(hDepthStencilState);966967pipe->delete_depth_stencil_alpha_state(pipe, pDepthStencilState->handle);968}969970971/*972* ----------------------------------------------------------------------973*974* SetDepthStencilState --975*976* The SetDepthStencilState function sets a depth-stencil state.977*978* ----------------------------------------------------------------------979*/980981void APIENTRY982SetDepthStencilState(D3D10DDI_HDEVICE hDevice, // IN983D3D10DDI_HDEPTHSTENCILSTATE hState, // IN984UINT StencilRef) // IN985{986LOG_ENTRYPOINT();987988struct pipe_context *pipe = CastPipeContext(hDevice);989void *state = CastPipeDepthStencilState(hState);990struct pipe_stencil_ref psr;991992psr.ref_value[0] = StencilRef;993psr.ref_value[1] = StencilRef;994995pipe->bind_depth_stencil_alpha_state(pipe, state);996pipe->set_stencil_ref(pipe, psr);997}9989991000