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 **********************************************************/
27 #include "svga_debug.h"
29 #include "pipe/p_defines.h"
30 #include "util/u_pack_color.h"
31 #include "util/u_surface.h"
33 #include "svga_context.h"
34 #include "svga_state.h"
35 #include "svga_surface.h"
39 * Saving blitter states before doing any blitter operation
42 begin_blit(struct svga_context
*svga
)
44 util_blitter_save_vertex_buffer_slot(svga
->blitter
, svga
->curr
.vb
);
45 util_blitter_save_vertex_elements(svga
->blitter
, (void*)svga
->curr
.velems
);
46 util_blitter_save_vertex_shader(svga
->blitter
, svga
->curr
.vs
);
47 util_blitter_save_geometry_shader(svga
->blitter
, svga
->curr
.gs
);
48 util_blitter_save_so_targets(svga
->blitter
, svga
->num_so_targets
,
49 (struct pipe_stream_output_target
**)svga
->so_targets
);
50 util_blitter_save_rasterizer(svga
->blitter
, (void*)svga
->curr
.rast
);
51 util_blitter_save_viewport(svga
->blitter
, &svga
->curr
.viewport
);
52 util_blitter_save_scissor(svga
->blitter
, &svga
->curr
.scissor
);
53 util_blitter_save_fragment_shader(svga
->blitter
, svga
->curr
.fs
);
54 util_blitter_save_blend(svga
->blitter
, (void*)svga
->curr
.blend
);
55 util_blitter_save_depth_stencil_alpha(svga
->blitter
,
56 (void*)svga
->curr
.depth
);
57 util_blitter_save_stencil_ref(svga
->blitter
, &svga
->curr
.stencil_ref
);
58 util_blitter_save_sample_mask(svga
->blitter
, svga
->curr
.sample_mask
);
63 * Clear the whole color buffer(s) by drawing a quad. For VGPU10 we use
64 * this when clearing integer render targets. We'll also clear the
65 * depth and/or stencil buffers if the clear_buffers mask specifies them.
68 clear_buffers_with_quad(struct svga_context
*svga
,
69 unsigned clear_buffers
,
70 const union pipe_color_union
*color
,
71 double depth
, unsigned stencil
)
73 const struct pipe_framebuffer_state
*fb
= &svga
->curr
.framebuffer
;
76 util_blitter_clear(svga
->blitter
,
77 fb
->width
, fb
->height
,
81 util_framebuffer_get_num_samples(fb
) > 1);
86 * Check if any of the color buffers are integer buffers.
89 is_integer_target(struct pipe_framebuffer_state
*fb
, unsigned buffers
)
93 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
94 if ((buffers
& (PIPE_CLEAR_COLOR0
<< i
)) &&
96 util_format_is_pure_integer(fb
->cbufs
[i
]->format
)) {
105 * Check if the integer values in the clear color can be represented
106 * by floats. If so, we can use the VGPU10 ClearRenderTargetView command.
107 * Otherwise, we need to clear with a quad.
110 ints_fit_in_floats(const union pipe_color_union
*color
)
112 const int max
= 1 << 24;
113 return (color
->i
[0] <= max
&&
114 color
->i
[1] <= max
&&
115 color
->i
[2] <= max
&&
120 static enum pipe_error
121 try_clear(struct svga_context
*svga
,
123 const union pipe_color_union
*color
,
127 enum pipe_error ret
= PIPE_OK
;
128 SVGA3dRect rect
= { 0, 0, 0, 0 };
129 boolean restore_viewport
= FALSE
;
130 SVGA3dClearFlag flags
= 0;
131 struct pipe_framebuffer_state
*fb
= &svga
->curr
.framebuffer
;
132 union util_color uc
= {0};
134 ret
= svga_update_state(svga
, SVGA_STATE_HW_CLEAR
);
138 if (svga
->rebind
.flags
.rendertargets
) {
139 ret
= svga_reemit_framebuffer_bindings(svga
);
140 if (ret
!= PIPE_OK
) {
145 if (buffers
& PIPE_CLEAR_COLOR
) {
146 flags
|= SVGA3D_CLEAR_COLOR
;
147 util_pack_color(color
->f
, PIPE_FORMAT_B8G8R8A8_UNORM
, &uc
);
153 if ((buffers
& PIPE_CLEAR_DEPTHSTENCIL
) && fb
->zsbuf
) {
154 if (buffers
& PIPE_CLEAR_DEPTH
)
155 flags
|= SVGA3D_CLEAR_DEPTH
;
157 if (buffers
& PIPE_CLEAR_STENCIL
)
158 flags
|= SVGA3D_CLEAR_STENCIL
;
160 rect
.w
= MAX2(rect
.w
, fb
->zsbuf
->width
);
161 rect
.h
= MAX2(rect
.h
, fb
->zsbuf
->height
);
164 if (!svga_have_vgpu10(svga
) &&
165 !svga_rects_equal(&rect
, &svga
->state
.hw_clear
.viewport
)) {
166 restore_viewport
= TRUE
;
167 ret
= SVGA3D_SetViewport(svga
->swc
, &rect
);
172 if (svga_have_vgpu10(svga
)) {
173 if (flags
& SVGA3D_CLEAR_COLOR
) {
176 if (is_integer_target(fb
, buffers
) && !ints_fit_in_floats(color
)) {
177 clear_buffers_with_quad(svga
, buffers
, color
, depth
, stencil
);
178 /* We also cleared depth/stencil, so that's done */
179 flags
&= ~(SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
);
182 struct pipe_surface
*rtv
;
184 /* Issue VGPU10 Clear commands */
185 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
186 if ((fb
->cbufs
[i
] == NULL
) ||
187 !(buffers
& (PIPE_CLEAR_COLOR0
<< i
)))
190 rtv
= svga_validate_surface_view(svga
,
191 svga_surface(fb
->cbufs
[i
]));
193 return PIPE_ERROR_OUT_OF_MEMORY
;
195 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
,
202 if (flags
& (SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
)) {
203 struct pipe_surface
*dsv
=
204 svga_validate_surface_view(svga
, svga_surface(fb
->zsbuf
));
206 return PIPE_ERROR_OUT_OF_MEMORY
;
208 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
, flags
,
209 stencil
, (float) depth
);
215 ret
= SVGA3D_ClearRect(svga
->swc
, flags
, uc
.ui
[0], (float) depth
, stencil
,
216 rect
.x
, rect
.y
, rect
.w
, rect
.h
);
221 if (restore_viewport
) {
222 ret
= SVGA3D_SetViewport(svga
->swc
, &svga
->state
.hw_clear
.viewport
);
229 * Clear the given surface to the specified value.
230 * No masking, no scissor (clear entire buffer).
233 svga_clear(struct pipe_context
*pipe
, unsigned buffers
,
234 const union pipe_color_union
*color
,
235 double depth
, unsigned stencil
)
237 struct svga_context
*svga
= svga_context( pipe
);
240 if (buffers
& PIPE_CLEAR_COLOR
) {
241 struct svga_winsys_surface
*h
= NULL
;
242 if (svga
->curr
.framebuffer
.cbufs
[0]) {
243 h
= svga_surface(svga
->curr
.framebuffer
.cbufs
[0])->handle
;
245 SVGA_DBG(DEBUG_DMA
, "clear sid %p\n", h
);
248 /* flush any queued prims (don't want them to appear after the clear!) */
249 svga_hwtnl_flush_retry(svga
);
251 ret
= try_clear( svga
, buffers
, color
, depth
, stencil
);
253 if (ret
== PIPE_ERROR_OUT_OF_MEMORY
) {
254 /* Flush command buffer and retry:
256 svga_context_flush( svga
, NULL
);
258 ret
= try_clear( svga
, buffers
, color
, depth
, stencil
);
262 * Mark target surfaces as dirty
263 * TODO Mark only cleared surfaces.
265 svga_mark_surfaces_dirty(svga
);
267 assert (ret
== PIPE_OK
);
272 svga_clear_texture(struct pipe_context
*pipe
,
273 struct pipe_resource
*res
,
275 const struct pipe_box
*box
,
278 struct svga_context
*svga
= svga_context(pipe
);
279 struct svga_surface
*svga_surface_dst
;
281 struct pipe_surface tmpl
;
282 struct pipe_surface
*surface
;
284 memset(&tmpl
, 0, sizeof(tmpl
));
285 tmpl
.format
= res
->format
;
286 tmpl
.u
.tex
.first_layer
= box
->z
;
287 tmpl
.u
.tex
.last_layer
= box
->z
+ box
->depth
- 1;
288 tmpl
.u
.tex
.level
= level
;
290 surface
= pipe
->create_surface(pipe
, res
, &tmpl
);
291 if (surface
== NULL
) {
292 debug_printf("failed to create surface\n");
295 svga_surface_dst
= svga_surface(surface
);
297 union pipe_color_union color
;
298 const struct util_format_description
*desc
=
299 util_format_description(surface
->format
);
301 if (util_format_is_depth_or_stencil(surface
->format
)) {
304 unsigned clear_flags
= 0;
306 /* If data is NULL, then set depthValue and stencilValue to zeros */
312 util_format_unpack_z_float(surface
->format
, &depth
, data
, 1);
313 util_format_unpack_s_8uint(surface
->format
, &stencil
, data
, 1);
316 if (util_format_has_depth(desc
)) {
317 clear_flags
|= PIPE_CLEAR_DEPTH
;
319 if (util_format_has_stencil(desc
)) {
320 clear_flags
|= PIPE_CLEAR_STENCIL
;
323 /* Setup depth stencil view */
324 struct pipe_surface
*dsv
=
325 svga_validate_surface_view(svga
, svga_surface_dst
);
328 pipe_surface_reference(&surface
, NULL
);
332 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
333 box
->height
== surface
->height
) {
334 /* clearing whole surface, use direct VGPU10 command */
337 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
340 if (ret
!= PIPE_OK
) {
341 /* flush and try again */
342 svga_context_flush(svga
, NULL
);
343 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
346 assert(ret
== PIPE_OK
);
350 /* To clear subtexture use software fallback */
352 util_blitter_save_framebuffer(svga
->blitter
,
353 &svga
->curr
.framebuffer
);
355 util_blitter_clear_depth_stencil(svga
->blitter
,
359 box
->width
, box
->height
);
363 /* non depth-stencil formats */
366 /* If data is NULL, the texture image is filled with zeros */
367 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
370 util_format_unpack_rgba(surface
->format
, color
.ui
, data
, 1);
373 /* Setup render target view */
374 struct pipe_surface
*rtv
=
375 svga_validate_surface_view(svga
, svga_surface_dst
);
378 pipe_surface_reference(&surface
, NULL
);
382 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
383 box
->height
== surface
->height
) {
384 struct pipe_framebuffer_state
*curr
= &svga
->curr
.framebuffer
;
386 if (is_integer_target(curr
, PIPE_CLEAR_COLOR
) &&
387 !ints_fit_in_floats(&color
)) {
388 /* To clear full texture with integer format */
389 clear_buffers_with_quad(svga
, PIPE_CLEAR_COLOR
, &color
, 0.0, 0);
392 /* clearing whole surface using VGPU10 command */
393 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
395 if (ret
!= PIPE_OK
) {
396 svga_context_flush(svga
,NULL
);
397 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
399 assert(ret
== PIPE_OK
);
404 /* To clear subtexture use software fallback */
407 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
408 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
409 * util_clear_render_target() for PIPE_TEXTURE_3D.
411 if (rtv
->texture
->target
!= PIPE_TEXTURE_3D
&&
412 pipe
->screen
->is_format_supported(pipe
->screen
, rtv
->format
,
413 rtv
->texture
->target
,
414 rtv
->texture
->nr_samples
,
415 rtv
->texture
->nr_storage_samples
,
416 PIPE_BIND_RENDER_TARGET
)) {
417 /* clear with quad drawing */
418 util_blitter_save_framebuffer(svga
->blitter
,
419 &svga
->curr
.framebuffer
);
421 util_blitter_clear_render_target(svga
->blitter
,
425 box
->width
, box
->height
);
428 /* clear with map/write/unmap */
430 /* store layer values */
431 unsigned first_layer
= rtv
->u
.tex
.first_layer
;
432 unsigned last_layer
= rtv
->u
.tex
.last_layer
;
433 unsigned box_depth
= last_layer
- first_layer
+ 1;
435 for (unsigned i
= 0; i
< box_depth
; i
++) {
436 rtv
->u
.tex
.first_layer
= rtv
->u
.tex
.last_layer
=
438 util_clear_render_target(pipe
, rtv
, &color
, box
->x
, box
->y
,
439 box
->width
, box
->height
);
441 /* restore layer values */
442 rtv
->u
.tex
.first_layer
= first_layer
;
443 rtv
->u
.tex
.last_layer
= last_layer
;
447 pipe_surface_reference(&surface
, NULL
);
451 * \brief Clear the whole render target using vgpu10 functionality
453 * \param svga[in] The svga context
454 * \param dst[in] The surface to clear
455 * \param color[in] Clear color
456 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
457 * command submission resources.
459 static enum pipe_error
460 svga_try_clear_render_target(struct svga_context
*svga
,
461 struct pipe_surface
*dst
,
462 const union pipe_color_union
*color
)
464 struct pipe_surface
*rtv
=
465 svga_validate_surface_view(svga
, svga_surface(dst
));
468 return PIPE_ERROR_OUT_OF_MEMORY
;
470 return SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
, color
->f
);
474 * \brief Clear part of render target using gallium blitter utilities
476 * \param svga[in] The svga context
477 * \param dst[in] The surface to clear
478 * \param color[in] Clear color
479 * \param dstx[in] Clear region left
480 * \param dsty[in] Clear region top
481 * \param width[in] Clear region width
482 * \param height[in] Clear region height
485 svga_blitter_clear_render_target(struct svga_context
*svga
,
486 struct pipe_surface
*dst
,
487 const union pipe_color_union
*color
,
488 unsigned dstx
, unsigned dsty
,
489 unsigned width
, unsigned height
)
492 util_blitter_save_framebuffer(svga
->blitter
, &svga
->curr
.framebuffer
);
494 util_blitter_clear_render_target(svga
->blitter
, dst
, color
,
495 dstx
, dsty
, width
, height
);
500 * \brief Clear render target pipe callback
502 * \param pipe[in] The pipe context
503 * \param dst[in] The surface to clear
504 * \param color[in] Clear color
505 * \param dstx[in] Clear region left
506 * \param dsty[in] Clear region top
507 * \param width[in] Clear region width
508 * \param height[in] Clear region height
509 * \param render_condition_enabled[in] Whether to use conditional rendering
510 * to clear (if elsewhere enabled).
513 svga_clear_render_target(struct pipe_context
*pipe
,
514 struct pipe_surface
*dst
,
515 const union pipe_color_union
*color
,
516 unsigned dstx
, unsigned dsty
,
517 unsigned width
, unsigned height
,
518 bool render_condition_enabled
)
520 struct svga_context
*svga
= svga_context( pipe
);
522 svga_toggle_render_condition(svga
, render_condition_enabled
, FALSE
);
523 if (!svga_have_vgpu10(svga
) || dstx
!= 0 || dsty
!= 0 ||
524 width
!= dst
->width
|| height
!= dst
->height
) {
525 svga_blitter_clear_render_target(svga
, dst
, color
, dstx
, dsty
, width
,
530 ret
= svga_try_clear_render_target(svga
, dst
, color
);
531 if (ret
== PIPE_ERROR_OUT_OF_MEMORY
) {
532 svga_context_flush( svga
, NULL
);
533 ret
= svga_try_clear_render_target(svga
, dst
, color
);
536 assert (ret
== PIPE_OK
);
538 svga_toggle_render_condition(svga
, render_condition_enabled
, TRUE
);
541 void svga_init_clear_functions(struct svga_context
*svga
)
543 svga
->pipe
.clear_render_target
= svga_clear_render_target
;
544 svga
->pipe
.clear_texture
= svga_clear_texture
;
545 svga
->pipe
.clear
= svga_clear
;