17ec681f3Smrg/************************************************************************** 27ec681f3Smrg * 37ec681f3Smrg * Copyright 2012-2021 VMware, Inc. 47ec681f3Smrg * All Rights Reserved. 57ec681f3Smrg * 67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77ec681f3Smrg * copy of this software and associated documentation files (the 87ec681f3Smrg * "Software"), to deal in the Software without restriction, including 97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish, 107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to 117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to 127ec681f3Smrg * the following conditions: 137ec681f3Smrg * 147ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 187ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 197ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 207ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 217ec681f3Smrg * 227ec681f3Smrg * The above copyright notice and this permission notice (including the 237ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions 247ec681f3Smrg * of the Software. 257ec681f3Smrg * 267ec681f3Smrg **************************************************************************/ 277ec681f3Smrg 287ec681f3Smrg/* 297ec681f3Smrg * InputAssembly.cpp -- 307ec681f3Smrg * Functions that manipulate the input assembly stage. 317ec681f3Smrg */ 327ec681f3Smrg 337ec681f3Smrg 347ec681f3Smrg#include <stdio.h> 357ec681f3Smrg#if defined(_MSC_VER) && !defined(snprintf) 367ec681f3Smrg#define snprintf _snprintf 377ec681f3Smrg#endif 387ec681f3Smrg 397ec681f3Smrg#include "InputAssembly.h" 407ec681f3Smrg#include "State.h" 417ec681f3Smrg 427ec681f3Smrg#include "Debug.h" 437ec681f3Smrg#include "Format.h" 447ec681f3Smrg 457ec681f3Smrg 467ec681f3Smrg/* 477ec681f3Smrg * ---------------------------------------------------------------------- 487ec681f3Smrg * 497ec681f3Smrg * IaSetTopology -- 507ec681f3Smrg * 517ec681f3Smrg * The IaSetTopology function sets the primitive topology to 527ec681f3Smrg * enable drawing for the input assember. 537ec681f3Smrg * 547ec681f3Smrg * ---------------------------------------------------------------------- 557ec681f3Smrg */ 567ec681f3Smrg 577ec681f3Smrgvoid APIENTRY 587ec681f3SmrgIaSetTopology(D3D10DDI_HDEVICE hDevice, // IN 597ec681f3Smrg D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology) // IN 607ec681f3Smrg{ 617ec681f3Smrg LOG_ENTRYPOINT(); 627ec681f3Smrg 637ec681f3Smrg Device *pDevice = CastDevice(hDevice); 647ec681f3Smrg 657ec681f3Smrg enum pipe_prim_type primitive; 667ec681f3Smrg switch (PrimitiveTopology) { 677ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_UNDEFINED: 687ec681f3Smrg /* Apps might set topology to UNDEFINED when cleaning up on exit. */ 697ec681f3Smrg primitive = PIPE_PRIM_MAX; 707ec681f3Smrg break; 717ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_POINTLIST: 727ec681f3Smrg primitive = PIPE_PRIM_POINTS; 737ec681f3Smrg break; 747ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST: 757ec681f3Smrg primitive = PIPE_PRIM_LINES; 767ec681f3Smrg break; 777ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP: 787ec681f3Smrg primitive = PIPE_PRIM_LINE_STRIP; 797ec681f3Smrg break; 807ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST: 817ec681f3Smrg primitive = PIPE_PRIM_TRIANGLES; 827ec681f3Smrg break; 837ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: 847ec681f3Smrg primitive = PIPE_PRIM_TRIANGLE_STRIP; 857ec681f3Smrg break; 867ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST_ADJ: 877ec681f3Smrg primitive = PIPE_PRIM_LINES_ADJACENCY; 887ec681f3Smrg break; 897ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: 907ec681f3Smrg primitive = PIPE_PRIM_LINE_STRIP_ADJACENCY; 917ec681f3Smrg break; 927ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: 937ec681f3Smrg primitive = PIPE_PRIM_TRIANGLES_ADJACENCY; 947ec681f3Smrg break; 957ec681f3Smrg case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: 967ec681f3Smrg primitive = PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY; 977ec681f3Smrg break; 987ec681f3Smrg default: 997ec681f3Smrg assert(0); 1007ec681f3Smrg primitive = PIPE_PRIM_MAX; 1017ec681f3Smrg break; 1027ec681f3Smrg } 1037ec681f3Smrg 1047ec681f3Smrg pDevice->primitive = primitive; 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrg 1087ec681f3Smrg/* 1097ec681f3Smrg * ---------------------------------------------------------------------- 1107ec681f3Smrg * 1117ec681f3Smrg * IaSetVertexBuffers -- 1127ec681f3Smrg * 1137ec681f3Smrg * The IaSetVertexBuffers function sets vertex buffers 1147ec681f3Smrg * for an input assembler. 1157ec681f3Smrg * 1167ec681f3Smrg * ---------------------------------------------------------------------- 1177ec681f3Smrg */ 1187ec681f3Smrg 1197ec681f3Smrgvoid APIENTRY 1207ec681f3SmrgIaSetVertexBuffers(D3D10DDI_HDEVICE hDevice, // IN 1217ec681f3Smrg UINT StartBuffer, // IN 1227ec681f3Smrg UINT NumBuffers, // IN 1237ec681f3Smrg __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers, // IN 1247ec681f3Smrg __in_ecount (NumBuffers) const UINT *pStrides, // IN 1257ec681f3Smrg __in_ecount (NumBuffers) const UINT *pOffsets) // IN 1267ec681f3Smrg{ 1277ec681f3Smrg static const float dummy[4] = {0.0f, 0.0f, 0.0f, 0.0f}; 1287ec681f3Smrg 1297ec681f3Smrg LOG_ENTRYPOINT(); 1307ec681f3Smrg 1317ec681f3Smrg Device *pDevice = CastDevice(hDevice); 1327ec681f3Smrg struct pipe_context *pipe = pDevice->pipe; 1337ec681f3Smrg unsigned i; 1347ec681f3Smrg 1357ec681f3Smrg for (i = 0; i < NumBuffers; i++) { 1367ec681f3Smrg struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[StartBuffer + i]; 1377ec681f3Smrg struct pipe_resource *resource = CastPipeResource(phBuffers[i]); 1387ec681f3Smrg Resource *res = CastResource(phBuffers[i]); 1397ec681f3Smrg struct pipe_stream_output_target *so_target = 1407ec681f3Smrg res ? res->so_target : NULL; 1417ec681f3Smrg 1427ec681f3Smrg if (so_target && pDevice->draw_so_target != so_target) { 1437ec681f3Smrg if (pDevice->draw_so_target) { 1447ec681f3Smrg pipe_so_target_reference(&pDevice->draw_so_target, NULL); 1457ec681f3Smrg } 1467ec681f3Smrg pipe_so_target_reference(&pDevice->draw_so_target, 1477ec681f3Smrg so_target); 1487ec681f3Smrg } 1497ec681f3Smrg 1507ec681f3Smrg if (resource) { 1517ec681f3Smrg vb->stride = pStrides[i]; 1527ec681f3Smrg vb->buffer_offset = pOffsets[i]; 1537ec681f3Smrg if (vb->is_user_buffer) { 1547ec681f3Smrg vb->buffer.resource = NULL; 1557ec681f3Smrg vb->is_user_buffer = FALSE; 1567ec681f3Smrg } 1577ec681f3Smrg pipe_resource_reference(&vb->buffer.resource, resource); 1587ec681f3Smrg } 1597ec681f3Smrg else { 1607ec681f3Smrg vb->stride = 0; 1617ec681f3Smrg vb->buffer_offset = 0; 1627ec681f3Smrg if (!vb->is_user_buffer) { 1637ec681f3Smrg pipe_resource_reference(&vb->buffer.resource, NULL); 1647ec681f3Smrg vb->is_user_buffer = TRUE; 1657ec681f3Smrg } 1667ec681f3Smrg vb->buffer.user = dummy; 1677ec681f3Smrg } 1687ec681f3Smrg } 1697ec681f3Smrg 1707ec681f3Smrg for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) { 1717ec681f3Smrg struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[i]; 1727ec681f3Smrg 1737ec681f3Smrg /* XXX this is odd... */ 1747ec681f3Smrg if (!vb->is_user_buffer && !vb->buffer.resource) { 1757ec681f3Smrg vb->stride = 0; 1767ec681f3Smrg vb->buffer_offset = 0; 1777ec681f3Smrg vb->is_user_buffer = TRUE; 1787ec681f3Smrg vb->buffer.user = dummy; 1797ec681f3Smrg } 1807ec681f3Smrg } 1817ec681f3Smrg 1827ec681f3Smrg /* Resubmit old and new vertex buffers. 1837ec681f3Smrg */ 1847ec681f3Smrg pipe->set_vertex_buffers(pipe, 0, PIPE_MAX_ATTRIBS, 0, FALSE, pDevice->vertex_buffers); 1857ec681f3Smrg} 1867ec681f3Smrg 1877ec681f3Smrg 1887ec681f3Smrg/* 1897ec681f3Smrg * ---------------------------------------------------------------------- 1907ec681f3Smrg * 1917ec681f3Smrg * IaSetIndexBuffer -- 1927ec681f3Smrg * 1937ec681f3Smrg * The IaSetIndexBuffer function sets an index buffer for 1947ec681f3Smrg * an input assembler. 1957ec681f3Smrg * 1967ec681f3Smrg * ---------------------------------------------------------------------- 1977ec681f3Smrg */ 1987ec681f3Smrg 1997ec681f3Smrgvoid APIENTRY 2007ec681f3SmrgIaSetIndexBuffer(D3D10DDI_HDEVICE hDevice, // IN 2017ec681f3Smrg D3D10DDI_HRESOURCE hBuffer, // IN 2027ec681f3Smrg DXGI_FORMAT Format, // IN 2037ec681f3Smrg UINT Offset) // IN 2047ec681f3Smrg{ 2057ec681f3Smrg LOG_ENTRYPOINT(); 2067ec681f3Smrg 2077ec681f3Smrg Device *pDevice = CastDevice(hDevice); 2087ec681f3Smrg struct pipe_resource *resource = CastPipeResource(hBuffer); 2097ec681f3Smrg 2107ec681f3Smrg if (resource) { 2117ec681f3Smrg pDevice->ib_offset = Offset; 2127ec681f3Smrg 2137ec681f3Smrg switch (Format) { 2147ec681f3Smrg case DXGI_FORMAT_R16_UINT: 2157ec681f3Smrg pDevice->index_size = 2; 2167ec681f3Smrg pDevice->restart_index = 0xffff; 2177ec681f3Smrg break; 2187ec681f3Smrg case DXGI_FORMAT_R32_UINT: 2197ec681f3Smrg pDevice->restart_index = 0xffffffff; 2207ec681f3Smrg pDevice->index_size = 4; 2217ec681f3Smrg break; 2227ec681f3Smrg default: 2237ec681f3Smrg assert(0); /* should not happen */ 2247ec681f3Smrg pDevice->index_size = 2; 2257ec681f3Smrg break; 2267ec681f3Smrg } 2277ec681f3Smrg pipe_resource_reference(&pDevice->index_buffer, resource); 2287ec681f3Smrg } else { 2297ec681f3Smrg pipe_resource_reference(&pDevice->index_buffer, NULL); 2307ec681f3Smrg } 2317ec681f3Smrg} 2327ec681f3Smrg 2337ec681f3Smrg 2347ec681f3Smrg/* 2357ec681f3Smrg * ---------------------------------------------------------------------- 2367ec681f3Smrg * 2377ec681f3Smrg * CalcPrivateElementLayoutSize -- 2387ec681f3Smrg * 2397ec681f3Smrg * The CalcPrivateElementLayoutSize function determines the size 2407ec681f3Smrg * of the user-mode display driver's private region of memory 2417ec681f3Smrg * (that is, the size of internal driver structures, not the size 2427ec681f3Smrg * of the resource video memory) for an element layout. 2437ec681f3Smrg * 2447ec681f3Smrg * ---------------------------------------------------------------------- 2457ec681f3Smrg */ 2467ec681f3Smrg 2477ec681f3SmrgSIZE_T APIENTRY 2487ec681f3SmrgCalcPrivateElementLayoutSize( 2497ec681f3Smrg D3D10DDI_HDEVICE hDevice, // IN 2507ec681f3Smrg __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout) // IN 2517ec681f3Smrg{ 2527ec681f3Smrg return sizeof(ElementLayout); 2537ec681f3Smrg} 2547ec681f3Smrg 2557ec681f3Smrg 2567ec681f3Smrg/* 2577ec681f3Smrg * ---------------------------------------------------------------------- 2587ec681f3Smrg * 2597ec681f3Smrg * CreateElementLayout -- 2607ec681f3Smrg * 2617ec681f3Smrg * The CreateElementLayout function creates an element layout. 2627ec681f3Smrg * 2637ec681f3Smrg * ---------------------------------------------------------------------- 2647ec681f3Smrg */ 2657ec681f3Smrg 2667ec681f3Smrgvoid APIENTRY 2677ec681f3SmrgCreateElementLayout( 2687ec681f3Smrg D3D10DDI_HDEVICE hDevice, // IN 2697ec681f3Smrg __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout, // IN 2707ec681f3Smrg D3D10DDI_HELEMENTLAYOUT hElementLayout, // IN 2717ec681f3Smrg D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout) // IN 2727ec681f3Smrg{ 2737ec681f3Smrg LOG_ENTRYPOINT(); 2747ec681f3Smrg 2757ec681f3Smrg struct pipe_context *pipe = CastPipeContext(hDevice); 2767ec681f3Smrg ElementLayout *pElementLayout = CastElementLayout(hElementLayout); 2777ec681f3Smrg 2787ec681f3Smrg struct pipe_vertex_element elements[PIPE_MAX_ATTRIBS]; 2797ec681f3Smrg memset(elements, 0, sizeof elements); 2807ec681f3Smrg 2817ec681f3Smrg unsigned num_elements = pCreateElementLayout->NumElements; 2827ec681f3Smrg unsigned max_elements = 0; 2837ec681f3Smrg for (unsigned i = 0; i < num_elements; i++) { 2847ec681f3Smrg const D3D10DDIARG_INPUT_ELEMENT_DESC* pVertexElement = 2857ec681f3Smrg &pCreateElementLayout->pVertexElements[i]; 2867ec681f3Smrg struct pipe_vertex_element *ve = 2877ec681f3Smrg &elements[pVertexElement->InputRegister]; 2887ec681f3Smrg 2897ec681f3Smrg ve->src_offset = pVertexElement->AlignedByteOffset; 2907ec681f3Smrg ve->vertex_buffer_index = pVertexElement->InputSlot; 2917ec681f3Smrg ve->src_format = FormatTranslate(pVertexElement->Format, FALSE); 2927ec681f3Smrg 2937ec681f3Smrg switch (pVertexElement->InputSlotClass) { 2947ec681f3Smrg case D3D10_DDI_INPUT_PER_VERTEX_DATA: 2957ec681f3Smrg ve->instance_divisor = 0; 2967ec681f3Smrg break; 2977ec681f3Smrg case D3D10_DDI_INPUT_PER_INSTANCE_DATA: 2987ec681f3Smrg if (!pVertexElement->InstanceDataStepRate) { 2997ec681f3Smrg LOG_UNSUPPORTED(!pVertexElement->InstanceDataStepRate); 3007ec681f3Smrg ve->instance_divisor = ~0; 3017ec681f3Smrg } else { 3027ec681f3Smrg ve->instance_divisor = pVertexElement->InstanceDataStepRate; 3037ec681f3Smrg } 3047ec681f3Smrg break; 3057ec681f3Smrg default: 3067ec681f3Smrg assert(0); 3077ec681f3Smrg break; 3087ec681f3Smrg } 3097ec681f3Smrg 3107ec681f3Smrg max_elements = MAX2(max_elements, pVertexElement->InputRegister + 1); 3117ec681f3Smrg } 3127ec681f3Smrg 3137ec681f3Smrg /* XXX: What do we do when there's a gap? */ 3147ec681f3Smrg if (max_elements != num_elements) { 3157ec681f3Smrg DebugPrintf("%s: gap\n", __FUNCTION__); 3167ec681f3Smrg } 3177ec681f3Smrg 3187ec681f3Smrg pElementLayout->handle = 3197ec681f3Smrg pipe->create_vertex_elements_state(pipe, max_elements, elements); 3207ec681f3Smrg} 3217ec681f3Smrg 3227ec681f3Smrg 3237ec681f3Smrg/* 3247ec681f3Smrg * ---------------------------------------------------------------------- 3257ec681f3Smrg * 3267ec681f3Smrg * DestroyElementLayout -- 3277ec681f3Smrg * 3287ec681f3Smrg * The DestroyElementLayout function destroys the specified 3297ec681f3Smrg * element layout object. The element layout object can be 3307ec681f3Smrg * destoyed only if it is not currently bound to a display device. 3317ec681f3Smrg * 3327ec681f3Smrg * ---------------------------------------------------------------------- 3337ec681f3Smrg */ 3347ec681f3Smrg 3357ec681f3Smrgvoid APIENTRY 3367ec681f3SmrgDestroyElementLayout(D3D10DDI_HDEVICE hDevice, // IN 3377ec681f3Smrg D3D10DDI_HELEMENTLAYOUT hElementLayout) // IN 3387ec681f3Smrg{ 3397ec681f3Smrg LOG_ENTRYPOINT(); 3407ec681f3Smrg 3417ec681f3Smrg struct pipe_context *pipe = CastPipeContext(hDevice); 3427ec681f3Smrg ElementLayout *pElementLayout = CastElementLayout(hElementLayout); 3437ec681f3Smrg 3447ec681f3Smrg pipe->delete_vertex_elements_state(pipe, pElementLayout->handle);} 3457ec681f3Smrg 3467ec681f3Smrg 3477ec681f3Smrg/* 3487ec681f3Smrg * ---------------------------------------------------------------------- 3497ec681f3Smrg * 3507ec681f3Smrg * IaSetInputLayout -- 3517ec681f3Smrg * 3527ec681f3Smrg * The IaSetInputLayout function sets an input layout for 3537ec681f3Smrg * the input assembler. 3547ec681f3Smrg * 3557ec681f3Smrg * ---------------------------------------------------------------------- 3567ec681f3Smrg */ 3577ec681f3Smrg 3587ec681f3Smrgvoid APIENTRY 3597ec681f3SmrgIaSetInputLayout(D3D10DDI_HDEVICE hDevice, // IN 3607ec681f3Smrg D3D10DDI_HELEMENTLAYOUT hInputLayout) // IN 3617ec681f3Smrg{ 3627ec681f3Smrg LOG_ENTRYPOINT(); 3637ec681f3Smrg 3647ec681f3Smrg struct pipe_context *pipe = CastPipeContext(hDevice); 3657ec681f3Smrg void *state = CastPipeInputLayout(hInputLayout); 3667ec681f3Smrg 3677ec681f3Smrg pipe->bind_vertex_elements_state(pipe, state); 3687ec681f3Smrg} 3697ec681f3Smrg 3707ec681f3Smrg 371