Path: blob/21.2-virgl/src/gallium/frontends/d3d10umd/InputAssembly.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* InputAssembly.cpp --29* Functions that manipulate the input assembly stage.30*/313233#include <stdio.h>34#if defined(_MSC_VER) && !defined(snprintf)35#define snprintf _snprintf36#endif3738#include "InputAssembly.h"39#include "State.h"4041#include "Debug.h"42#include "Format.h"434445/*46* ----------------------------------------------------------------------47*48* IaSetTopology --49*50* The IaSetTopology function sets the primitive topology to51* enable drawing for the input assember.52*53* ----------------------------------------------------------------------54*/5556void APIENTRY57IaSetTopology(D3D10DDI_HDEVICE hDevice, // IN58D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology) // IN59{60LOG_ENTRYPOINT();6162Device *pDevice = CastDevice(hDevice);6364enum pipe_prim_type primitive;65switch (PrimitiveTopology) {66case D3D10_DDI_PRIMITIVE_TOPOLOGY_UNDEFINED:67/* Apps might set topology to UNDEFINED when cleaning up on exit. */68primitive = PIPE_PRIM_MAX;69break;70case D3D10_DDI_PRIMITIVE_TOPOLOGY_POINTLIST:71primitive = PIPE_PRIM_POINTS;72break;73case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST:74primitive = PIPE_PRIM_LINES;75break;76case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP:77primitive = PIPE_PRIM_LINE_STRIP;78break;79case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST:80primitive = PIPE_PRIM_TRIANGLES;81break;82case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:83primitive = PIPE_PRIM_TRIANGLE_STRIP;84break;85case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST_ADJ:86primitive = PIPE_PRIM_LINES_ADJACENCY;87break;88case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ:89primitive = PIPE_PRIM_LINE_STRIP_ADJACENCY;90break;91case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ:92primitive = PIPE_PRIM_TRIANGLES_ADJACENCY;93break;94case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ:95primitive = PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY;96break;97default:98assert(0);99primitive = PIPE_PRIM_MAX;100break;101}102103pDevice->primitive = primitive;104}105106107/*108* ----------------------------------------------------------------------109*110* IaSetVertexBuffers --111*112* The IaSetVertexBuffers function sets vertex buffers113* for an input assembler.114*115* ----------------------------------------------------------------------116*/117118void APIENTRY119IaSetVertexBuffers(D3D10DDI_HDEVICE hDevice, // IN120UINT StartBuffer, // IN121UINT NumBuffers, // IN122__in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers, // IN123__in_ecount (NumBuffers) const UINT *pStrides, // IN124__in_ecount (NumBuffers) const UINT *pOffsets) // IN125{126static const float dummy[4] = {0.0f, 0.0f, 0.0f, 0.0f};127128LOG_ENTRYPOINT();129130Device *pDevice = CastDevice(hDevice);131struct pipe_context *pipe = pDevice->pipe;132unsigned i;133134for (i = 0; i < NumBuffers; i++) {135struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[StartBuffer + i];136struct pipe_resource *resource = CastPipeResource(phBuffers[i]);137Resource *res = CastResource(phBuffers[i]);138struct pipe_stream_output_target *so_target =139res ? res->so_target : NULL;140141if (so_target && pDevice->draw_so_target != so_target) {142if (pDevice->draw_so_target) {143pipe_so_target_reference(&pDevice->draw_so_target, NULL);144}145pipe_so_target_reference(&pDevice->draw_so_target,146so_target);147}148149if (resource) {150vb->stride = pStrides[i];151vb->buffer_offset = pOffsets[i];152if (vb->is_user_buffer) {153vb->buffer.resource = NULL;154vb->is_user_buffer = FALSE;155}156pipe_resource_reference(&vb->buffer.resource, resource);157}158else {159vb->stride = 0;160vb->buffer_offset = 0;161if (!vb->is_user_buffer) {162pipe_resource_reference(&vb->buffer.resource, NULL);163vb->is_user_buffer = TRUE;164}165vb->buffer.user = dummy;166}167}168169for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) {170struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[i];171172/* XXX this is odd... */173if (!vb->is_user_buffer && !vb->buffer.resource) {174vb->stride = 0;175vb->buffer_offset = 0;176vb->is_user_buffer = TRUE;177vb->buffer.user = dummy;178}179}180181/* Resubmit old and new vertex buffers.182*/183pipe->set_vertex_buffers(pipe, 0, PIPE_MAX_ATTRIBS, 0, FALSE, pDevice->vertex_buffers);184}185186187/*188* ----------------------------------------------------------------------189*190* IaSetIndexBuffer --191*192* The IaSetIndexBuffer function sets an index buffer for193* an input assembler.194*195* ----------------------------------------------------------------------196*/197198void APIENTRY199IaSetIndexBuffer(D3D10DDI_HDEVICE hDevice, // IN200D3D10DDI_HRESOURCE hBuffer, // IN201DXGI_FORMAT Format, // IN202UINT Offset) // IN203{204LOG_ENTRYPOINT();205206Device *pDevice = CastDevice(hDevice);207struct pipe_resource *resource = CastPipeResource(hBuffer);208209if (resource) {210pDevice->ib_offset = Offset;211212switch (Format) {213case DXGI_FORMAT_R16_UINT:214pDevice->index_size = 2;215pDevice->restart_index = 0xffff;216break;217case DXGI_FORMAT_R32_UINT:218pDevice->restart_index = 0xffffffff;219pDevice->index_size = 4;220break;221default:222assert(0); /* should not happen */223pDevice->index_size = 2;224break;225}226pipe_resource_reference(&pDevice->index_buffer, resource);227} else {228pipe_resource_reference(&pDevice->index_buffer, NULL);229}230}231232233/*234* ----------------------------------------------------------------------235*236* CalcPrivateElementLayoutSize --237*238* The CalcPrivateElementLayoutSize function determines the size239* of the user-mode display driver's private region of memory240* (that is, the size of internal driver structures, not the size241* of the resource video memory) for an element layout.242*243* ----------------------------------------------------------------------244*/245246SIZE_T APIENTRY247CalcPrivateElementLayoutSize(248D3D10DDI_HDEVICE hDevice, // IN249__in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout) // IN250{251return sizeof(ElementLayout);252}253254255/*256* ----------------------------------------------------------------------257*258* CreateElementLayout --259*260* The CreateElementLayout function creates an element layout.261*262* ----------------------------------------------------------------------263*/264265void APIENTRY266CreateElementLayout(267D3D10DDI_HDEVICE hDevice, // IN268__in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout, // IN269D3D10DDI_HELEMENTLAYOUT hElementLayout, // IN270D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout) // IN271{272LOG_ENTRYPOINT();273274struct pipe_context *pipe = CastPipeContext(hDevice);275ElementLayout *pElementLayout = CastElementLayout(hElementLayout);276277struct pipe_vertex_element elements[PIPE_MAX_ATTRIBS];278memset(elements, 0, sizeof elements);279280unsigned num_elements = pCreateElementLayout->NumElements;281unsigned max_elements = 0;282for (unsigned i = 0; i < num_elements; i++) {283const D3D10DDIARG_INPUT_ELEMENT_DESC* pVertexElement =284&pCreateElementLayout->pVertexElements[i];285struct pipe_vertex_element *ve =286&elements[pVertexElement->InputRegister];287288ve->src_offset = pVertexElement->AlignedByteOffset;289ve->vertex_buffer_index = pVertexElement->InputSlot;290ve->src_format = FormatTranslate(pVertexElement->Format, FALSE);291292switch (pVertexElement->InputSlotClass) {293case D3D10_DDI_INPUT_PER_VERTEX_DATA:294ve->instance_divisor = 0;295break;296case D3D10_DDI_INPUT_PER_INSTANCE_DATA:297if (!pVertexElement->InstanceDataStepRate) {298LOG_UNSUPPORTED(!pVertexElement->InstanceDataStepRate);299ve->instance_divisor = ~0;300} else {301ve->instance_divisor = pVertexElement->InstanceDataStepRate;302}303break;304default:305assert(0);306break;307}308309max_elements = MAX2(max_elements, pVertexElement->InputRegister + 1);310}311312/* XXX: What do we do when there's a gap? */313if (max_elements != num_elements) {314DebugPrintf("%s: gap\n", __FUNCTION__);315}316317pElementLayout->handle =318pipe->create_vertex_elements_state(pipe, max_elements, elements);319}320321322/*323* ----------------------------------------------------------------------324*325* DestroyElementLayout --326*327* The DestroyElementLayout function destroys the specified328* element layout object. The element layout object can be329* destoyed only if it is not currently bound to a display device.330*331* ----------------------------------------------------------------------332*/333334void APIENTRY335DestroyElementLayout(D3D10DDI_HDEVICE hDevice, // IN336D3D10DDI_HELEMENTLAYOUT hElementLayout) // IN337{338LOG_ENTRYPOINT();339340struct pipe_context *pipe = CastPipeContext(hDevice);341ElementLayout *pElementLayout = CastElementLayout(hElementLayout);342343pipe->delete_vertex_elements_state(pipe, pElementLayout->handle);}344345346/*347* ----------------------------------------------------------------------348*349* IaSetInputLayout --350*351* The IaSetInputLayout function sets an input layout for352* the input assembler.353*354* ----------------------------------------------------------------------355*/356357void APIENTRY358IaSetInputLayout(D3D10DDI_HDEVICE hDevice, // IN359D3D10DDI_HELEMENTLAYOUT hInputLayout) // IN360{361LOG_ENTRYPOINT();362363struct pipe_context *pipe = CastPipeContext(hDevice);364void *state = CastPipeInputLayout(hInputLayout);365366pipe->bind_vertex_elements_state(pipe, state);367}368369370371372