1 /**********************************************************
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 
26 #include "util/u_inlines.h"
27 #include "pipe/p_defines.h"
28 #include "util/u_math.h"
29 #include "util/format/u_format.h"
30 
31 #include "svga_context.h"
32 #include "svga_state.h"
33 #include "svga_cmd.h"
34 #include "svga_debug.h"
35 #include "svga_screen.h"
36 #include "svga_surface.h"
37 #include "svga_resource_texture.h"
38 
39 
40 /*
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 
52 
53 static enum pipe_error
emit_fb_vgpu9(struct svga_context * svga)54 emit_fb_vgpu9(struct svga_context *svga)
55 {
56    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
57    const struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
58    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
59    boolean reemit = svga->rebind.flags.rendertargets;
60    unsigned i;
61    enum pipe_error ret;
62 
63    assert(!svga_have_vgpu10(svga));
64 
65    /*
66     * We need to reemit non-null surface bindings, even when they are not
67     * dirty, to ensure that the resources are paged in.
68     */
69 
70    for (i = 0; i < svgascreen->max_color_buffers; i++) {
71       if ((curr->cbufs[i] != hw->cbufs[i]) || (reemit && hw->cbufs[i])) {
72          if (svga->curr.nr_fbs++ > MAX_RT_PER_BATCH)
73             return PIPE_ERROR_OUT_OF_MEMORY;
74 
75          /* 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 
79          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i,
80                                       curr->cbufs[i]);
81          if (ret != PIPE_OK)
82             return ret;
83 
84          pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
85       }
86 
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       }
92    }
93 
94    if ((curr->zsbuf != hw->zsbuf) || (reemit && hw->zsbuf)) {
95       ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, curr->zsbuf);
96       if (ret != PIPE_OK)
97          return ret;
98 
99       /* Check to see if we need to propagate the depth stencil surface */
100       if (hw->zsbuf && svga_surface_needs_propagation(hw->zsbuf))
101          svga_propagate_surface(svga, hw->zsbuf, TRUE);
102 
103       if (curr->zsbuf &&
104           util_format_is_depth_and_stencil(curr->zsbuf->format)) {
105          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL,
106                                       curr->zsbuf);
107          if (ret != PIPE_OK)
108             return ret;
109       }
110       else {
111          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
112          if (ret != PIPE_OK)
113             return ret;
114       }
115 
116       pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
117 
118       /* Set the rendered-to flag */
119       struct pipe_surface *s = curr->zsbuf;
120       if (s) {
121          svga_set_texture_rendered_to(svga_texture(s->texture));
122       }
123    }
124 
125    return PIPE_OK;
126 }
127 
128 
129 /*
130  * Rebind rendertargets.
131  *
132  * Similar to emit_framebuffer, but without any state checking/update.
133  *
134  * Called at the beginning of every new command buffer to ensure that
135  * non-dirty rendertargets are properly paged-in.
136  */
137 static enum pipe_error
svga_reemit_framebuffer_bindings_vgpu9(struct svga_context * svga)138 svga_reemit_framebuffer_bindings_vgpu9(struct svga_context *svga)
139 {
140    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
141    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
142    unsigned i;
143    enum pipe_error ret;
144 
145    assert(!svga_have_vgpu10(svga));
146 
147    for (i = 0; i < svgascreen->max_color_buffers; i++) {
148       if (hw->cbufs[i]) {
149          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_COLOR0 + i,
150                                       hw->cbufs[i]);
151          if (ret != PIPE_OK) {
152             return ret;
153          }
154       }
155    }
156 
157    if (hw->zsbuf) {
158       ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_DEPTH, hw->zsbuf);
159       if (ret != PIPE_OK) {
160          return ret;
161       }
162 
163       if (hw->zsbuf &&
164           util_format_is_depth_and_stencil(hw->zsbuf->format)) {
165          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, hw->zsbuf);
166          if (ret != PIPE_OK) {
167             return ret;
168          }
169       }
170       else {
171          ret = SVGA3D_SetRenderTarget(svga->swc, SVGA3D_RT_STENCIL, NULL);
172          if (ret != PIPE_OK) {
173             return ret;
174          }
175       }
176    }
177 
178    return PIPE_OK;
179 }
180 
181 
182 
183 static enum pipe_error
emit_fb_vgpu10(struct svga_context * svga)184 emit_fb_vgpu10(struct svga_context *svga)
185 {
186    const struct svga_screen *ss = svga_screen(svga->pipe.screen);
187    struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS];
188    struct pipe_surface *dsv;
189    struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
190    struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
191    const unsigned num_color = MAX2(curr->nr_cbufs, hw->nr_cbufs);
192    int last_rtv = -1;
193    unsigned i;
194    enum pipe_error ret = PIPE_OK;
195 
196    assert(svga_have_vgpu10(svga));
197 
198    /* Reset the has_backed_views flag.
199     * The flag is set in svga_validate_surface_view() if
200     * a backed surface view is used.
201     */
202    svga->state.hw_draw.has_backed_views = FALSE;
203 
204    /* Setup render targets array.  Note that we loop over the max of the
205     * number of previously bound buffers and the new buffers to unbind
206     * any previously bound buffers when the new number of buffers is less
207     * than the old number of buffers.
208     */
209    for (i = 0; i < num_color; i++) {
210       if (curr->cbufs[i]) {
211          struct pipe_surface *s = curr->cbufs[i];
212 
213          if (curr->cbufs[i] != hw->cbufs[i]) {
214             rtv[i] = svga_validate_surface_view(svga, svga_surface(s));
215             if (rtv[i] == NULL) {
216                return PIPE_ERROR_OUT_OF_MEMORY;
217             }
218          } else {
219            rtv[i] = svga->state.hw_clear.rtv[i];
220          }
221 
222          assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID);
223          last_rtv = i;
224 
225          /* Set the rendered-to flag */
226          svga_set_texture_rendered_to(svga_texture(s->texture));
227       }
228       else {
229          rtv[i] = NULL;
230       }
231    }
232 
233    /* Setup depth stencil view */
234    if (curr->zsbuf) {
235       struct pipe_surface *s = curr->zsbuf;
236 
237       if (curr->zsbuf != hw->zsbuf) {
238          dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf));
239          if (!dsv) {
240             return PIPE_ERROR_OUT_OF_MEMORY;
241          }
242       } else {
243          dsv = svga->state.hw_clear.dsv;
244       }
245 
246       /* Set the rendered-to flag */
247       svga_set_texture_rendered_to(svga_texture(s->texture));
248    }
249    else {
250       dsv = NULL;
251    }
252 
253    /* avoid emitting redundant SetRenderTargets command */
254    if ((num_color != svga->state.hw_clear.num_rendertargets) ||
255        (dsv != svga->state.hw_clear.dsv) ||
256        memcmp(rtv, svga->state.hw_clear.rtv, num_color * sizeof(rtv[0]))) {
257 
258       ret = SVGA3D_vgpu10_SetRenderTargets(svga->swc, num_color, rtv, dsv);
259       if (ret != PIPE_OK)
260          return ret;
261 
262       /* number of render targets sent to the device, not including trailing
263        * unbound render targets.
264        */
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,
270                                       &svga_surface(hw->cbufs[i])->backed->base,
271                                       TRUE);
272             }
273             else if (svga->state.hw_clear.rtv[i] != hw->cbufs[i] &&
274                      svga->state.hw_clear.rtv[i]) {
275                /* Free the alternate surface view when it is unbound.  */
276                svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.rtv[i]);
277             }
278             pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
279          }
280       }
281       svga->state.hw_clear.num_rendertargets = last_rtv + 1;
282       memcpy(svga->state.hw_clear.rtv, rtv, num_color * sizeof(rtv[0]));
283       hw->nr_cbufs = curr->nr_cbufs;
284 
285       if (hw->zsbuf != curr->zsbuf) {
286          /* propagate the backed view surface before unbinding it */
287          if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) {
288             svga_propagate_surface(svga,
289                                    &svga_surface(hw->zsbuf)->backed->base,
290                                    TRUE);
291          }
292          else if (svga->state.hw_clear.dsv != hw->zsbuf && svga->state.hw_clear.dsv) {
293             /* Free the alternate surface view when it is unbound.  */
294             svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.dsv);
295          }
296          pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
297       }
298       svga->state.hw_clear.dsv = dsv;
299    }
300 
301    return ret;
302 }
303 
304 
305 static enum pipe_error
emit_framebuffer(struct svga_context * svga,uint64_t dirty)306 emit_framebuffer(struct svga_context *svga, uint64_t dirty)
307 {
308    if (svga_have_vgpu10(svga)) {
309       return emit_fb_vgpu10(svga);
310    }
311    else {
312       return emit_fb_vgpu9(svga);
313    }
314 }
315 
316 
317 /*
318  * Rebind rendertargets.
319  *
320  * Similar to emit_framebuffer, but without any state checking/update.
321  *
322  * Called at the beginning of every new command buffer to ensure that
323  * non-dirty rendertargets are properly paged-in.
324  */
325 enum pipe_error
svga_reemit_framebuffer_bindings(struct svga_context * svga)326 svga_reemit_framebuffer_bindings(struct svga_context *svga)
327 {
328    enum pipe_error ret;
329 
330    assert(svga->rebind.flags.rendertargets);
331 
332    if (svga_have_vgpu10(svga)) {
333       ret = emit_fb_vgpu10(svga);
334    }
335    else {
336       ret = svga_reemit_framebuffer_bindings_vgpu9(svga);
337    }
338 
339    svga->rebind.flags.rendertargets = FALSE;
340 
341    return ret;
342 }
343 
344 
345 /*
346  * Send a private allocation command to page in rendertargets resource.
347  */
348 enum pipe_error
svga_rebind_framebuffer_bindings(struct svga_context * svga)349 svga_rebind_framebuffer_bindings(struct svga_context *svga)
350 {
351    struct svga_hw_clear_state *hw = &svga->state.hw_clear;
352    unsigned i;
353    enum pipe_error ret;
354 
355    assert(svga_have_vgpu10(svga));
356 
357    if (!svga->rebind.flags.rendertargets)
358       return PIPE_OK;
359 
360    for (i = 0; i < hw->num_rendertargets; i++) {
361       if (hw->rtv[i]) {
362          ret = svga->swc->resource_rebind(svga->swc,
363                                           svga_surface(hw->rtv[i])->handle,
364                                           NULL,
365                                           SVGA_RELOC_WRITE);
366          if (ret != PIPE_OK)
367             return ret;
368       }
369    }
370 
371    if (hw->dsv) {
372       ret = svga->swc->resource_rebind(svga->swc,
373                                        svga_surface(hw->dsv)->handle,
374                                        NULL,
375                                        SVGA_RELOC_WRITE);
376       if (ret != PIPE_OK)
377          return ret;
378    }
379 
380    svga->rebind.flags.rendertargets = 0;
381 
382    return PIPE_OK;
383 }
384 
385 
386 struct svga_tracked_state svga_hw_framebuffer =
387 {
388    "hw framebuffer state",
389    SVGA_NEW_FRAME_BUFFER,
390    emit_framebuffer
391 };
392 
393 
394 
395 
396 /***********************************************************************
397  */
398 
399 static void
get_viewport_prescale(struct svga_context * svga,struct pipe_viewport_state * viewport,SVGA3dViewport * vp,struct svga_prescale * prescale)400 get_viewport_prescale(struct svga_context *svga,
401                       struct pipe_viewport_state *viewport,
402                       SVGA3dViewport *vp,
403                       struct svga_prescale *prescale)
404 {
405    SVGA3dRect rect;
406 
407    /* Not sure if this state is relevant with POSITIONT.  Probably
408     * not, but setting to 0,1 avoids some state pingponging.
409     */
410    float range_min = 0.0;
411    float range_max = 1.0;
412    float flip = -1.0;
413    boolean degenerate = FALSE;
414    boolean invertY = FALSE;
415 
416    float fb_width = (float) svga->curr.framebuffer.width;
417    float fb_height = (float) svga->curr.framebuffer.height;
418 
419    float fx =        viewport->scale[0] * -1.0f + viewport->translate[0];
420    float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1];
421    float fw =        viewport->scale[0] * 2.0f;
422    float fh = flip * viewport->scale[1] * 2.0f;
423 
424    memset(prescale, 0, sizeof(*prescale));
425 
426    /* Examine gallium viewport transformation and produce a screen
427     * rectangle and possibly vertex shader pre-transformation to
428     * get the same results.
429     */
430 
431    SVGA_DBG(DEBUG_VIEWPORT,
432             "\ninitial %f,%f %fx%f\n",
433             fx,
434             fy,
435             fw,
436             fh);
437 
438    prescale->scale[0] = 1.0;
439    prescale->scale[1] = 1.0;
440    prescale->scale[2] = 1.0;
441    prescale->scale[3] = 1.0;
442    prescale->translate[0] = 0;
443    prescale->translate[1] = 0;
444    prescale->translate[2] = 0;
445    prescale->translate[3] = 0;
446 
447    /* Enable prescale to adjust vertex positions to match
448       VGPU10 convention only if rasterization is enabled.
449     */
450    if (svga->curr.rast && svga->curr.rast->templ.rasterizer_discard) {
451       degenerate = TRUE;
452       goto out;
453    } else {
454       prescale->enabled = TRUE;
455    }
456 
457    if (fw < 0) {
458       prescale->scale[0] *= -1.0f;
459       prescale->translate[0] += -fw;
460       fw = -fw;
461       fx = viewport->scale[0] * 1.0f + viewport->translate[0];
462    }
463 
464    if (fh < 0.0) {
465       if (svga_have_vgpu10(svga)) {
466          /* floating point viewport params below */
467          prescale->translate[1] = fh + fy * 2.0f;
468       }
469       else {
470          /* integer viewport params below */
471          prescale->translate[1] = fh - 1.0f + fy * 2.0f;
472       }
473       fh = -fh;
474       fy -= fh;
475       prescale->scale[1] = -1.0f;
476       invertY = TRUE;
477    }
478 
479    if (fx < 0) {
480       prescale->translate[0] += fx;
481       prescale->scale[0] *= fw / (fw + fx);
482       fw += fx;
483       fx = 0.0f;
484    }
485 
486    if (fy < 0) {
487       if (invertY) {
488          prescale->translate[1] -= fy;
489       }
490       else {
491          prescale->translate[1] += fy;
492       }
493       prescale->scale[1] *= fh / (fh + fy);
494       fh += fy;
495       fy = 0.0f;
496    }
497 
498    if (fx + fw > fb_width) {
499       prescale->scale[0] *= fw / (fb_width - fx);
500       prescale->translate[0] -= fx * (fw / (fb_width - fx));
501       prescale->translate[0] += fx;
502       fw = fb_width - fx;
503    }
504 
505    if (fy + fh > fb_height) {
506       prescale->scale[1] *= fh / (fb_height - fy);
507       if (invertY) {
508          float in = fb_height - fy;       /* number of vp pixels inside view */
509          float out = fy + fh - fb_height; /* number of vp pixels out of view */
510          prescale->translate[1] += fy * out / in;
511       }
512       else {
513          prescale->translate[1] -= fy * (fh / (fb_height - fy));
514          prescale->translate[1] += fy;
515       }
516       fh = fb_height - fy;
517    }
518 
519    if (fw < 0 || fh < 0) {
520       fw = fh = fx = fy = 0;
521       degenerate = TRUE;
522       goto out;
523    }
524 
525    /* D3D viewport is integer space.  Convert fx,fy,etc. to
526     * integers.
527     *
528     * TODO: adjust pretranslate correct for any subpixel error
529     * introduced converting to integers.
530     */
531    rect.x = (uint32) fx;
532    rect.y = (uint32) fy;
533    rect.w = (uint32) fw;
534    rect.h = (uint32) fh;
535 
536    SVGA_DBG(DEBUG_VIEWPORT,
537             "viewport error %f,%f %fx%f\n",
538             fabs((float)rect.x - fx),
539             fabs((float)rect.y - fy),
540             fabs((float)rect.w - fw),
541             fabs((float)rect.h - fh));
542 
543    SVGA_DBG(DEBUG_VIEWPORT,
544             "viewport %d,%d %dx%d\n",
545             rect.x,
546             rect.y,
547             rect.w,
548             rect.h);
549 
550    /* Finally, to get GL rasterization rules, need to tweak the
551     * screen-space coordinates slightly relative to D3D which is
552     * what hardware implements natively.
553     */
554    if (svga->curr.rast && svga->curr.rast->templ.half_pixel_center) {
555       float adjust_x = 0.0;
556       float adjust_y = 0.0;
557 
558       if (svga_have_vgpu10(svga)) {
559          /* Normally, we don't have to do any sub-pixel coordinate
560           * adjustments for VGPU10.  But when we draw wide points with
561           * a GS we need an X adjustment in order to be conformant.
562           */
563          if (svga->curr.reduced_prim == PIPE_PRIM_POINTS &&
564              svga->curr.rast->pointsize > 1.0f) {
565             adjust_x = 0.5;
566          }
567       }
568       else {
569          /* Use (-0.5, -0.5) bias for all prim types.
570           * Regarding line rasterization, this does not seem to satisfy
571           * the Piglit gl-1.0-ortho-pos test but it generally produces
572           * results identical or very similar to VGPU10.
573           */
574          adjust_x = -0.5;
575          adjust_y = -0.5;
576       }
577 
578       if (invertY)
579          adjust_y = -adjust_y;
580 
581       prescale->translate[0] += adjust_x;
582       prescale->translate[1] += adjust_y;
583       prescale->translate[2] = 0.5; /* D3D clip space */
584       prescale->scale[2]     = 0.5; /* D3D clip space */
585    }
586 
587    range_min = viewport->scale[2] * -1.0f + viewport->translate[2];
588    range_max = viewport->scale[2] *  1.0f + viewport->translate[2];
589 
590    /* D3D (and by implication SVGA) doesn't like dealing with zmax
591     * less than zmin.  Detect that case, flip the depth range and
592     * invert our z-scale factor to achieve the same effect.
593     */
594    if (range_min > range_max) {
595       float range_tmp;
596       range_tmp = range_min;
597       range_min = range_max;
598       range_max = range_tmp;
599       prescale->scale[2] = -prescale->scale[2];
600    }
601 
602    /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale.
603     * zmin can be set to -1 when viewport->scale[2] is set to 1 and
604     * viewport->translate[2] is set to 0 in the blit code.
605     */
606    if (range_min < 0.0f) {
607       range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
608       range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
609       prescale->scale[2] *= 2.0f;
610       prescale->translate[2] -= 0.5f;
611    }
612 
613    /* Clamp depth range, making sure it's between 0 and 1 */
614    range_min = CLAMP(range_min, 0.0f, 1.0f);
615    range_max = CLAMP(range_max, 0.0f, 1.0f);
616 
617    if (prescale->enabled) {
618       float H[2];
619       float J[2];
620       int i;
621 
622       SVGA_DBG(DEBUG_VIEWPORT,
623                "prescale %f,%f %fx%f\n",
624                prescale->translate[0],
625                prescale->translate[1],
626                prescale->scale[0],
627                prescale->scale[1]);
628 
629       H[0] = (float)rect.w / 2.0f;
630       H[1] = -(float)rect.h / 2.0f;
631       J[0] = (float)rect.x + (float)rect.w / 2.0f;
632       J[1] = (float)rect.y + (float)rect.h / 2.0f;
633 
634       SVGA_DBG(DEBUG_VIEWPORT,
635                "H %f,%f\n"
636                "J %fx%f\n",
637                H[0],
638                H[1],
639                J[0],
640                J[1]);
641 
642       /* Adjust prescale to take into account the fact that it is
643        * going to be applied prior to the perspective divide and
644        * viewport transformation.
645        *
646        * Vwin = H(Vc/Vc.w) + J
647        *
648        * We want to tweak Vwin with scale and translation from above,
649        * as in:
650        *
651        * Vwin' = S Vwin + T
652        *
653        * But we can only modify the values at Vc.  Plugging all the
654        * above together, and rearranging, eventually we get:
655        *
656        *   Vwin' = H(Vc'/Vc'.w) + J
657        * where:
658        *   Vc' = SVc + KVc.w
659        *   K = (T + (S-1)J) / H
660        *
661        * Overwrite prescale.translate with values for K:
662        */
663       for (i = 0; i < 2; i++) {
664          prescale->translate[i] = ((prescale->translate[i] +
665                                    (prescale->scale[i] - 1.0f) * J[i]) / H[i]);
666       }
667 
668       SVGA_DBG(DEBUG_VIEWPORT,
669                "clipspace %f,%f %fx%f\n",
670                prescale->translate[0],
671                prescale->translate[1],
672                prescale->scale[0],
673                prescale->scale[1]);
674    }
675 
676 out:
677    if (degenerate) {
678       rect.x = 0;
679       rect.y = 0;
680       rect.w = 1;
681       rect.h = 1;
682       prescale->enabled = FALSE;
683    }
684 
685    vp->x = (float) rect.x;
686    vp->y = (float) rect.y;
687    vp->width = (float) rect.w;
688    vp->height = (float) rect.h;
689    vp->minDepth = range_min;
690    vp->maxDepth = range_max;
691 }
692 
693 
694 static enum pipe_error
emit_viewport(struct svga_context * svga,uint64_t dirty)695 emit_viewport( struct svga_context *svga,
696                uint64_t dirty )
697 {
698    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
699    SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS];
700    struct svga_prescale prescale[SVGA3D_DX_MAX_VIEWPORTS];
701    unsigned i;
702    enum pipe_error ret;
703    unsigned max_viewports = svgascreen->max_viewports;
704 
705    for (i = 0; i < max_viewports; i++) {
706       get_viewport_prescale(svga, &svga->curr.viewport[i],
707                             &viewports[i], &prescale[i]);
708    }
709 
710    if (memcmp(viewports, svga->state.hw_clear.viewports,
711               max_viewports * sizeof viewports[0]) != 0) {
712 
713       if (!svga_have_vgpu10(svga)) {
714          SVGA3dRect rect;
715          SVGA3dViewport *vp = &viewports[0];
716 
717          rect.x = (uint32)vp->x;
718          rect.y = (uint32)vp->y;
719          rect.w = (uint32)vp->width;
720          rect.h = (uint32)vp->height;
721 
722          ret = SVGA3D_SetViewport(svga->swc, &rect);
723          if (ret != PIPE_OK)
724             return ret;
725 
726          ret = SVGA3D_SetZRange(svga->swc, vp->minDepth, vp->maxDepth);
727          if (ret != PIPE_OK)
728             return ret;
729 
730          svga->state.hw_clear.viewport = rect;
731          svga->state.hw_clear.depthrange.zmin = vp->minDepth;
732          svga->state.hw_clear.depthrange.zmax = vp->maxDepth;
733       }
734       else {
735          ret = SVGA3D_vgpu10_SetViewports(svga->swc, max_viewports,
736                                           viewports);
737          if (ret != PIPE_OK)
738             return ret;
739       }
740       memcpy(svga->state.hw_clear.viewports, viewports,
741              max_viewports * sizeof viewports[0]);
742    }
743 
744    if (memcmp(prescale, svga->state.hw_clear.prescale,
745               max_viewports * sizeof prescale[0]) != 0) {
746       svga->dirty |= SVGA_NEW_PRESCALE;
747       memcpy(svga->state.hw_clear.prescale, prescale,
748              max_viewports * sizeof prescale[0]);
749 
750       /*
751        * Determine number of unique prescales. This is to minimize the
752        * if check needed in the geometry shader to identify the prescale
753        * for the specified viewport.
754        */
755       unsigned last_prescale = SVGA3D_DX_MAX_VIEWPORTS - 1;
756       unsigned i;
757       for (i = SVGA3D_DX_MAX_VIEWPORTS-1; i > 0; i--) {
758          if (memcmp(&svga->state.hw_clear.prescale[i],
759                     &svga->state.hw_clear.prescale[i-1],
760                     sizeof svga->state.hw_clear.prescale[0])) {
761             break;
762          }
763          last_prescale--;
764       }
765       svga->state.hw_clear.num_prescale = last_prescale + 1;
766    }
767 
768    return PIPE_OK;
769 }
770 
771 
772 struct svga_tracked_state svga_hw_viewport =
773 {
774    "hw viewport state",
775    ( SVGA_NEW_FRAME_BUFFER |
776      SVGA_NEW_VIEWPORT |
777      SVGA_NEW_RAST |
778      SVGA_NEW_REDUCED_PRIMITIVE ),
779    emit_viewport
780 };
781 
782 
783 /***********************************************************************
784  * Scissor state
785  */
786 static enum pipe_error
emit_scissor_rect(struct svga_context * svga,uint64_t dirty)787 emit_scissor_rect( struct svga_context *svga,
788                    uint64_t dirty )
789 {
790    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
791    const struct pipe_scissor_state *scissor = svga->curr.scissor;
792    unsigned max_viewports = svgascreen->max_viewports;
793    enum pipe_error ret;
794 
795    if (memcmp(&svga->state.hw_clear.scissors[0], scissor,
796               max_viewports * sizeof *scissor) != 0) {
797 
798       if (svga_have_vgpu10(svga)) {
799          SVGASignedRect rect[SVGA3D_DX_MAX_VIEWPORTS];
800          unsigned i;
801 
802          for (i = 0; i < max_viewports; i++) {
803             rect[i].left = scissor[i].minx;
804             rect[i].top = scissor[i].miny;
805             rect[i].right = scissor[i].maxx;
806             rect[i].bottom = scissor[i].maxy;
807          }
808 
809          ret = SVGA3D_vgpu10_SetScissorRects(svga->swc, max_viewports, rect);
810       }
811       else {
812          SVGA3dRect rect;
813 
814          rect.x = scissor[0].minx;
815          rect.y = scissor[0].miny;
816          rect.w = scissor[0].maxx - scissor[0].minx; /* + 1 ?? */
817          rect.h = scissor[0].maxy - scissor[0].miny; /* + 1 ?? */
818 
819          ret = SVGA3D_SetScissorRect(svga->swc, &rect);
820       }
821 
822       if (ret != PIPE_OK)
823          return ret;
824 
825       memcpy(svga->state.hw_clear.scissors, scissor,
826              max_viewports * sizeof *scissor);
827    }
828 
829    return PIPE_OK;
830 }
831 
832 struct svga_tracked_state svga_hw_scissor =
833 {
834    "hw scissor state",
835    SVGA_NEW_SCISSOR,
836    emit_scissor_rect
837 };
838 
839 
840 /***********************************************************************
841  * Userclip state
842  */
843 
844 static enum pipe_error
emit_clip_planes(struct svga_context * svga,uint64_t dirty)845 emit_clip_planes( struct svga_context *svga,
846                   uint64_t dirty )
847 {
848    unsigned i;
849    enum pipe_error ret;
850 
851    /* TODO: just emit directly from svga_set_clip_state()?
852     */
853    for (i = 0; i < SVGA3D_MAX_CLIP_PLANES; i++) {
854       /* need to express the plane in D3D-style coordinate space.
855        * GL coords get converted to D3D coords with the matrix:
856        * [ 1  0  0  0 ]
857        * [ 0 -1  0  0 ]
858        * [ 0  0  2  0 ]
859        * [ 0  0 -1  1 ]
860        * Apply that matrix to our plane equation, and invert Y.
861        */
862       float a = svga->curr.clip.ucp[i][0];
863       float b = svga->curr.clip.ucp[i][1];
864       float c = svga->curr.clip.ucp[i][2];
865       float d = svga->curr.clip.ucp[i][3];
866       float plane[4];
867 
868       plane[0] = a;
869       plane[1] = b;
870       plane[2] = 2.0f * c;
871       plane[3] = d - c;
872 
873       if (svga_have_vgpu10(svga)) {
874          //debug_printf("XXX emit DX10 clip plane\n");
875          ret = PIPE_OK;
876       }
877       else {
878          ret = SVGA3D_SetClipPlane(svga->swc, i, plane);
879          if (ret != PIPE_OK)
880             return ret;
881       }
882    }
883 
884    return PIPE_OK;
885 }
886 
887 
888 struct svga_tracked_state svga_hw_clip_planes =
889 {
890    "hw viewport state",
891    SVGA_NEW_CLIP,
892    emit_clip_planes
893 };
894