1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
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"
31 #include "svga_context.h"
32 #include "svga_state.h"
34 #include "svga_debug.h"
35 #include "svga_screen.h"
36 #include "svga_surface.h"
37 #include "svga_resource_texture.h"
41 * flush our command buffer after the 8th distinct render target
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.
49 #define MAX_RT_PER_BATCH 8
53 static enum pipe_error
54 emit_fb_vgpu9(struct svga_context
*svga
)
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
;
63 assert(!svga_have_vgpu10(svga
));
66 * We need to reemit non-null surface bindings, even when they are not
67 * dirty, to ensure that the resources are paged in.
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
;
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
);
79 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_COLOR0
+ i
,
84 pipe_surface_reference(&hw
->cbufs
[i
], curr
->cbufs
[i
]);
87 /* Set the rendered-to flag */
88 struct pipe_surface
*s
= curr
->cbufs
[i
];
90 svga_set_texture_rendered_to(svga_texture(s
->texture
),
91 s
->u
.tex
.first_layer
, s
->u
.tex
.level
);
95 if ((curr
->zsbuf
!= hw
->zsbuf
) || (reemit
&& hw
->zsbuf
)) {
96 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_DEPTH
, curr
->zsbuf
);
100 /* 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
);
105 util_format_is_depth_and_stencil(curr
->zsbuf
->format
)) {
106 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_STENCIL
,
112 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_STENCIL
, NULL
);
117 pipe_surface_reference(&hw
->zsbuf
, curr
->zsbuf
);
119 /* Set the rendered-to flag */
120 struct pipe_surface
*s
= curr
->zsbuf
;
122 svga_set_texture_rendered_to(svga_texture(s
->texture
),
123 s
->u
.tex
.first_layer
, s
->u
.tex
.level
);
132 * Rebind rendertargets.
134 * Similar to emit_framebuffer, but without any state checking/update.
136 * Called at the beginning of every new command buffer to ensure that
137 * non-dirty rendertargets are properly paged-in.
139 static enum pipe_error
140 svga_reemit_framebuffer_bindings_vgpu9(struct svga_context
*svga
)
142 struct svga_screen
*svgascreen
= svga_screen(svga
->pipe
.screen
);
143 struct pipe_framebuffer_state
*hw
= &svga
->state
.hw_clear
.framebuffer
;
147 assert(!svga_have_vgpu10(svga
));
149 for (i
= 0; i
< svgascreen
->max_color_buffers
; i
++) {
151 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_COLOR0
+ i
,
153 if (ret
!= PIPE_OK
) {
160 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_DEPTH
, hw
->zsbuf
);
161 if (ret
!= PIPE_OK
) {
166 util_format_is_depth_and_stencil(hw
->zsbuf
->format
)) {
167 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_STENCIL
, hw
->zsbuf
);
168 if (ret
!= PIPE_OK
) {
173 ret
= SVGA3D_SetRenderTarget(svga
->swc
, SVGA3D_RT_STENCIL
, NULL
);
174 if (ret
!= PIPE_OK
) {
185 static enum pipe_error
186 emit_fb_vgpu10(struct svga_context
*svga
)
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
);
196 enum pipe_error ret
= PIPE_OK
;
198 assert(svga_have_vgpu10(svga
));
200 /* Reset the has_backed_views flag.
201 * The flag is set in svga_validate_surface_view() if
202 * a backed surface view is used.
204 svga
->state
.hw_draw
.has_backed_views
= FALSE
;
206 /* 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.
211 for (i
= 0; i
< num_color
; i
++) {
212 if (curr
->cbufs
[i
]) {
213 struct pipe_surface
*s
= curr
->cbufs
[i
];
215 if (curr
->cbufs
[i
] != hw
->cbufs
[i
]) {
216 rtv
[i
] = svga_validate_surface_view(svga
, svga_surface(s
));
217 if (rtv
[i
] == NULL
) {
218 return PIPE_ERROR_OUT_OF_MEMORY
;
221 rtv
[i
] = svga
->state
.hw_clear
.rtv
[i
];
224 assert(svga_surface(rtv
[i
])->view_id
!= SVGA3D_INVALID_ID
);
227 /* Set the rendered-to flag */
228 svga_set_texture_rendered_to(svga_texture(s
->texture
),
229 s
->u
.tex
.first_layer
, s
->u
.tex
.level
);
236 /* Setup depth stencil view */
238 struct pipe_surface
*s
= curr
->zsbuf
;
240 if (curr
->zsbuf
!= hw
->zsbuf
) {
241 dsv
= svga_validate_surface_view(svga
, svga_surface(curr
->zsbuf
));
243 return PIPE_ERROR_OUT_OF_MEMORY
;
246 dsv
= svga
->state
.hw_clear
.dsv
;
249 /* Set the rendered-to flag */
250 svga_set_texture_rendered_to(svga_texture(s
->texture
),
251 s
->u
.tex
.first_layer
, s
->u
.tex
.level
);
257 /* avoid emitting redundant SetRenderTargets command */
258 if ((num_color
!= svga
->state
.hw_clear
.num_rendertargets
) ||
259 (dsv
!= svga
->state
.hw_clear
.dsv
) ||
260 memcmp(rtv
, svga
->state
.hw_clear
.rtv
, num_color
* sizeof(rtv
[0]))) {
262 ret
= SVGA3D_vgpu10_SetRenderTargets(svga
->swc
, num_color
, rtv
, dsv
);
266 /* number of render targets sent to the device, not including trailing
267 * unbound render targets.
269 for (i
= 0; i
< ss
->max_color_buffers
; i
++) {
270 if (hw
->cbufs
[i
] != curr
->cbufs
[i
]) {
271 /* propagate the backed view surface before unbinding it */
272 if (hw
->cbufs
[i
] && svga_surface(hw
->cbufs
[i
])->backed
) {
273 svga_propagate_surface(svga
,
274 &svga_surface(hw
->cbufs
[i
])->backed
->base
,
277 else if (svga
->state
.hw_clear
.rtv
[i
] != hw
->cbufs
[i
] &&
278 svga
->state
.hw_clear
.rtv
[i
]) {
279 /* Free the alternate surface view when it is unbound. */
280 svga
->pipe
.surface_destroy(&svga
->pipe
, svga
->state
.hw_clear
.rtv
[i
]);
282 pipe_surface_reference(&hw
->cbufs
[i
], curr
->cbufs
[i
]);
285 svga
->state
.hw_clear
.num_rendertargets
= last_rtv
+ 1;
286 memcpy(svga
->state
.hw_clear
.rtv
, rtv
, num_color
* sizeof(rtv
[0]));
287 hw
->nr_cbufs
= curr
->nr_cbufs
;
289 if (hw
->zsbuf
!= curr
->zsbuf
) {
290 /* propagate the backed view surface before unbinding it */
291 if (hw
->zsbuf
&& svga_surface(hw
->zsbuf
)->backed
) {
292 svga_propagate_surface(svga
,
293 &svga_surface(hw
->zsbuf
)->backed
->base
,
296 else if (svga
->state
.hw_clear
.dsv
!= hw
->zsbuf
&& svga
->state
.hw_clear
.dsv
) {
297 /* Free the alternate surface view when it is unbound. */
298 svga
->pipe
.surface_destroy(&svga
->pipe
, svga
->state
.hw_clear
.dsv
);
300 pipe_surface_reference(&hw
->zsbuf
, curr
->zsbuf
);
302 svga
->state
.hw_clear
.dsv
= dsv
;
309 static enum pipe_error
310 emit_framebuffer(struct svga_context
*svga
, uint64_t dirty
)
312 if (svga_have_vgpu10(svga
)) {
313 return emit_fb_vgpu10(svga
);
316 return emit_fb_vgpu9(svga
);
322 * Rebind rendertargets.
324 * Similar to emit_framebuffer, but without any state checking/update.
326 * Called at the beginning of every new command buffer to ensure that
327 * non-dirty rendertargets are properly paged-in.
330 svga_reemit_framebuffer_bindings(struct svga_context
*svga
)
334 assert(svga
->rebind
.flags
.rendertargets
);
336 if (svga_have_vgpu10(svga
)) {
337 ret
= emit_fb_vgpu10(svga
);
340 ret
= svga_reemit_framebuffer_bindings_vgpu9(svga
);
343 svga
->rebind
.flags
.rendertargets
= FALSE
;
350 * Send a private allocation command to page in rendertargets resource.
353 svga_rebind_framebuffer_bindings(struct svga_context
*svga
)
355 struct svga_hw_clear_state
*hw
= &svga
->state
.hw_clear
;
359 assert(svga_have_vgpu10(svga
));
361 if (!svga
->rebind
.flags
.rendertargets
)
364 for (i
= 0; i
< hw
->num_rendertargets
; i
++) {
366 ret
= svga
->swc
->resource_rebind(svga
->swc
,
367 svga_surface(hw
->rtv
[i
])->handle
,
376 ret
= svga
->swc
->resource_rebind(svga
->swc
,
377 svga_surface(hw
->dsv
)->handle
,
384 svga
->rebind
.flags
.rendertargets
= 0;
390 struct svga_tracked_state svga_hw_framebuffer
=
392 "hw framebuffer state",
393 SVGA_NEW_FRAME_BUFFER
,
400 /***********************************************************************
404 get_viewport_prescale(struct svga_context
*svga
,
405 struct pipe_viewport_state
*viewport
,
407 struct svga_prescale
*prescale
)
411 /* Not sure if this state is relevant with POSITIONT. Probably
412 * not, but setting to 0,1 avoids some state pingponging.
414 float range_min
= 0.0;
415 float range_max
= 1.0;
417 boolean degenerate
= FALSE
;
418 boolean invertY
= FALSE
;
420 float fb_width
= (float) svga
->curr
.framebuffer
.width
;
421 float fb_height
= (float) svga
->curr
.framebuffer
.height
;
423 float fx
= viewport
->scale
[0] * -1.0f
+ viewport
->translate
[0];
424 float fy
= flip
* viewport
->scale
[1] * -1.0f
+ viewport
->translate
[1];
425 float fw
= viewport
->scale
[0] * 2.0f
;
426 float fh
= flip
* viewport
->scale
[1] * 2.0f
;
428 memset(prescale
, 0, sizeof(*prescale
));
430 /* Examine gallium viewport transformation and produce a screen
431 * rectangle and possibly vertex shader pre-transformation to
432 * get the same results.
435 SVGA_DBG(DEBUG_VIEWPORT
,
436 "\ninitial %f,%f %fx%f\n",
442 prescale
->scale
[0] = 1.0;
443 prescale
->scale
[1] = 1.0;
444 prescale
->scale
[2] = 1.0;
445 prescale
->scale
[3] = 1.0;
446 prescale
->translate
[0] = 0;
447 prescale
->translate
[1] = 0;
448 prescale
->translate
[2] = 0;
449 prescale
->translate
[3] = 0;
451 /* Enable prescale to adjust vertex positions to match
452 VGPU10 convention only if rasterization is enabled.
454 if (svga
->curr
.rast
&& svga
->curr
.rast
->templ
.rasterizer_discard
) {
458 prescale
->enabled
= TRUE
;
462 prescale
->scale
[0] *= -1.0f
;
463 prescale
->translate
[0] += -fw
;
465 fx
= viewport
->scale
[0] * 1.0f
+ viewport
->translate
[0];
469 if (svga_have_vgpu10(svga
)) {
470 /* floating point viewport params below */
471 prescale
->translate
[1] = fh
+ fy
* 2.0f
;
474 /* integer viewport params below */
475 prescale
->translate
[1] = fh
- 1.0f
+ fy
* 2.0f
;
479 prescale
->scale
[1] = -1.0f
;
484 prescale
->translate
[0] += fx
;
485 prescale
->scale
[0] *= fw
/ (fw
+ fx
);
492 prescale
->translate
[1] -= fy
;
495 prescale
->translate
[1] += fy
;
497 prescale
->scale
[1] *= fh
/ (fh
+ fy
);
502 if (fx
+ fw
> fb_width
) {
503 prescale
->scale
[0] *= fw
/ (fb_width
- fx
);
504 prescale
->translate
[0] -= fx
* (fw
/ (fb_width
- fx
));
505 prescale
->translate
[0] += fx
;
509 if (fy
+ fh
> fb_height
) {
510 prescale
->scale
[1] *= fh
/ (fb_height
- fy
);
512 float in
= fb_height
- fy
; /* number of vp pixels inside view */
513 float out
= fy
+ fh
- fb_height
; /* number of vp pixels out of view */
514 prescale
->translate
[1] += fy
* out
/ in
;
517 prescale
->translate
[1] -= fy
* (fh
/ (fb_height
- fy
));
518 prescale
->translate
[1] += fy
;
523 if (fw
< 0 || fh
< 0) {
524 fw
= fh
= fx
= fy
= 0;
529 /* D3D viewport is integer space. Convert fx,fy,etc. to
532 * TODO: adjust pretranslate correct for any subpixel error
533 * introduced converting to integers.
535 rect
.x
= (uint32
) fx
;
536 rect
.y
= (uint32
) fy
;
537 rect
.w
= (uint32
) fw
;
538 rect
.h
= (uint32
) fh
;
540 SVGA_DBG(DEBUG_VIEWPORT
,
541 "viewport error %f,%f %fx%f\n",
542 fabs((float)rect
.x
- fx
),
543 fabs((float)rect
.y
- fy
),
544 fabs((float)rect
.w
- fw
),
545 fabs((float)rect
.h
- fh
));
547 SVGA_DBG(DEBUG_VIEWPORT
,
548 "viewport %d,%d %dx%d\n",
554 /* Finally, to get GL rasterization rules, need to tweak the
555 * screen-space coordinates slightly relative to D3D which is
556 * what hardware implements natively.
558 if (svga
->curr
.rast
&& svga
->curr
.rast
->templ
.half_pixel_center
) {
559 float adjust_x
= 0.0;
560 float adjust_y
= 0.0;
562 if (svga_have_vgpu10(svga
)) {
563 /* Normally, we don't have to do any sub-pixel coordinate
564 * adjustments for VGPU10. But when we draw wide points with
565 * a GS we need an X adjustment in order to be conformant.
567 if (svga
->curr
.reduced_prim
== PIPE_PRIM_POINTS
&&
568 svga
->curr
.rast
->pointsize
> 1.0f
) {
573 /* Use (-0.5, -0.5) bias for all prim types.
574 * Regarding line rasterization, this does not seem to satisfy
575 * the Piglit gl-1.0-ortho-pos test but it generally produces
576 * results identical or very similar to VGPU10.
583 adjust_y
= -adjust_y
;
585 prescale
->translate
[0] += adjust_x
;
586 prescale
->translate
[1] += adjust_y
;
587 prescale
->translate
[2] = 0.5; /* D3D clip space */
588 prescale
->scale
[2] = 0.5; /* D3D clip space */
591 range_min
= viewport
->scale
[2] * -1.0f
+ viewport
->translate
[2];
592 range_max
= viewport
->scale
[2] * 1.0f
+ viewport
->translate
[2];
594 /* D3D (and by implication SVGA) doesn't like dealing with zmax
595 * less than zmin. Detect that case, flip the depth range and
596 * invert our z-scale factor to achieve the same effect.
598 if (range_min
> range_max
) {
600 range_tmp
= range_min
;
601 range_min
= range_max
;
602 range_max
= range_tmp
;
603 prescale
->scale
[2] = -prescale
->scale
[2];
606 /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale.
607 * zmin can be set to -1 when viewport->scale[2] is set to 1 and
608 * viewport->translate[2] is set to 0 in the blit code.
610 if (range_min
< 0.0f
) {
611 range_min
= -0.5f
* viewport
->scale
[2] + 0.5f
+ viewport
->translate
[2];
612 range_max
= 0.5f
* viewport
->scale
[2] + 0.5f
+ viewport
->translate
[2];
613 prescale
->scale
[2] *= 2.0f
;
614 prescale
->translate
[2] -= 0.5f
;
617 if (prescale
->enabled
) {
622 SVGA_DBG(DEBUG_VIEWPORT
,
623 "prescale %f,%f %fx%f\n",
624 prescale
->translate
[0],
625 prescale
->translate
[1],
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
;
634 SVGA_DBG(DEBUG_VIEWPORT
,
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.
646 * Vwin = H(Vc/Vc.w) + J
648 * We want to tweak Vwin with scale and translation from above,
653 * But we can only modify the values at Vc. Plugging all the
654 * above together, and rearranging, eventually we get:
656 * Vwin' = H(Vc'/Vc'.w) + J
659 * K = (T + (S-1)J) / H
661 * Overwrite prescale.translate with values for K:
663 for (i
= 0; i
< 2; i
++) {
664 prescale
->translate
[i
] = ((prescale
->translate
[i
] +
665 (prescale
->scale
[i
] - 1.0f
) * J
[i
]) / H
[i
]);
668 SVGA_DBG(DEBUG_VIEWPORT
,
669 "clipspace %f,%f %fx%f\n",
670 prescale
->translate
[0],
671 prescale
->translate
[1],
682 prescale
->enabled
= FALSE
;
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
;
694 static enum pipe_error
695 emit_viewport( struct svga_context
*svga
,
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
];
703 unsigned max_viewports
= svgascreen
->max_viewports
;
705 for (i
= 0; i
< max_viewports
; i
++) {
706 get_viewport_prescale(svga
, &svga
->curr
.viewport
[i
],
707 &viewports
[i
], &prescale
[i
]);
710 if (memcmp(viewports
, svga
->state
.hw_clear
.viewports
,
711 max_viewports
* sizeof viewports
[0]) != 0) {
713 if (!svga_have_vgpu10(svga
)) {
715 SVGA3dViewport
*vp
= &viewports
[0];
717 rect
.x
= (uint32
)vp
->x
;
718 rect
.y
= (uint32
)vp
->y
;
719 rect
.w
= (uint32
)vp
->width
;
720 rect
.h
= (uint32
)vp
->height
;
722 ret
= SVGA3D_SetViewport(svga
->swc
, &rect
);
726 ret
= SVGA3D_SetZRange(svga
->swc
, vp
->minDepth
, vp
->maxDepth
);
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
;
735 ret
= SVGA3D_vgpu10_SetViewports(svga
->swc
, max_viewports
,
740 memcpy(svga
->state
.hw_clear
.viewports
, viewports
,
741 max_viewports
* sizeof viewports
[0]);
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]);
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.
755 unsigned last_prescale
= SVGA3D_DX_MAX_VIEWPORTS
- 1;
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])) {
765 svga
->state
.hw_clear
.num_prescale
= last_prescale
+ 1;
772 struct svga_tracked_state svga_hw_viewport
=
775 ( SVGA_NEW_FRAME_BUFFER
|
778 SVGA_NEW_REDUCED_PRIMITIVE
),
783 /***********************************************************************
786 static enum pipe_error
787 emit_scissor_rect( struct svga_context
*svga
,
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
;
795 if (memcmp(&svga
->state
.hw_clear
.scissors
[0], scissor
,
796 max_viewports
* sizeof *scissor
) != 0) {
798 if (svga_have_vgpu10(svga
)) {
799 SVGASignedRect rect
[SVGA3D_DX_MAX_VIEWPORTS
];
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
;
809 ret
= SVGA3D_vgpu10_SetScissorRects(svga
->swc
, max_viewports
, rect
);
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 ?? */
819 ret
= SVGA3D_SetScissorRect(svga
->swc
, &rect
);
825 memcpy(svga
->state
.hw_clear
.scissors
, scissor
,
826 max_viewports
* sizeof *scissor
);
832 struct svga_tracked_state svga_hw_scissor
=
840 /***********************************************************************
844 static enum pipe_error
845 emit_clip_planes( struct svga_context
*svga
,
851 /* TODO: just emit directly from svga_set_clip_state()?
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:
860 * Apply that matrix to our plane equation, and invert Y.
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];
873 if (svga_have_vgpu10(svga
)) {
874 //debug_printf("XXX emit DX10 clip plane\n");
878 ret
= SVGA3D_SetClipPlane(svga
->swc
, i
, plane
);
888 struct svga_tracked_state svga_hw_clip_planes
=