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
,
85 * Check if any of the color buffers are integer buffers.
88 is_integer_target(struct pipe_framebuffer_state
*fb
, unsigned buffers
)
92 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
93 if ((buffers
& (PIPE_CLEAR_COLOR0
<< i
)) &&
95 util_format_is_pure_integer(fb
->cbufs
[i
]->format
)) {
104 * Check if the integer values in the clear color can be represented
105 * by floats. If so, we can use the VGPU10 ClearRenderTargetView command.
106 * Otherwise, we need to clear with a quad.
109 ints_fit_in_floats(const union pipe_color_union
*color
)
111 const int max
= 1 << 24;
112 return (color
->i
[0] <= max
&&
113 color
->i
[1] <= max
&&
114 color
->i
[2] <= max
&&
119 static enum pipe_error
120 try_clear(struct svga_context
*svga
,
122 const union pipe_color_union
*color
,
126 enum pipe_error ret
= PIPE_OK
;
127 SVGA3dRect rect
= { 0, 0, 0, 0 };
128 boolean restore_viewport
= FALSE
;
129 SVGA3dClearFlag flags
= 0;
130 struct pipe_framebuffer_state
*fb
= &svga
->curr
.framebuffer
;
131 union util_color uc
= {0};
133 ret
= svga_update_state(svga
, SVGA_STATE_HW_CLEAR
);
137 if (svga
->rebind
.flags
.rendertargets
) {
138 ret
= svga_reemit_framebuffer_bindings(svga
);
139 if (ret
!= PIPE_OK
) {
144 if (buffers
& PIPE_CLEAR_COLOR
) {
145 flags
|= SVGA3D_CLEAR_COLOR
;
146 util_pack_color(color
->f
, PIPE_FORMAT_B8G8R8A8_UNORM
, &uc
);
152 if ((buffers
& PIPE_CLEAR_DEPTHSTENCIL
) && fb
->zsbuf
) {
153 if (buffers
& PIPE_CLEAR_DEPTH
)
154 flags
|= SVGA3D_CLEAR_DEPTH
;
156 if (buffers
& PIPE_CLEAR_STENCIL
)
157 flags
|= SVGA3D_CLEAR_STENCIL
;
159 rect
.w
= MAX2(rect
.w
, fb
->zsbuf
->width
);
160 rect
.h
= MAX2(rect
.h
, fb
->zsbuf
->height
);
163 if (!svga_have_vgpu10(svga
) &&
164 !svga_rects_equal(&rect
, &svga
->state
.hw_clear
.viewport
)) {
165 restore_viewport
= TRUE
;
166 ret
= SVGA3D_SetViewport(svga
->swc
, &rect
);
171 if (svga_have_vgpu10(svga
)) {
172 if (flags
& SVGA3D_CLEAR_COLOR
) {
175 if (is_integer_target(fb
, buffers
) && !ints_fit_in_floats(color
)) {
176 clear_buffers_with_quad(svga
, buffers
, color
, depth
, stencil
);
177 /* We also cleared depth/stencil, so that's done */
178 flags
&= ~(SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
);
181 struct pipe_surface
*rtv
;
183 /* Issue VGPU10 Clear commands */
184 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
185 if ((fb
->cbufs
[i
] == NULL
) ||
186 !(buffers
& (PIPE_CLEAR_COLOR0
<< i
)))
189 rtv
= svga_validate_surface_view(svga
,
190 svga_surface(fb
->cbufs
[i
]));
192 return PIPE_ERROR_OUT_OF_MEMORY
;
194 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
,
201 if (flags
& (SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
)) {
202 struct pipe_surface
*dsv
=
203 svga_validate_surface_view(svga
, svga_surface(fb
->zsbuf
));
205 return PIPE_ERROR_OUT_OF_MEMORY
;
207 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
, flags
,
208 stencil
, (float) depth
);
214 ret
= SVGA3D_ClearRect(svga
->swc
, flags
, uc
.ui
[0], (float) depth
, stencil
,
215 rect
.x
, rect
.y
, rect
.w
, rect
.h
);
220 if (restore_viewport
) {
221 ret
= SVGA3D_SetViewport(svga
->swc
, &svga
->state
.hw_clear
.viewport
);
228 * Clear the given surface to the specified value.
229 * No masking, no scissor (clear entire buffer).
232 svga_clear(struct pipe_context
*pipe
, unsigned buffers
,
233 const union pipe_color_union
*color
,
234 double depth
, unsigned stencil
)
236 struct svga_context
*svga
= svga_context( pipe
);
239 if (buffers
& PIPE_CLEAR_COLOR
) {
240 struct svga_winsys_surface
*h
= NULL
;
241 if (svga
->curr
.framebuffer
.cbufs
[0]) {
242 h
= svga_surface(svga
->curr
.framebuffer
.cbufs
[0])->handle
;
244 SVGA_DBG(DEBUG_DMA
, "clear sid %p\n", h
);
247 /* flush any queued prims (don't want them to appear after the clear!) */
248 svga_hwtnl_flush_retry(svga
);
250 ret
= try_clear( svga
, buffers
, color
, depth
, stencil
);
252 if (ret
== PIPE_ERROR_OUT_OF_MEMORY
) {
253 /* Flush command buffer and retry:
255 svga_context_flush( svga
, NULL
);
257 ret
= try_clear( svga
, buffers
, color
, depth
, stencil
);
261 * Mark target surfaces as dirty
262 * TODO Mark only cleared surfaces.
264 svga_mark_surfaces_dirty(svga
);
266 assert (ret
== PIPE_OK
);
271 svga_clear_texture(struct pipe_context
*pipe
,
272 struct pipe_resource
*res
,
274 const struct pipe_box
*box
,
277 struct svga_context
*svga
= svga_context(pipe
);
278 struct svga_surface
*svga_surface_dst
;
280 struct pipe_surface tmpl
;
281 struct pipe_surface
*surface
;
283 memset(&tmpl
, 0, sizeof(tmpl
));
284 tmpl
.format
= res
->format
;
285 tmpl
.u
.tex
.first_layer
= box
->z
;
286 tmpl
.u
.tex
.last_layer
= box
->z
+ box
->depth
- 1;
287 tmpl
.u
.tex
.level
= level
;
289 surface
= pipe
->create_surface(pipe
, res
, &tmpl
);
290 if (surface
== NULL
) {
291 debug_printf("failed to create surface\n");
294 svga_surface_dst
= svga_surface(surface
);
296 union pipe_color_union color
;
297 const struct util_format_description
*desc
=
298 util_format_description(surface
->format
);
300 if (util_format_is_depth_or_stencil(surface
->format
)) {
303 unsigned clear_flags
= 0;
305 /* If data is NULL, then set depthValue and stencilValue to zeros */
311 desc
->unpack_z_float(&depth
, 0, data
, 0, 1, 1);
312 desc
->unpack_s_8uint(&stencil
, 0, data
, 0, 1, 1);
315 if (util_format_has_depth(desc
)) {
316 clear_flags
|= PIPE_CLEAR_DEPTH
;
318 if (util_format_has_stencil(desc
)) {
319 clear_flags
|= PIPE_CLEAR_STENCIL
;
322 /* Setup depth stencil view */
323 struct pipe_surface
*dsv
=
324 svga_validate_surface_view(svga
, svga_surface_dst
);
327 pipe_surface_reference(&surface
, NULL
);
331 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
332 box
->height
== surface
->height
) {
333 /* clearing whole surface, use direct VGPU10 command */
336 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
339 if (ret
!= PIPE_OK
) {
340 /* flush and try again */
341 svga_context_flush(svga
, NULL
);
342 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
345 assert(ret
== PIPE_OK
);
349 /* To clear subtexture use software fallback */
351 util_blitter_save_framebuffer(svga
->blitter
,
352 &svga
->curr
.framebuffer
);
354 util_blitter_clear_depth_stencil(svga
->blitter
,
358 box
->width
, box
->height
);
362 /* non depth-stencil formats */
365 /* If data is NULL, the texture image is filled with zeros */
366 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
369 if (util_format_is_pure_sint(surface
->format
)) {
371 desc
->unpack_rgba_sint(color
.i
, 0, data
, 0, 1, 1);
373 else if (util_format_is_pure_uint(surface
->format
)) {
374 /* unsigned integer */
375 desc
->unpack_rgba_uint(color
.ui
, 0, data
, 0, 1, 1);
379 desc
->unpack_rgba_float(color
.f
, 0, data
, 0, 1, 1);
383 /* Setup render target view */
384 struct pipe_surface
*rtv
=
385 svga_validate_surface_view(svga
, svga_surface_dst
);
388 pipe_surface_reference(&surface
, NULL
);
392 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
393 box
->height
== surface
->height
) {
394 struct pipe_framebuffer_state
*curr
= &svga
->curr
.framebuffer
;
396 if (is_integer_target(curr
, PIPE_CLEAR_COLOR
) &&
397 !ints_fit_in_floats(&color
)) {
398 /* To clear full texture with integer format */
399 clear_buffers_with_quad(svga
, PIPE_CLEAR_COLOR
, &color
, 0.0, 0);
402 /* clearing whole surface using VGPU10 command */
403 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
405 if (ret
!= PIPE_OK
) {
406 svga_context_flush(svga
,NULL
);
407 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
409 assert(ret
== PIPE_OK
);
414 /* To clear subtexture use software fallback */
417 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
418 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
419 * util_clear_render_target() for PIPE_TEXTURE_3D.
421 if (rtv
->texture
->target
!= PIPE_TEXTURE_3D
&&
422 pipe
->screen
->is_format_supported(pipe
->screen
, rtv
->format
,
423 rtv
->texture
->target
,
424 rtv
->texture
->nr_samples
,
425 rtv
->texture
->nr_storage_samples
,
426 PIPE_BIND_RENDER_TARGET
)) {
427 /* clear with quad drawing */
428 util_blitter_save_framebuffer(svga
->blitter
,
429 &svga
->curr
.framebuffer
);
431 util_blitter_clear_render_target(svga
->blitter
,
435 box
->width
, box
->height
);
438 /* clear with map/write/unmap */
440 /* store layer values */
441 unsigned first_layer
= rtv
->u
.tex
.first_layer
;
442 unsigned last_layer
= rtv
->u
.tex
.last_layer
;
443 unsigned box_depth
= last_layer
- first_layer
+ 1;
445 for (unsigned i
= 0; i
< box_depth
; i
++) {
446 rtv
->u
.tex
.first_layer
= rtv
->u
.tex
.last_layer
=
448 util_clear_render_target(pipe
, rtv
, &color
, box
->x
, box
->y
,
449 box
->width
, box
->height
);
451 /* restore layer values */
452 rtv
->u
.tex
.first_layer
= first_layer
;
453 rtv
->u
.tex
.last_layer
= last_layer
;
457 pipe_surface_reference(&surface
, NULL
);
461 * \brief Clear the whole render target using vgpu10 functionality
463 * \param svga[in] The svga context
464 * \param dst[in] The surface to clear
465 * \param color[in] Clear color
466 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
467 * command submission resources.
469 static enum pipe_error
470 svga_try_clear_render_target(struct svga_context
*svga
,
471 struct pipe_surface
*dst
,
472 const union pipe_color_union
*color
)
474 struct pipe_surface
*rtv
=
475 svga_validate_surface_view(svga
, svga_surface(dst
));
478 return PIPE_ERROR_OUT_OF_MEMORY
;
480 return SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
, color
->f
);
484 * \brief Clear part of render target using gallium blitter utilities
486 * \param svga[in] The svga context
487 * \param dst[in] The surface to clear
488 * \param color[in] Clear color
489 * \param dstx[in] Clear region left
490 * \param dsty[in] Clear region top
491 * \param width[in] Clear region width
492 * \param height[in] Clear region height
495 svga_blitter_clear_render_target(struct svga_context
*svga
,
496 struct pipe_surface
*dst
,
497 const union pipe_color_union
*color
,
498 unsigned dstx
, unsigned dsty
,
499 unsigned width
, unsigned height
)
502 util_blitter_save_framebuffer(svga
->blitter
, &svga
->curr
.framebuffer
);
504 util_blitter_clear_render_target(svga
->blitter
, dst
, color
,
505 dstx
, dsty
, width
, height
);
510 * \brief Clear render target pipe callback
512 * \param pipe[in] The pipe context
513 * \param dst[in] The surface to clear
514 * \param color[in] Clear color
515 * \param dstx[in] Clear region left
516 * \param dsty[in] Clear region top
517 * \param width[in] Clear region width
518 * \param height[in] Clear region height
519 * \param render_condition_enabled[in] Whether to use conditional rendering
520 * to clear (if elsewhere enabled).
523 svga_clear_render_target(struct pipe_context
*pipe
,
524 struct pipe_surface
*dst
,
525 const union pipe_color_union
*color
,
526 unsigned dstx
, unsigned dsty
,
527 unsigned width
, unsigned height
,
528 bool render_condition_enabled
)
530 struct svga_context
*svga
= svga_context( pipe
);
532 svga_toggle_render_condition(svga
, render_condition_enabled
, FALSE
);
533 if (!svga_have_vgpu10(svga
) || dstx
!= 0 || dsty
!= 0 ||
534 width
!= dst
->width
|| height
!= dst
->height
) {
535 svga_blitter_clear_render_target(svga
, dst
, color
, dstx
, dsty
, width
,
540 ret
= svga_try_clear_render_target(svga
, dst
, color
);
541 if (ret
== PIPE_ERROR_OUT_OF_MEMORY
) {
542 svga_context_flush( svga
, NULL
);
543 ret
= svga_try_clear_render_target(svga
, dst
, color
);
546 assert (ret
== PIPE_OK
);
548 svga_toggle_render_condition(svga
, render_condition_enabled
, TRUE
);
551 void svga_init_clear_functions(struct svga_context
*svga
)
553 svga
->pipe
.clear_render_target
= svga_clear_render_target
;
554 svga
->pipe
.clear_texture
= svga_clear_texture
;
555 svga
->pipe
.clear
= svga_clear
;