blob: 0aabde71e0e53e205dd5cb51a6bf0d584ff962a3 [file] [log] [blame]
Jakob Bornecrantz31926332009-11-16 19:56:18 +01001/**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
José Fonseca28486882010-02-02 14:42:17 +000026#include "util/u_inlines.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010027#include "pipe/p_defines.h"
28#include "util/u_math.h"
Brian Paule0542512015-08-13 11:00:58 -070029#include "util/u_format.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010030
31#include "svga_context.h"
32#include "svga_state.h"
33#include "svga_cmd.h"
34#include "svga_debug.h"
Brian Paul34ce1a82013-11-07 17:28:33 -070035#include "svga_screen.h"
Brian Paule0542512015-08-13 11:00:58 -070036#include "svga_surface.h"
Charmaine Leef4824932017-04-12 16:21:51 -070037#include "svga_resource_texture.h"
Jakob Bornecrantz31926332009-11-16 19:56:18 +010038
Jakob Bornecrantz31926332009-11-16 19:56:18 +010039
Brian Paul2182d2d2013-11-07 16:57:23 -070040/*
41 * flush our command buffer after the 8th distinct render target
42 *
43 * This helps improve the surface cache behaviour in the face of the
44 * large number of single-use render targets generated by EXA and the xorg
45 * state tracker. Without this we can reference hundreds of individual
46 * render targets from a command buffer, which leaves little scope for
47 * sharing or reuse of those targets.
48 */
49#define MAX_RT_PER_BATCH 8
50
51
Jakob Bornecrantz31926332009-11-16 19:56:18 +010052
José Fonsecae8f646f2011-11-02 10:32:20 +000053static enum pipe_error
Brian Paule0542512015-08-13 11:00:58 -070054emit_fb_vgpu9(struct svga_context *svga)
Jakob Bornecrantz31926332009-11-16 19:56:18 +010055{
Brian Paul34ce1a82013-11-07 17:28:33 -070056 struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
Jakob Bornecrantz31926332009-11-16 19:56:18 +010057 const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
58 struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
Brian Paule0542512015-08-13 11:00:58 -070059 boolean reemit = svga->rebind.flags.rendertargets;
Jakob Bornecrantz31926332009-11-16 19:56:18 +010060 unsigned i;
61 enum pipe_error ret;
62
Brian Paule0542512015-08-13 11:00:58 -070063 assert(!svga_have_vgpu10(svga));
64
José Fonseca5a70db62010-08-15 13:36:02 +010065 /*
66 * We need to reemit non-null surface bindings, even when they are not
67 * dirty, to ensure that the resources are paged in.
Jakob Bornecrantz31926332009-11-16 19:56:18 +010068 */
Brian Paulf12954e2014-01-18 05:57:32 -080069
Brian Paul34ce1a82013-11-07 17:28:33 -070070 for (i = 0; i < svgascreen->max_color_buffers; i++) {
Brian Paule0542512015-08-13 11:00:58 -070071 if ((curr->cbufs[i] != hw->cbufs[i]) || (reemit && hw->cbufs[i])) {
Brian Paul2182d2d2013-11-07 16:57:23 -070072 if (svga->curr.nr_fbs++ > MAX_RT_PER_BATCH)
Keith Whitwellb84b7f12009-11-27 12:19:28 +000073 return PIPE_ERROR_OUT_OF_MEMORY;
74
Charmaine Leeb1c96442017-04-03 12:57:18 -070075 /* Check to see if we need to propagate the render target surface */
76 if (hw->cbufs[i] && svga_surface_needs_propagation(hw->cbufs[i]))
77 svga_propagate_surface(svga, hw->cbufs[i], TRUE);
78
Brian Paulf12954e2014-01-18 05:57:32 -080079 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i,
80 curr->cbufs[i]);
Jakob Bornecrantz31926332009-11-16 19:56:18 +010081 if (ret != PIPE_OK)
82 return ret;
Brian Paulf12954e2014-01-18 05:57:32 -080083
Jakob Bornecrantz31926332009-11-16 19:56:18 +010084 pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
85 }
Charmaine Leef4824932017-04-12 16:21:51 -070086
87 /* Set the rendered-to flag */
88 struct pipe_surface *s = curr->cbufs[i];
89 if (s) {
90 svga_set_texture_rendered_to(svga_texture(s->texture),
91 s->u.tex.first_layer, s->u.tex.level);
92 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +010093 }
94
Brian Paule0542512015-08-13 11:00:58 -070095 if ((curr->zsbuf != hw->zsbuf) || (reemit && hw->zsbuf)) {
Jakob Bornecrantz31926332009-11-16 19:56:18 +010096 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf);
97 if (ret != PIPE_OK)
98 return ret;
99
Charmaine Leeb1c96442017-04-03 12:57:18 -0700100 /* Check to see if we need to propagate the depth stencil surface */
101 if (hw->zsbuf && svga_surface_needs_propagation(hw->zsbuf))
102 svga_propagate_surface(svga, hw->zsbuf, TRUE);
103
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100104 if (curr->zsbuf &&
Brian Paule0542512015-08-13 11:00:58 -0700105 util_format_is_depth_and_stencil(curr->zsbuf->format)) {
Brian Paulf12954e2014-01-18 05:57:32 -0800106 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL,
107 curr->zsbuf);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100108 if (ret != PIPE_OK)
109 return ret;
110 }
111 else {
112 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
113 if (ret != PIPE_OK)
114 return ret;
115 }
Brian Paulf12954e2014-01-18 05:57:32 -0800116
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100117 pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
Charmaine Leef4824932017-04-12 16:21:51 -0700118
119 /* Set the rendered-to flag */
120 struct pipe_surface *s = curr->zsbuf;
121 if (s) {
122 svga_set_texture_rendered_to(svga_texture(s->texture),
123 s->u.tex.first_layer, s->u.tex.level);
124 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100125 }
126
Brian Paul27863432012-05-17 13:53:15 -0600127 return PIPE_OK;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100128}
129
130
José Fonseca369ece12011-02-23 13:32:37 +0000131/*
132 * Rebind rendertargets.
133 *
134 * Similar to emit_framebuffer, but without any state checking/update.
135 *
136 * Called at the beginning of every new command buffer to ensure that
137 * non-dirty rendertargets are properly paged-in.
138 */
Brian Paule0542512015-08-13 11:00:58 -0700139static enum pipe_error
140svga_reemit_framebuffer_bindings_vgpu9(struct svga_context *svga)
José Fonseca369ece12011-02-23 13:32:37 +0000141{
Brian Paul34ce1a82013-11-07 17:28:33 -0700142 struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
José Fonseca369ece12011-02-23 13:32:37 +0000143 struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
144 unsigned i;
145 enum pipe_error ret;
146
Brian Paule0542512015-08-13 11:00:58 -0700147 assert(!svga_have_vgpu10(svga));
José Fonseca6b95cfb2011-04-07 16:54:37 +0100148
Brian Paul34ce1a82013-11-07 17:28:33 -0700149 for (i = 0; i < svgascreen->max_color_buffers; i++) {
José Fonseca369ece12011-02-23 13:32:37 +0000150 if (hw->cbufs[i]) {
Brian Paulf12954e2014-01-18 05:57:32 -0800151 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i,
152 hw->cbufs[i]);
José Fonseca369ece12011-02-23 13:32:37 +0000153 if (ret != PIPE_OK) {
154 return ret;
155 }
156 }
157 }
158
159 if (hw->zsbuf) {
160 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf);
161 if (ret != PIPE_OK) {
162 return ret;
163 }
164
165 if (hw->zsbuf &&
Brian Paule0542512015-08-13 11:00:58 -0700166 util_format_is_depth_and_stencil(hw->zsbuf->format)) {
José Fonseca369ece12011-02-23 13:32:37 +0000167 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf);
168 if (ret != PIPE_OK) {
169 return ret;
170 }
171 }
172 else {
173 ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
174 if (ret != PIPE_OK) {
175 return ret;
176 }
177 }
178 }
179
Brian Paule0542512015-08-13 11:00:58 -0700180 return PIPE_OK;
181}
182
183
184
185static enum pipe_error
186emit_fb_vgpu10(struct svga_context *svga)
187{
188 const struct svga_screen *ss = svga_screen(svga->pipe.screen);
189 struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS];
190 struct pipe_surface *dsv;
191 struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
192 struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
193 const unsigned num_color = MAX2(curr->nr_cbufs, hw->nr_cbufs);
Charmaine Lee6b7923e2016-07-11 17:11:41 -0700194 int last_rtv = -1;
Brian Paule0542512015-08-13 11:00:58 -0700195 unsigned i;
Charmaine Lee32651c62016-06-28 16:09:59 -0700196 enum pipe_error ret = PIPE_OK;
Brian Paule0542512015-08-13 11:00:58 -0700197
198 assert(svga_have_vgpu10(svga));
199
Charmaine Lee02c9bf22017-03-22 10:46:54 -0700200 /* Reset the has_backed_views flag.
201 * The flag is set in svga_validate_surface_view() if
202 * a backed surface view is used.
203 */
204 svga->state.hw_draw.has_backed_views = FALSE;
205
Brian Paule0542512015-08-13 11:00:58 -0700206 /* Setup render targets array. Note that we loop over the max of the
207 * number of previously bound buffers and the new buffers to unbind
208 * any previously bound buffers when the new number of buffers is less
209 * than the old number of buffers.
210 */
211 for (i = 0; i < num_color; i++) {
212 if (curr->cbufs[i]) {
Charmaine Leef4824932017-04-12 16:21:51 -0700213 struct pipe_surface *s = curr->cbufs[i];
214
215 rtv[i] = svga_validate_surface_view(svga, svga_surface(s));
Brian Paule0542512015-08-13 11:00:58 -0700216 if (rtv[i] == NULL) {
217 return PIPE_ERROR_OUT_OF_MEMORY;
218 }
219
220 assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID);
Charmaine Lee6b7923e2016-07-11 17:11:41 -0700221 last_rtv = i;
Charmaine Leef4824932017-04-12 16:21:51 -0700222
223 /* Set the rendered-to flag */
224 svga_set_texture_rendered_to(svga_texture(s->texture),
225 s->u.tex.first_layer, s->u.tex.level);
Brian Paule0542512015-08-13 11:00:58 -0700226 }
227 else {
228 rtv[i] = NULL;
229 }
230 }
231
232 /* Setup depth stencil view */
233 if (curr->zsbuf) {
Charmaine Leef4824932017-04-12 16:21:51 -0700234 struct pipe_surface *s = curr->zsbuf;
235
Brian Paule0542512015-08-13 11:00:58 -0700236 dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf));
Edward O'Callaghan13eb5f52015-12-04 22:08:22 +1100237 if (!dsv) {
Brian Paule0542512015-08-13 11:00:58 -0700238 return PIPE_ERROR_OUT_OF_MEMORY;
239 }
Charmaine Leef4824932017-04-12 16:21:51 -0700240
241 /* Set the rendered-to flag */
242 svga_set_texture_rendered_to(svga_texture(s->texture),
243 s->u.tex.first_layer, s->u.tex.level);
Brian Paule0542512015-08-13 11:00:58 -0700244 }
245 else {
246 dsv = NULL;
247 }
248
Charmaine Lee32651c62016-06-28 16:09:59 -0700249 /* avoid emitting redundant SetRenderTargets command */
Charmaine Leedc30ac52017-04-25 14:27:51 -0600250 if ((num_color != svga->state.hw_clear.num_rendertargets) ||
251 (dsv != svga->state.hw_clear.dsv) ||
252 memcmp(rtv, svga->state.hw_clear.rtv, num_color * sizeof(rtv[0]))) {
Brian Paule0542512015-08-13 11:00:58 -0700253
Charmaine Lee32651c62016-06-28 16:09:59 -0700254 ret = SVGA3D_vgpu10_SetRenderTargets(svga->swc, num_color, rtv, dsv);
255 if (ret != PIPE_OK)
256 return ret;
257
Charmaine Lee6b7923e2016-07-11 17:11:41 -0700258 /* number of render targets sent to the device, not including trailing
259 * unbound render targets.
260 */
Charmaine Leedc30ac52017-04-25 14:27:51 -0600261 svga->state.hw_clear.num_rendertargets = last_rtv + 1;
262 svga->state.hw_clear.dsv = dsv;
263 memcpy(svga->state.hw_clear.rtv, rtv, num_color * sizeof(rtv[0]));
Charmaine Lee32651c62016-06-28 16:09:59 -0700264
265 for (i = 0; i < ss->max_color_buffers; i++) {
266 if (hw->cbufs[i] != curr->cbufs[i]) {
267 /* propagate the backed view surface before unbinding it */
268 if (hw->cbufs[i] && svga_surface(hw->cbufs[i])->backed) {
269 svga_propagate_surface(svga,
Charmaine Leea08e3b82017-03-22 12:45:11 -0700270 &svga_surface(hw->cbufs[i])->backed->base,
271 TRUE);
Charmaine Lee32651c62016-06-28 16:09:59 -0700272 }
273 pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
Brian Paule0542512015-08-13 11:00:58 -0700274 }
Brian Paule0542512015-08-13 11:00:58 -0700275 }
Charmaine Lee32651c62016-06-28 16:09:59 -0700276 hw->nr_cbufs = curr->nr_cbufs;
Brian Paule0542512015-08-13 11:00:58 -0700277
Charmaine Lee32651c62016-06-28 16:09:59 -0700278 if (hw->zsbuf != curr->zsbuf) {
279 /* propagate the backed view surface before unbinding it */
280 if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) {
Charmaine Leea08e3b82017-03-22 12:45:11 -0700281 svga_propagate_surface(svga, &svga_surface(hw->zsbuf)->backed->base,
282 TRUE);
Charmaine Lee32651c62016-06-28 16:09:59 -0700283 }
284 pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
Brian Paule0542512015-08-13 11:00:58 -0700285 }
Brian Paule0542512015-08-13 11:00:58 -0700286 }
287
288 return ret;
289}
290
291
292static enum pipe_error
293emit_framebuffer(struct svga_context *svga, unsigned dirty)
294{
295 if (svga_have_vgpu10(svga)) {
296 return emit_fb_vgpu10(svga);
297 }
298 else {
299 return emit_fb_vgpu9(svga);
300 }
301}
302
303
304/*
305 * Rebind rendertargets.
306 *
307 * Similar to emit_framebuffer, but without any state checking/update.
308 *
309 * Called at the beginning of every new command buffer to ensure that
310 * non-dirty rendertargets are properly paged-in.
311 */
312enum pipe_error
313svga_reemit_framebuffer_bindings(struct svga_context *svga)
314{
315 enum pipe_error ret;
316
317 assert(svga->rebind.flags.rendertargets);
318
319 if (svga_have_vgpu10(svga)) {
320 ret = emit_fb_vgpu10(svga);
321 }
322 else {
323 ret = svga_reemit_framebuffer_bindings_vgpu9(svga);
324 }
325
326 svga->rebind.flags.rendertargets = FALSE;
327
328 return ret;
329}
330
331
332/*
333 * Send a private allocation command to page in rendertargets resource.
334 */
335enum pipe_error
336svga_rebind_framebuffer_bindings(struct svga_context *svga)
337{
Charmaine Leedc30ac52017-04-25 14:27:51 -0600338 struct svga_hw_clear_state *hw = &svga->state.hw_clear;
Brian Paule0542512015-08-13 11:00:58 -0700339 unsigned i;
340 enum pipe_error ret;
341
342 assert(svga_have_vgpu10(svga));
343
344 if (!svga->rebind.flags.rendertargets)
345 return PIPE_OK;
346
Charmaine Leec3c7ff02016-06-30 13:08:25 -0700347 for (i = 0; i < hw->num_rendertargets; i++) {
348 if (hw->rtv[i]) {
Brian Paule0542512015-08-13 11:00:58 -0700349 ret = svga->swc->resource_rebind(svga->swc,
Charmaine Leec3c7ff02016-06-30 13:08:25 -0700350 svga_surface(hw->rtv[i])->handle,
Brian Paule0542512015-08-13 11:00:58 -0700351 NULL,
352 SVGA_RELOC_WRITE);
353 if (ret != PIPE_OK)
354 return ret;
355 }
356 }
357
Charmaine Leec3c7ff02016-06-30 13:08:25 -0700358 if (hw->dsv) {
Brian Paule0542512015-08-13 11:00:58 -0700359 ret = svga->swc->resource_rebind(svga->swc,
Charmaine Leec3c7ff02016-06-30 13:08:25 -0700360 svga_surface(hw->dsv)->handle,
Brian Paule0542512015-08-13 11:00:58 -0700361 NULL,
362 SVGA_RELOC_WRITE);
363 if (ret != PIPE_OK)
364 return ret;
365 }
366
367 svga->rebind.flags.rendertargets = 0;
José Fonseca6b95cfb2011-04-07 16:54:37 +0100368
José Fonseca369ece12011-02-23 13:32:37 +0000369 return PIPE_OK;
370}
371
372
Brian Paulf12954e2014-01-18 05:57:32 -0800373struct svga_tracked_state svga_hw_framebuffer =
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100374{
375 "hw framebuffer state",
José Fonseca6b95cfb2011-04-07 16:54:37 +0100376 SVGA_NEW_FRAME_BUFFER,
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100377 emit_framebuffer
378};
379
380
381
382
Brian Paulf12954e2014-01-18 05:57:32 -0800383/***********************************************************************
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100384 */
385
José Fonsecae8f646f2011-11-02 10:32:20 +0000386static enum pipe_error
387emit_viewport( struct svga_context *svga,
388 unsigned dirty )
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100389{
390 const struct pipe_viewport_state *viewport = &svga->curr.viewport;
391 struct svga_prescale prescale;
392 SVGA3dRect rect;
393 /* Not sure if this state is relevant with POSITIONT. Probably
394 * not, but setting to 0,1 avoids some state pingponging.
395 */
396 float range_min = 0.0;
397 float range_max = 1.0;
398 float flip = -1.0;
399 boolean degenerate = FALSE;
Brian Paul1459c182012-05-14 16:33:58 -0600400 boolean invertY = FALSE;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100401 enum pipe_error ret;
402
Brian Paul200291e2012-10-16 17:54:37 -0600403 float fb_width = (float) svga->curr.framebuffer.width;
404 float fb_height = (float) svga->curr.framebuffer.height;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100405
Brian Paul200291e2012-10-16 17:54:37 -0600406 float fx = viewport->scale[0] * -1.0f + viewport->translate[0];
407 float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1];
Brian Paulf12954e2014-01-18 05:57:32 -0800408 float fw = viewport->scale[0] * 2.0f;
409 float fh = flip * viewport->scale[1] * 2.0f;
Brian Paule0542512015-08-13 11:00:58 -0700410 boolean emit_vgpu10_viewport = FALSE;
Michal Krol63cb6f52010-02-22 21:36:22 +0100411
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100412 memset( &prescale, 0, sizeof(prescale) );
413
Michal Krol63cb6f52010-02-22 21:36:22 +0100414 /* Examine gallium viewport transformation and produce a screen
415 * rectangle and possibly vertex shader pre-transformation to
416 * get the same results.
417 */
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100418
Michal Krol63cb6f52010-02-22 21:36:22 +0100419 SVGA_DBG(DEBUG_VIEWPORT,
420 "\ninitial %f,%f %fx%f\n",
421 fx,
422 fy,
423 fw,
424 fh);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100425
Michal Krol63cb6f52010-02-22 21:36:22 +0100426 prescale.scale[0] = 1.0;
427 prescale.scale[1] = 1.0;
428 prescale.scale[2] = 1.0;
429 prescale.scale[3] = 1.0;
430 prescale.translate[0] = 0;
431 prescale.translate[1] = 0;
432 prescale.translate[2] = 0;
433 prescale.translate[3] = 0;
Brian Paule0542512015-08-13 11:00:58 -0700434
435 /* Enable prescale to adjust vertex positions to match
436 VGPU10 convention only if rasterization is enabled.
437 */
Brian Paulb95ead82017-03-01 15:29:55 -0700438 if (svga->curr.rast && svga->curr.rast->templ.rasterizer_discard) {
Brian Paule0542512015-08-13 11:00:58 -0700439 degenerate = TRUE;
440 goto out;
441 } else {
442 prescale.enabled = TRUE;
443 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100444
Michal Krol63cb6f52010-02-22 21:36:22 +0100445 if (fw < 0) {
Brian Paul200291e2012-10-16 17:54:37 -0600446 prescale.scale[0] *= -1.0f;
Michal Krol63cb6f52010-02-22 21:36:22 +0100447 prescale.translate[0] += -fw;
448 fw = -fw;
Brian Paulf12954e2014-01-18 05:57:32 -0800449 fx = viewport->scale[0] * 1.0f + viewport->translate[0];
Michal Krol63cb6f52010-02-22 21:36:22 +0100450 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100451
Brian Paul1459c182012-05-14 16:33:58 -0600452 if (fh < 0.0) {
Brian Paule0542512015-08-13 11:00:58 -0700453 if (svga_have_vgpu10(svga)) {
454 /* floating point viewport params below */
455 prescale.translate[1] = fh + fy * 2.0f;
456 }
457 else {
458 /* integer viewport params below */
459 prescale.translate[1] = fh - 1.0f + fy * 2.0f;
460 }
Michal Krol63cb6f52010-02-22 21:36:22 +0100461 fh = -fh;
Brian Paul1459c182012-05-14 16:33:58 -0600462 fy -= fh;
Brian Paul200291e2012-10-16 17:54:37 -0600463 prescale.scale[1] = -1.0f;
Brian Paul1459c182012-05-14 16:33:58 -0600464 invertY = TRUE;
Michal Krol63cb6f52010-02-22 21:36:22 +0100465 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100466
Michal Krol63cb6f52010-02-22 21:36:22 +0100467 if (fx < 0) {
468 prescale.translate[0] += fx;
Brian Paulf12954e2014-01-18 05:57:32 -0800469 prescale.scale[0] *= fw / (fw + fx);
Michal Krol63cb6f52010-02-22 21:36:22 +0100470 fw += fx;
Brian Paul200291e2012-10-16 17:54:37 -0600471 fx = 0.0f;
Michal Krol63cb6f52010-02-22 21:36:22 +0100472 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100473
Michal Krol63cb6f52010-02-22 21:36:22 +0100474 if (fy < 0) {
Brian Paul1459c182012-05-14 16:33:58 -0600475 if (invertY) {
476 prescale.translate[1] -= fy;
477 }
478 else {
479 prescale.translate[1] += fy;
480 }
Brian Paulf12954e2014-01-18 05:57:32 -0800481 prescale.scale[1] *= fh / (fh + fy);
Michal Krol63cb6f52010-02-22 21:36:22 +0100482 fh += fy;
Brian Paul200291e2012-10-16 17:54:37 -0600483 fy = 0.0f;
Michal Krol63cb6f52010-02-22 21:36:22 +0100484 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100485
Michal Krol63cb6f52010-02-22 21:36:22 +0100486 if (fx + fw > fb_width) {
Brian Paulf12954e2014-01-18 05:57:32 -0800487 prescale.scale[0] *= fw / (fb_width - fx);
Michal Krol63cb6f52010-02-22 21:36:22 +0100488 prescale.translate[0] -= fx * (fw / (fb_width - fx));
489 prescale.translate[0] += fx;
490 fw = fb_width - fx;
Michal Krol63cb6f52010-02-22 21:36:22 +0100491 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100492
Michal Krol63cb6f52010-02-22 21:36:22 +0100493 if (fy + fh > fb_height) {
494 prescale.scale[1] *= fh / (fb_height - fy);
Brian Paul1459c182012-05-14 16:33:58 -0600495 if (invertY) {
496 float in = fb_height - fy; /* number of vp pixels inside view */
497 float out = fy + fh - fb_height; /* number of vp pixels out of view */
498 prescale.translate[1] += fy * out / in;
499 }
500 else {
501 prescale.translate[1] -= fy * (fh / (fb_height - fy));
502 prescale.translate[1] += fy;
503 }
Michal Krol63cb6f52010-02-22 21:36:22 +0100504 fh = fb_height - fy;
505 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100506
Michal Krol63cb6f52010-02-22 21:36:22 +0100507 if (fw < 0 || fh < 0) {
508 fw = fh = fx = fy = 0;
509 degenerate = TRUE;
510 goto out;
511 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100512
Michal Krol63cb6f52010-02-22 21:36:22 +0100513 /* D3D viewport is integer space. Convert fx,fy,etc. to
514 * integers.
515 *
516 * TODO: adjust pretranslate correct for any subpixel error
517 * introduced converting to integers.
518 */
Brian Paul200291e2012-10-16 17:54:37 -0600519 rect.x = (uint32) fx;
520 rect.y = (uint32) fy;
521 rect.w = (uint32) fw;
522 rect.h = (uint32) fh;
Michal Krol63cb6f52010-02-22 21:36:22 +0100523
524 SVGA_DBG(DEBUG_VIEWPORT,
525 "viewport error %f,%f %fx%f\n",
526 fabs((float)rect.x - fx),
527 fabs((float)rect.y - fy),
528 fabs((float)rect.w - fw),
529 fabs((float)rect.h - fh));
530
531 SVGA_DBG(DEBUG_VIEWPORT,
532 "viewport %d,%d %dx%d\n",
533 rect.x,
534 rect.y,
535 rect.w,
536 rect.h);
537
Michal Krol63cb6f52010-02-22 21:36:22 +0100538 /* Finally, to get GL rasterization rules, need to tweak the
539 * screen-space coordinates slightly relative to D3D which is
540 * what hardware implements natively.
541 */
Brian Paulb95ead82017-03-01 15:29:55 -0700542 if (svga->curr.rast && svga->curr.rast->templ.half_pixel_center) {
Michal Krol63cb6f52010-02-22 21:36:22 +0100543 float adjust_x = 0.0;
544 float adjust_y = 0.0;
545
Brian Paule0542512015-08-13 11:00:58 -0700546 if (svga_have_vgpu10(svga)) {
547 /* Normally, we don't have to do any sub-pixel coordinate
548 * adjustments for VGPU10. But when we draw wide points with
549 * a GS we need an X adjustment in order to be conformant.
550 */
551 if (svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
552 svga->curr.rast->pointsize > 1.0f) {
553 adjust_x = 0.5;
554 }
555 }
556 else {
Brian Paul362fb052017-08-18 14:38:03 -0600557 /* Use (-0.5, -0.5) bias for all prim types.
558 * Regarding line rasterization, this does not seem to satisfy
559 * the Piglit gl-1.0-ortho-pos test but it generally produces
560 * results identical or very similar to VGPU10.
561 */
562 adjust_x = -0.5;
563 adjust_y = -0.5;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100564 }
565
Brian Paul1459c182012-05-14 16:33:58 -0600566 if (invertY)
567 adjust_y = -adjust_y;
568
Michal Krol63cb6f52010-02-22 21:36:22 +0100569 prescale.translate[0] += adjust_x;
570 prescale.translate[1] += adjust_y;
571 prescale.translate[2] = 0.5; /* D3D clip space */
572 prescale.scale[2] = 0.5; /* D3D clip space */
573 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100574
Brian Paul200291e2012-10-16 17:54:37 -0600575 range_min = viewport->scale[2] * -1.0f + viewport->translate[2];
576 range_max = viewport->scale[2] * 1.0f + viewport->translate[2];
Michal Krol63cb6f52010-02-22 21:36:22 +0100577
578 /* D3D (and by implication SVGA) doesn't like dealing with zmax
579 * less than zmin. Detect that case, flip the depth range and
580 * invert our z-scale factor to achieve the same effect.
581 */
582 if (range_min > range_max) {
583 float range_tmp;
Brian Paulf12954e2014-01-18 05:57:32 -0800584 range_tmp = range_min;
585 range_min = range_max;
Michal Krol63cb6f52010-02-22 21:36:22 +0100586 range_max = range_tmp;
Brian Paulf12954e2014-01-18 05:57:32 -0800587 prescale.scale[2] = -prescale.scale[2];
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100588 }
589
Brian Paule0542512015-08-13 11:00:58 -0700590 /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale.
591 * zmin can be set to -1 when viewport->scale[2] is set to 1 and
592 * viewport->translate[2] is set to 0 in the blit code.
593 */
594 if (range_min < 0.0f) {
595 range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
596 range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
597 prescale.scale[2] *= 2.0f;
598 prescale.translate[2] -= 0.5f;
599 }
600
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100601 if (prescale.enabled) {
602 float H[2];
603 float J[2];
604 int i;
605
606 SVGA_DBG(DEBUG_VIEWPORT,
607 "prescale %f,%f %fx%f\n",
608 prescale.translate[0],
609 prescale.translate[1],
610 prescale.scale[0],
611 prescale.scale[1]);
612
Brian Paul200291e2012-10-16 17:54:37 -0600613 H[0] = (float)rect.w / 2.0f;
614 H[1] = -(float)rect.h / 2.0f;
615 J[0] = (float)rect.x + (float)rect.w / 2.0f;
616 J[1] = (float)rect.y + (float)rect.h / 2.0f;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100617
618 SVGA_DBG(DEBUG_VIEWPORT,
619 "H %f,%f\n"
620 "J %fx%f\n",
621 H[0],
622 H[1],
623 J[0],
624 J[1]);
625
626 /* Adjust prescale to take into account the fact that it is
627 * going to be applied prior to the perspective divide and
628 * viewport transformation.
Brian Paulf12954e2014-01-18 05:57:32 -0800629 *
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100630 * Vwin = H(Vc/Vc.w) + J
631 *
632 * We want to tweak Vwin with scale and translation from above,
633 * as in:
634 *
635 * Vwin' = S Vwin + T
636 *
637 * But we can only modify the values at Vc. Plugging all the
638 * above together, and rearranging, eventually we get:
639 *
640 * Vwin' = H(Vc'/Vc'.w) + J
641 * where:
642 * Vc' = SVc + KVc.w
643 * K = (T + (S-1)J) / H
644 *
645 * Overwrite prescale.translate with values for K:
646 */
647 for (i = 0; i < 2; i++) {
648 prescale.translate[i] = ((prescale.translate[i] +
Brian Paul200291e2012-10-16 17:54:37 -0600649 (prescale.scale[i] - 1.0f) * J[i]) / H[i]);
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100650 }
651
652 SVGA_DBG(DEBUG_VIEWPORT,
653 "clipspace %f,%f %fx%f\n",
654 prescale.translate[0],
655 prescale.translate[1],
656 prescale.scale[0],
657 prescale.scale[1]);
658 }
659
660out:
661 if (degenerate) {
662 rect.x = 0;
663 rect.y = 0;
664 rect.w = 1;
665 rect.h = 1;
666 prescale.enabled = FALSE;
667 }
668
Brian Paule0542512015-08-13 11:00:58 -0700669 if (!svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
670 if (svga_have_vgpu10(svga)) {
671 emit_vgpu10_viewport = TRUE;
672 }
673 else {
674 ret = SVGA3D_SetViewport(svga->swc, &rect);
675 if (ret != PIPE_OK)
676 return ret;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100677
Brian Paule0542512015-08-13 11:00:58 -0700678 svga->state.hw_clear.viewport = rect;
679 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100680 }
681
682 if (svga->state.hw_clear.depthrange.zmin != range_min ||
Brian Paule0542512015-08-13 11:00:58 -0700683 svga->state.hw_clear.depthrange.zmax != range_max)
684 {
685 if (svga_have_vgpu10(svga)) {
686 emit_vgpu10_viewport = TRUE;
687 }
688 else {
689 ret = SVGA3D_SetZRange(svga->swc, range_min, range_max );
690 if (ret != PIPE_OK)
691 return ret;
692
693 svga->state.hw_clear.depthrange.zmin = range_min;
694 svga->state.hw_clear.depthrange.zmax = range_max;
695 }
696 }
697
698 if (emit_vgpu10_viewport) {
699 SVGA3dViewport vp;
700 vp.x = (float) rect.x;
701 vp.y = (float) rect.y;
702 vp.width = (float) rect.w;
703 vp.height = (float) rect.h;
704 vp.minDepth = range_min;
705 vp.maxDepth = range_max;
706 ret = SVGA3D_vgpu10_SetViewports(svga->swc, 1, &vp);
707 if (ret != PIPE_OK)
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100708 return ret;
709
Brian Paule0542512015-08-13 11:00:58 -0700710 svga->state.hw_clear.viewport = rect;
711
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100712 svga->state.hw_clear.depthrange.zmin = range_min;
713 svga->state.hw_clear.depthrange.zmax = range_max;
714 }
715
716 if (memcmp(&prescale, &svga->state.hw_clear.prescale, sizeof prescale) != 0) {
717 svga->dirty |= SVGA_NEW_PRESCALE;
718 svga->state.hw_clear.prescale = prescale;
719 }
720
Brian Paul27863432012-05-17 13:53:15 -0600721 return PIPE_OK;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100722}
723
724
Brian Paulf12954e2014-01-18 05:57:32 -0800725struct svga_tracked_state svga_hw_viewport =
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100726{
727 "hw viewport state",
728 ( SVGA_NEW_FRAME_BUFFER |
729 SVGA_NEW_VIEWPORT |
730 SVGA_NEW_RAST |
731 SVGA_NEW_REDUCED_PRIMITIVE ),
732 emit_viewport
733};
734
735
736/***********************************************************************
737 * Scissor state
738 */
José Fonsecae8f646f2011-11-02 10:32:20 +0000739static enum pipe_error
740emit_scissor_rect( struct svga_context *svga,
741 unsigned dirty )
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100742{
743 const struct pipe_scissor_state *scissor = &svga->curr.scissor;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100744
Brian Paule0542512015-08-13 11:00:58 -0700745 if (svga_have_vgpu10(svga)) {
746 SVGASignedRect rect;
Brian Paulf12954e2014-01-18 05:57:32 -0800747
Brian Paule0542512015-08-13 11:00:58 -0700748 rect.left = scissor->minx;
749 rect.top = scissor->miny;
750 rect.right = scissor->maxx;
751 rect.bottom = scissor->maxy;
752
753 return SVGA3D_vgpu10_SetScissorRects(svga->swc, 1, &rect);
754 }
755 else {
756 SVGA3dRect rect;
757
758 rect.x = scissor->minx;
759 rect.y = scissor->miny;
760 rect.w = scissor->maxx - scissor->minx; /* + 1 ?? */
761 rect.h = scissor->maxy - scissor->miny; /* + 1 ?? */
762
763 return SVGA3D_SetScissorRect(svga->swc, &rect);
764 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100765}
766
767
Brian Paulf12954e2014-01-18 05:57:32 -0800768struct svga_tracked_state svga_hw_scissor =
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100769{
770 "hw scissor state",
771 SVGA_NEW_SCISSOR,
772 emit_scissor_rect
773};
774
775
776/***********************************************************************
777 * Userclip state
778 */
779
José Fonsecae8f646f2011-11-02 10:32:20 +0000780static enum pipe_error
781emit_clip_planes( struct svga_context *svga,
782 unsigned dirty )
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100783{
784 unsigned i;
785 enum pipe_error ret;
786
787 /* TODO: just emit directly from svga_set_clip_state()?
788 */
José Fonsecace2929d2012-01-11 20:54:13 +0000789 for (i = 0; i < SVGA3D_MAX_CLIP_PLANES; i++) {
Brian Paul0be6ae72011-04-25 10:26:19 -0600790 /* need to express the plane in D3D-style coordinate space.
791 * GL coords get converted to D3D coords with the matrix:
792 * [ 1 0 0 0 ]
793 * [ 0 -1 0 0 ]
794 * [ 0 0 2 0 ]
795 * [ 0 0 -1 1 ]
796 * Apply that matrix to our plane equation, and invert Y.
797 */
798 float a = svga->curr.clip.ucp[i][0];
799 float b = svga->curr.clip.ucp[i][1];
800 float c = svga->curr.clip.ucp[i][2];
801 float d = svga->curr.clip.ucp[i][3];
802 float plane[4];
803
804 plane[0] = a;
805 plane[1] = b;
806 plane[2] = 2.0f * c;
807 plane[3] = d - c;
808
Brian Paule0542512015-08-13 11:00:58 -0700809 if (svga_have_vgpu10(svga)) {
810 //debug_printf("XXX emit DX10 clip plane\n");
811 ret = PIPE_OK;
812 }
813 else {
814 ret = SVGA3D_SetClipPlane(svga->swc, i, plane);
815 if (ret != PIPE_OK)
816 return ret;
817 }
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100818 }
819
Brian Paul27863432012-05-17 13:53:15 -0600820 return PIPE_OK;
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100821}
822
823
Brian Paulf12954e2014-01-18 05:57:32 -0800824struct svga_tracked_state svga_hw_clip_planes =
Jakob Bornecrantz31926332009-11-16 19:56:18 +0100825{
826 "hw viewport state",
827 SVGA_NEW_CLIP,
828 emit_clip_planes
829};