xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/d3d10umd/InputAssembly.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2012-2021 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20  * USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  **************************************************************************/
27 
28 /*
29  * InputAssembly.cpp --
30  *    Functions that manipulate the input assembly stage.
31  */
32 
33 
34 #include <stdio.h>
35 
36 #include "InputAssembly.h"
37 #include "State.h"
38 
39 #include "Debug.h"
40 #include "Format.h"
41 
42 
43 /*
44  * ----------------------------------------------------------------------
45  *
46  * IaSetTopology --
47  *
48  *    The IaSetTopology function sets the primitive topology to
49  *    enable drawing for the input assember.
50  *
51  * ----------------------------------------------------------------------
52  */
53 
54 void APIENTRY
IaSetTopology(D3D10DDI_HDEVICE hDevice,D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology)55 IaSetTopology(D3D10DDI_HDEVICE hDevice,                        // IN
56               D3D10_DDI_PRIMITIVE_TOPOLOGY PrimitiveTopology)  // IN
57 {
58    LOG_ENTRYPOINT();
59 
60    Device *pDevice = CastDevice(hDevice);
61 
62    enum mesa_prim primitive;
63    switch (PrimitiveTopology) {
64    case D3D10_DDI_PRIMITIVE_TOPOLOGY_UNDEFINED:
65       /* Apps might set topology to UNDEFINED when cleaning up on exit. */
66       primitive = MESA_PRIM_COUNT;
67       break;
68    case D3D10_DDI_PRIMITIVE_TOPOLOGY_POINTLIST:
69       primitive = MESA_PRIM_POINTS;
70       break;
71    case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST:
72       primitive = MESA_PRIM_LINES;
73       break;
74    case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP:
75       primitive = MESA_PRIM_LINE_STRIP;
76       break;
77    case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST:
78       primitive = MESA_PRIM_TRIANGLES;
79       break;
80    case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP:
81       primitive = MESA_PRIM_TRIANGLE_STRIP;
82       break;
83    case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINELIST_ADJ:
84       primitive = MESA_PRIM_LINES_ADJACENCY;
85       break;
86    case D3D10_DDI_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ:
87       primitive = MESA_PRIM_LINE_STRIP_ADJACENCY;
88       break;
89    case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ:
90       primitive = MESA_PRIM_TRIANGLES_ADJACENCY;
91       break;
92    case D3D10_DDI_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ:
93       primitive = MESA_PRIM_TRIANGLE_STRIP_ADJACENCY;
94       break;
95    default:
96       assert(0);
97       primitive = MESA_PRIM_COUNT;
98       break;
99    }
100 
101    pDevice->primitive = primitive;
102 }
103 
104 
105 /*
106  * ----------------------------------------------------------------------
107  *
108  * IaSetVertexBuffers --
109  *
110  *    The IaSetVertexBuffers function sets vertex buffers
111  *    for an input assembler.
112  *
113  * ----------------------------------------------------------------------
114  */
115 
116 void APIENTRY
IaSetVertexBuffers(D3D10DDI_HDEVICE hDevice,UINT StartBuffer,UINT NumBuffers,__in_ecount (NumBuffers)const D3D10DDI_HRESOURCE * phBuffers,__in_ecount (NumBuffers)const UINT * pStrides,__in_ecount (NumBuffers)const UINT * pOffsets)117 IaSetVertexBuffers(D3D10DDI_HDEVICE hDevice,                                     // IN
118                    UINT StartBuffer,                                             // IN
119                    UINT NumBuffers,                                              // IN
120                    __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers, // IN
121                    __in_ecount (NumBuffers) const UINT *pStrides,                // IN
122                    __in_ecount (NumBuffers) const UINT *pOffsets)                // IN
123 {
124    static const float dummy[4] = {0.0f, 0.0f, 0.0f, 0.0f};
125 
126    LOG_ENTRYPOINT();
127 
128    Device *pDevice = CastDevice(hDevice);
129    unsigned i;
130 
131    for (i = 0; i < NumBuffers; i++) {
132       struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[StartBuffer + i];
133       struct pipe_resource *resource = CastPipeResource(phBuffers[i]);
134       Resource *res = CastResource(phBuffers[i]);
135       struct pipe_stream_output_target *so_target =
136          res ? res->so_target : NULL;
137 
138       if (so_target && pDevice->draw_so_target != so_target) {
139          if (pDevice->draw_so_target) {
140             pipe_so_target_reference(&pDevice->draw_so_target, NULL);
141          }
142          pipe_so_target_reference(&pDevice->draw_so_target,
143                                   so_target);
144       }
145 
146       if (resource) {
147          pDevice->vertex_strides[StartBuffer + i] = pStrides[i];
148          vb->buffer_offset = pOffsets[i];
149          if (vb->is_user_buffer) {
150             vb->buffer.resource = NULL;
151             vb->is_user_buffer = false;
152          }
153          pipe_resource_reference(&vb->buffer.resource, resource);
154       }
155       else {
156          pDevice->vertex_strides[StartBuffer + i] = 0;
157          vb->buffer_offset = 0;
158          if (!vb->is_user_buffer) {
159             pipe_resource_reference(&vb->buffer.resource, NULL);
160             vb->is_user_buffer = true;
161          }
162          vb->buffer.user = dummy;
163       }
164    }
165 
166    for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) {
167       struct pipe_vertex_buffer *vb = &pDevice->vertex_buffers[i];
168 
169       /* XXX this is odd... */
170       if (!vb->is_user_buffer && !vb->buffer.resource) {
171          pDevice->vertex_strides[i] = 0;
172          vb->buffer_offset = 0;
173          vb->is_user_buffer = true;
174          vb->buffer.user = dummy;
175       }
176    }
177 
178    /* Resubmit old and new vertex buffers.
179     */
180    pDevice->velems_changed = true;
181    pDevice->vbuffers_changed = true;
182 }
183 
184 
185 /*
186  * ----------------------------------------------------------------------
187  *
188  * IaSetIndexBuffer --
189  *
190  *    The IaSetIndexBuffer function sets an index buffer for
191  *    an input assembler.
192  *
193  * ----------------------------------------------------------------------
194  */
195 
196 void APIENTRY
IaSetIndexBuffer(D3D10DDI_HDEVICE hDevice,D3D10DDI_HRESOURCE hBuffer,DXGI_FORMAT Format,UINT Offset)197 IaSetIndexBuffer(D3D10DDI_HDEVICE hDevice,   // IN
198                  D3D10DDI_HRESOURCE hBuffer, // IN
199                  DXGI_FORMAT Format,         // IN
200                  UINT Offset)                // IN
201 {
202    LOG_ENTRYPOINT();
203 
204    Device *pDevice = CastDevice(hDevice);
205    struct pipe_resource *resource = CastPipeResource(hBuffer);
206 
207    if (resource) {
208       pDevice->ib_offset = Offset;
209 
210       switch (Format) {
211       case DXGI_FORMAT_R16_UINT:
212          pDevice->index_size = 2;
213          pDevice->restart_index = 0xffff;
214          break;
215       case DXGI_FORMAT_R32_UINT:
216          pDevice->restart_index = 0xffffffff;
217          pDevice->index_size = 4;
218          break;
219       default:
220          assert(0);             /* should not happen */
221          pDevice->index_size = 2;
222          break;
223       }
224       pipe_resource_reference(&pDevice->index_buffer, resource);
225    } else {
226       pipe_resource_reference(&pDevice->index_buffer, NULL);
227    }
228 }
229 
230 
231 /*
232  * ----------------------------------------------------------------------
233  *
234  * CalcPrivateElementLayoutSize --
235  *
236  *    The CalcPrivateElementLayoutSize function determines the size
237  *    of the user-mode display driver's private region of memory
238  *    (that is, the size of internal driver structures, not the size
239  *    of the resource video memory) for an element layout.
240  *
241  * ----------------------------------------------------------------------
242  */
243 
244 SIZE_T APIENTRY
CalcPrivateElementLayoutSize(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATEELEMENTLAYOUT * pCreateElementLayout)245 CalcPrivateElementLayoutSize(
246    D3D10DDI_HDEVICE hDevice,                                         // IN
247    __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout) // IN
248 {
249    return sizeof(ElementLayout);
250 }
251 
252 
253 /*
254  * ----------------------------------------------------------------------
255  *
256  * CreateElementLayout --
257  *
258  *    The CreateElementLayout function creates an element layout.
259  *
260  * ----------------------------------------------------------------------
261  */
262 
263 void APIENTRY
CreateElementLayout(D3D10DDI_HDEVICE hDevice,__in const D3D10DDIARG_CREATEELEMENTLAYOUT * pCreateElementLayout,D3D10DDI_HELEMENTLAYOUT hElementLayout,D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout)264 CreateElementLayout(
265    D3D10DDI_HDEVICE hDevice,                                         // IN
266    __in const D3D10DDIARG_CREATEELEMENTLAYOUT *pCreateElementLayout, // IN
267    D3D10DDI_HELEMENTLAYOUT hElementLayout,                           // IN
268    D3D10DDI_HRTELEMENTLAYOUT hRTElementLayout)                       // IN
269 {
270    LOG_ENTRYPOINT();
271 
272    ElementLayout *pElementLayout = CastElementLayout(hElementLayout);
273    memset(pElementLayout, 0, sizeof *pElementLayout);
274 
275    unsigned num_elements = pCreateElementLayout->NumElements;
276    unsigned max_elements = 0;
277    for (unsigned i = 0; i < num_elements; i++) {
278       const D3D10DDIARG_INPUT_ELEMENT_DESC* pVertexElement =
279             &pCreateElementLayout->pVertexElements[i];
280       struct pipe_vertex_element *ve =
281             &pElementLayout->state.velems[pVertexElement->InputRegister];
282 
283       ve->src_offset          = pVertexElement->AlignedByteOffset;
284       ve->vertex_buffer_index = pVertexElement->InputSlot;
285       ve->src_format          = FormatTranslate(pVertexElement->Format, false);
286 
287       switch (pVertexElement->InputSlotClass) {
288       case D3D10_DDI_INPUT_PER_VERTEX_DATA:
289          ve->instance_divisor = 0;
290          break;
291       case D3D10_DDI_INPUT_PER_INSTANCE_DATA:
292          if (!pVertexElement->InstanceDataStepRate) {
293             LOG_UNSUPPORTED(!pVertexElement->InstanceDataStepRate);
294             ve->instance_divisor = ~0;
295          } else {
296             ve->instance_divisor = pVertexElement->InstanceDataStepRate;
297          }
298          break;
299       default:
300          assert(0);
301          break;
302       }
303 
304       max_elements = MAX2(max_elements, pVertexElement->InputRegister + 1);
305    }
306 
307    /* XXX: What do we do when there's a gap? */
308    if (max_elements != num_elements) {
309       DebugPrintf("%s: gap\n", __func__);
310    }
311 
312    pElementLayout->state.count = max_elements;
313 }
314 
315 
316 /*
317  * ----------------------------------------------------------------------
318  *
319  * DestroyElementLayout --
320  *
321  *    The DestroyElementLayout function destroys the specified
322  *    element layout object. The element layout object can be
323  *    destoyed only if it is not currently bound to a display device.
324  *
325  * ----------------------------------------------------------------------
326  */
327 
328 void APIENTRY
DestroyElementLayout(D3D10DDI_HDEVICE hDevice,D3D10DDI_HELEMENTLAYOUT hElementLayout)329 DestroyElementLayout(D3D10DDI_HDEVICE hDevice,                 // IN
330                      D3D10DDI_HELEMENTLAYOUT hElementLayout)   // IN
331 {
332    LOG_ENTRYPOINT();
333 
334 }
335 
336 
337 /*
338  * ----------------------------------------------------------------------
339  *
340  * IaSetInputLayout --
341  *
342  *    The IaSetInputLayout function sets an input layout for
343  *    the input assembler.
344  *
345  * ----------------------------------------------------------------------
346  */
347 
348 void APIENTRY
IaSetInputLayout(D3D10DDI_HDEVICE hDevice,D3D10DDI_HELEMENTLAYOUT hInputLayout)349 IaSetInputLayout(D3D10DDI_HDEVICE hDevice,               // IN
350                  D3D10DDI_HELEMENTLAYOUT hInputLayout)   // IN
351 {
352    LOG_ENTRYPOINT();
353 
354    Device *pDevice = CastDevice(hDevice);
355    pDevice->element_layout = CastElementLayout(hInputLayout);
356    pDevice->velems_changed = true;
357 
358 }
359