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 * Rasterizer.cpp --
30 *    Functions that manipulate rasterizer state.
31 */
32
33
34#include "Rasterizer.h"
35#include "State.h"
36
37#include "Debug.h"
38
39
40/*
41 * ----------------------------------------------------------------------
42 *
43 * SetViewports --
44 *
45 *    The SetViewports function sets viewports.
46 *
47 * ----------------------------------------------------------------------
48 */
49
50void APIENTRY
51SetViewports(D3D10DDI_HDEVICE hDevice,                                        // IN
52             UINT NumViewports,                                               // IN
53             UINT ClearViewports,                                             // IN
54             __in_ecount (NumViewports) const D3D10_DDI_VIEWPORT *pViewports) // IN
55{
56   LOG_ENTRYPOINT();
57
58   struct pipe_context *pipe = CastPipeContext(hDevice);
59   struct pipe_viewport_state states[PIPE_MAX_VIEWPORTS];
60
61   ASSERT(NumViewports + ClearViewports <=
62          D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE);
63
64   for (UINT i = 0; i < NumViewports; ++i) {
65      const D3D10_DDI_VIEWPORT *pViewport = &pViewports[i];
66      float width = pViewport->Width;
67      float height = pViewport->Height;
68      float x = pViewport->TopLeftX;
69      float y = pViewport->TopLeftY;
70      float z = pViewport->MinDepth;
71      float half_width = width / 2.0f;
72      float half_height = height / 2.0f;
73      float depth = pViewport->MaxDepth - z;
74
75      states[i].scale[0] = half_width;
76      states[i].scale[1] = -half_height;
77      states[i].scale[2] = depth;
78
79      states[i].translate[0] = half_width + x;
80      states[i].translate[1] = half_height + y;
81      states[i].translate[2] = z;
82   }
83   if (ClearViewports) {
84      memset(states + NumViewports, 0,
85             sizeof(struct pipe_viewport_state) * ClearViewports);
86   }
87   pipe->set_viewport_states(pipe, 0, NumViewports + ClearViewports,
88                             states);
89}
90
91
92/*
93 * ----------------------------------------------------------------------
94 *
95 * SetScissorRects --
96 *
97 *    The SetScissorRects function marks portions of render targets
98 *    that rendering is confined to.
99 *
100 * ----------------------------------------------------------------------
101 */
102
103void APIENTRY
104SetScissorRects(D3D10DDI_HDEVICE hDevice,                            // IN
105                UINT NumScissorRects,                                // IN
106                UINT ClearScissorRects,                              // IN
107                __in_ecount (NumRects) const D3D10_DDI_RECT *pRects) // IN
108{
109   LOG_ENTRYPOINT();
110
111   struct pipe_context *pipe = CastPipeContext(hDevice);
112   struct pipe_scissor_state states[PIPE_MAX_VIEWPORTS];
113
114   ASSERT(NumScissorRects + ClearScissorRects <=
115          D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE);
116
117   for (UINT i = 0; i < NumScissorRects; ++i) {
118      const D3D10_DDI_RECT *pRect = &pRects[i];
119      /* gallium scissor values are unsigned so lets make
120      * sure that we don't overflow */
121      states[i].minx = pRect->left   < 0 ? 0 : pRect->left;
122      states[i].miny = pRect->top    < 0 ? 0 : pRect->top;
123      states[i].maxx = pRect->right  < 0 ? 0 : pRect->right;
124      states[i].maxy = pRect->bottom < 0 ? 0 : pRect->bottom;
125   }
126   if (ClearScissorRects) {
127      memset(states + NumScissorRects, 0,
128             sizeof(struct pipe_scissor_state) * ClearScissorRects);
129   }
130   pipe->set_scissor_states(pipe, 0, NumScissorRects + ClearScissorRects,
131                            states);
132}
133
134
135/*
136 * ----------------------------------------------------------------------
137 *
138 * CalcPrivateRasterizerStateSize --
139 *
140 *    The CalcPrivateRasterizerStateSize function determines the size
141 *    of the user-mode display driver's private region of memory
142 *    (that is, the size of internal driver structures, not the size
143 *    of the resource video memory) for a rasterizer state.
144 *
145 * ----------------------------------------------------------------------
146 */
147
148SIZE_T APIENTRY
149CalcPrivateRasterizerStateSize(
150   D3D10DDI_HDEVICE hDevice,                                // IN
151   __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc)   // IN
152{
153   return sizeof(RasterizerState);
154}
155
156
157static uint
158translate_cull_mode(D3D10_DDI_CULL_MODE CullMode)
159{
160   switch (CullMode) {
161   case D3D10_DDI_CULL_NONE:
162      return PIPE_FACE_NONE;
163   case D3D10_DDI_CULL_FRONT:
164      return PIPE_FACE_FRONT;
165   case D3D10_DDI_CULL_BACK:
166      return PIPE_FACE_BACK;
167   default:
168      assert(0);
169      return PIPE_FACE_NONE;
170   }
171}
172
173static uint
174translate_fill_mode(D3D10_DDI_FILL_MODE FillMode)
175{
176   switch (FillMode) {
177   case D3D10_DDI_FILL_WIREFRAME:
178      return PIPE_POLYGON_MODE_LINE;
179   case D3D10_DDI_FILL_SOLID:
180      return PIPE_POLYGON_MODE_FILL;
181   default:
182      assert(0);
183      return PIPE_POLYGON_MODE_FILL;
184   }
185}
186
187
188/*
189 * ----------------------------------------------------------------------
190 *
191 * CreateRasterizerState --
192 *
193 *    The CreateRasterizerState function creates a rasterizer state.
194 *
195 * ----------------------------------------------------------------------
196 */
197
198void APIENTRY
199CreateRasterizerState(
200    D3D10DDI_HDEVICE hDevice,                               // IN
201    __in const D3D10_DDI_RASTERIZER_DESC *pRasterizerDesc,  // IN
202    D3D10DDI_HRASTERIZERSTATE hRasterizerState,             // IN
203    D3D10DDI_HRTRASTERIZERSTATE hRTRasterizerState)         // IN
204{
205   LOG_ENTRYPOINT();
206
207   struct pipe_context *pipe = CastPipeContext(hDevice);
208   RasterizerState *pRasterizerState = CastRasterizerState(hRasterizerState);
209
210   struct pipe_rasterizer_state state;
211   memset(&state, 0, sizeof state);
212
213   state.flatshade_first = 1;
214   state.front_ccw = (pRasterizerDesc->FrontCounterClockwise ? 1 : 0);
215   state.cull_face = translate_cull_mode(pRasterizerDesc->CullMode);
216   state.fill_front = translate_fill_mode(pRasterizerDesc->FillMode);
217   state.fill_back = state.fill_front;
218   state.scissor = (pRasterizerDesc->ScissorEnable ? 1 : 0);
219   state.line_smooth = (pRasterizerDesc->AntialiasedLineEnable ? 1 : 0);
220   state.offset_units = (float)pRasterizerDesc->DepthBias;
221   state.offset_scale = pRasterizerDesc->SlopeScaledDepthBias;
222   state.offset_clamp = pRasterizerDesc->DepthBiasClamp;
223   state.multisample = /* pRasterizerDesc->MultisampleEnable */ 0;
224   state.half_pixel_center = 1;
225   state.bottom_edge_rule = 0;
226   state.clip_halfz = 1;
227   state.depth_clip_near = pRasterizerDesc->DepthClipEnable ? 1 : 0;
228   state.depth_clip_far = pRasterizerDesc->DepthClipEnable ? 1 : 0;
229   state.depth_clamp = 1;
230
231   state.point_quad_rasterization = 1;
232   state.point_size = 1.0f;
233   state.point_tri_clip = 1;
234
235   state.line_width = 1.0f;
236   state.line_rectangular = 0;
237
238   pRasterizerState->handle = pipe->create_rasterizer_state(pipe, &state);
239}
240
241
242/*
243 * ----------------------------------------------------------------------
244 *
245 * DestroyRasterizerState --
246 *
247 *    The DestroyRasterizerState function destroys the specified
248 *    rasterizer state object. The rasterizer state object can be
249 *    destoyed only if it is not currently bound to a display device.
250 *
251 * ----------------------------------------------------------------------
252 */
253
254void APIENTRY
255DestroyRasterizerState(D3D10DDI_HDEVICE hDevice,                     // IN
256                       D3D10DDI_HRASTERIZERSTATE hRasterizerState)   // IN
257{
258   LOG_ENTRYPOINT();
259
260   struct pipe_context *pipe = CastPipeContext(hDevice);
261   RasterizerState *pRasterizerState = CastRasterizerState(hRasterizerState);
262
263   pipe->delete_rasterizer_state(pipe, pRasterizerState->handle);
264}
265
266
267/*
268 * ----------------------------------------------------------------------
269 *
270 * SetRasterizerState --
271 *
272 *    The SetRasterizerState function sets the rasterizer state.
273 *
274 * ----------------------------------------------------------------------
275 */
276
277void APIENTRY
278SetRasterizerState(D3D10DDI_HDEVICE hDevice,                   // IN
279                   D3D10DDI_HRASTERIZERSTATE hRasterizerState) // IN
280{
281   LOG_ENTRYPOINT();
282
283   struct pipe_context *pipe = CastPipeContext(hDevice);
284   void *state = CastPipeRasterizerState(hRasterizerState);
285
286   pipe->bind_rasterizer_state(pipe, state);
287}
288