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_tessctrl_shader(svga
->blitter
, svga
->curr
.tcs
);
49 util_blitter_save_tesseval_shader(svga
->blitter
, svga
->curr
.tes
);
50 util_blitter_save_so_targets(svga
->blitter
, svga
->num_so_targets
,
51 (struct pipe_stream_output_target
**)svga
->so_targets
);
52 util_blitter_save_rasterizer(svga
->blitter
, (void*)svga
->curr
.rast
);
53 util_blitter_save_viewport(svga
->blitter
, &svga
->curr
.viewport
[0]);
54 util_blitter_save_scissor(svga
->blitter
, &svga
->curr
.scissor
[0]);
55 util_blitter_save_fragment_shader(svga
->blitter
, svga
->curr
.fs
);
56 util_blitter_save_blend(svga
->blitter
, (void*)svga
->curr
.blend
);
57 util_blitter_save_depth_stencil_alpha(svga
->blitter
,
58 (void*)svga
->curr
.depth
);
59 util_blitter_save_stencil_ref(svga
->blitter
, &svga
->curr
.stencil_ref
);
60 util_blitter_save_sample_mask(svga
->blitter
, svga
->curr
.sample_mask
);
65 * Clear the whole color buffer(s) by drawing a quad. For VGPU10 we use
66 * this when clearing integer render targets. We'll also clear the
67 * depth and/or stencil buffers if the clear_buffers mask specifies them.
70 clear_buffers_with_quad(struct svga_context
*svga
,
71 unsigned clear_buffers
,
72 const union pipe_color_union
*color
,
73 double depth
, unsigned stencil
)
75 const struct pipe_framebuffer_state
*fb
= &svga
->curr
.framebuffer
;
78 util_blitter_clear(svga
->blitter
,
79 fb
->width
, fb
->height
,
83 util_framebuffer_get_num_samples(fb
) > 1);
88 * Check if any of the color buffers are integer buffers.
91 is_integer_target(struct pipe_framebuffer_state
*fb
, unsigned buffers
)
95 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
96 if ((buffers
& (PIPE_CLEAR_COLOR0
<< i
)) &&
98 util_format_is_pure_integer(fb
->cbufs
[i
]->format
)) {
107 * Check if the integer values in the clear color can be represented
108 * by floats. If so, we can use the VGPU10 ClearRenderTargetView command.
109 * Otherwise, we need to clear with a quad.
112 ints_fit_in_floats(const union pipe_color_union
*color
)
114 const int max
= 1 << 24;
115 return (color
->i
[0] <= max
&&
116 color
->i
[1] <= max
&&
117 color
->i
[2] <= max
&&
122 static enum pipe_error
123 try_clear(struct svga_context
*svga
,
125 const union pipe_color_union
*color
,
129 enum pipe_error ret
= PIPE_OK
;
130 SVGA3dRect rect
= { 0, 0, 0, 0 };
131 boolean restore_viewport
= FALSE
;
132 SVGA3dClearFlag flags
= 0;
133 struct pipe_framebuffer_state
*fb
= &svga
->curr
.framebuffer
;
134 union util_color uc
= {0};
136 ret
= svga_update_state(svga
, SVGA_STATE_HW_CLEAR
);
140 if (svga
->rebind
.flags
.rendertargets
) {
141 ret
= svga_reemit_framebuffer_bindings(svga
);
142 if (ret
!= PIPE_OK
) {
147 if (buffers
& PIPE_CLEAR_COLOR
) {
148 flags
|= SVGA3D_CLEAR_COLOR
;
149 util_pack_color(color
->f
, PIPE_FORMAT_B8G8R8A8_UNORM
, &uc
);
155 if ((buffers
& PIPE_CLEAR_DEPTHSTENCIL
) && fb
->zsbuf
) {
156 if (buffers
& PIPE_CLEAR_DEPTH
)
157 flags
|= SVGA3D_CLEAR_DEPTH
;
159 if (buffers
& PIPE_CLEAR_STENCIL
)
160 flags
|= SVGA3D_CLEAR_STENCIL
;
162 rect
.w
= MAX2(rect
.w
, fb
->zsbuf
->width
);
163 rect
.h
= MAX2(rect
.h
, fb
->zsbuf
->height
);
166 if (!svga_have_vgpu10(svga
) &&
167 !svga_rects_equal(&rect
, &svga
->state
.hw_clear
.viewport
)) {
168 restore_viewport
= TRUE
;
169 ret
= SVGA3D_SetViewport(svga
->swc
, &rect
);
174 if (svga_have_vgpu10(svga
)) {
175 if (flags
& SVGA3D_CLEAR_COLOR
) {
178 if (is_integer_target(fb
, buffers
) && !ints_fit_in_floats(color
)) {
179 clear_buffers_with_quad(svga
, buffers
, color
, depth
, stencil
);
180 /* We also cleared depth/stencil, so that's done */
181 flags
&= ~(SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
);
184 struct pipe_surface
*rtv
;
186 /* Issue VGPU10 Clear commands */
187 for (i
= 0; i
< fb
->nr_cbufs
; i
++) {
188 if ((fb
->cbufs
[i
] == NULL
) ||
189 !(buffers
& (PIPE_CLEAR_COLOR0
<< i
)))
192 rtv
= svga_validate_surface_view(svga
,
193 svga_surface(fb
->cbufs
[i
]));
195 return PIPE_ERROR_OUT_OF_MEMORY
;
197 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
,
204 if (flags
& (SVGA3D_CLEAR_DEPTH
| SVGA3D_CLEAR_STENCIL
)) {
205 struct pipe_surface
*dsv
=
206 svga_validate_surface_view(svga
, svga_surface(fb
->zsbuf
));
208 return PIPE_ERROR_OUT_OF_MEMORY
;
210 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
, flags
,
211 stencil
, (float) depth
);
217 ret
= SVGA3D_ClearRect(svga
->swc
, flags
, uc
.ui
[0], (float) depth
, stencil
,
218 rect
.x
, rect
.y
, rect
.w
, rect
.h
);
223 if (restore_viewport
) {
224 ret
= SVGA3D_SetViewport(svga
->swc
, &svga
->state
.hw_clear
.viewport
);
231 * Clear the given surface to the specified value.
232 * No masking, no scissor (clear entire buffer).
235 svga_clear(struct pipe_context
*pipe
, unsigned buffers
, const struct pipe_scissor_state
*scissor_state
,
236 const union pipe_color_union
*color
,
237 double depth
, unsigned stencil
)
239 struct svga_context
*svga
= svga_context( pipe
);
242 if (buffers
& PIPE_CLEAR_COLOR
) {
243 struct svga_winsys_surface
*h
= NULL
;
244 if (svga
->curr
.framebuffer
.cbufs
[0]) {
245 h
= svga_surface(svga
->curr
.framebuffer
.cbufs
[0])->handle
;
247 SVGA_DBG(DEBUG_DMA
, "clear sid %p\n", h
);
250 /* flush any queued prims (don't want them to appear after the clear!) */
251 svga_hwtnl_flush_retry(svga
);
253 SVGA_RETRY_OOM(svga
, ret
, try_clear( svga
, buffers
, color
, depth
, stencil
));
256 * Mark target surfaces as dirty
257 * TODO Mark only cleared surfaces.
259 svga_mark_surfaces_dirty(svga
);
261 assert (ret
== PIPE_OK
);
266 svga_clear_texture(struct pipe_context
*pipe
,
267 struct pipe_resource
*res
,
269 const struct pipe_box
*box
,
272 struct svga_context
*svga
= svga_context(pipe
);
273 struct svga_surface
*svga_surface_dst
;
274 struct pipe_surface tmpl
;
275 struct pipe_surface
*surface
;
277 memset(&tmpl
, 0, sizeof(tmpl
));
278 tmpl
.format
= res
->format
;
279 tmpl
.u
.tex
.first_layer
= box
->z
;
280 tmpl
.u
.tex
.last_layer
= box
->z
+ box
->depth
- 1;
281 tmpl
.u
.tex
.level
= level
;
283 surface
= pipe
->create_surface(pipe
, res
, &tmpl
);
284 if (surface
== NULL
) {
285 debug_printf("failed to create surface\n");
288 svga_surface_dst
= svga_surface(surface
);
290 union pipe_color_union color
;
291 const struct util_format_description
*desc
=
292 util_format_description(surface
->format
);
293 const struct util_format_description
*unpack
=
294 util_format_unpack_description(surface
->format
);
296 if (util_format_is_depth_or_stencil(surface
->format
)) {
299 unsigned clear_flags
= 0;
301 /* If data is NULL, then set depthValue and stencilValue to zeros */
307 unpack
->unpack_z_float(&depth
, 0, data
, 0, 1, 1);
308 unpack
->unpack_s_8uint(&stencil
, 0, data
, 0, 1, 1);
311 if (util_format_has_depth(desc
)) {
312 clear_flags
|= PIPE_CLEAR_DEPTH
;
314 if (util_format_has_stencil(desc
)) {
315 clear_flags
|= PIPE_CLEAR_STENCIL
;
318 /* Setup depth stencil view */
319 struct pipe_surface
*dsv
=
320 svga_validate_surface_view(svga
, svga_surface_dst
);
323 pipe_surface_reference(&surface
, NULL
);
327 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
328 box
->height
== surface
->height
) {
329 /* clearing whole surface, use direct VGPU10 command */
332 SVGA_RETRY(svga
, SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
337 /* To clear subtexture use software fallback */
339 util_blitter_save_framebuffer(svga
->blitter
,
340 &svga
->curr
.framebuffer
);
342 util_blitter_clear_depth_stencil(svga
->blitter
,
346 box
->width
, box
->height
);
350 /* non depth-stencil formats */
353 /* If data is NULL, the texture image is filled with zeros */
354 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
357 util_format_unpack_rgba(surface
->format
, &color
, data
, 1);
360 /* Setup render target view */
361 struct pipe_surface
*rtv
=
362 svga_validate_surface_view(svga
, svga_surface_dst
);
365 pipe_surface_reference(&surface
, NULL
);
369 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
370 box
->height
== surface
->height
) {
371 struct pipe_framebuffer_state
*curr
= &svga
->curr
.framebuffer
;
373 if (is_integer_target(curr
, PIPE_CLEAR_COLOR
) &&
374 !ints_fit_in_floats(&color
)) {
375 /* To clear full texture with integer format */
376 clear_buffers_with_quad(svga
, PIPE_CLEAR_COLOR
, &color
, 0.0, 0);
379 /* clearing whole surface using VGPU10 command */
380 SVGA_RETRY(svga
, SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
385 /* To clear subtexture use software fallback */
388 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
389 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
390 * util_clear_render_target() for PIPE_TEXTURE_3D.
392 if (rtv
->texture
->target
!= PIPE_TEXTURE_3D
&&
393 pipe
->screen
->is_format_supported(pipe
->screen
, rtv
->format
,
394 rtv
->texture
->target
,
395 rtv
->texture
->nr_samples
,
396 rtv
->texture
->nr_storage_samples
,
397 PIPE_BIND_RENDER_TARGET
)) {
398 /* clear with quad drawing */
399 util_blitter_save_framebuffer(svga
->blitter
,
400 &svga
->curr
.framebuffer
);
402 util_blitter_clear_render_target(svga
->blitter
,
406 box
->width
, box
->height
);
409 /* clear with map/write/unmap */
411 /* store layer values */
412 unsigned first_layer
= rtv
->u
.tex
.first_layer
;
413 unsigned last_layer
= rtv
->u
.tex
.last_layer
;
414 unsigned box_depth
= last_layer
- first_layer
+ 1;
416 for (unsigned i
= 0; i
< box_depth
; i
++) {
417 rtv
->u
.tex
.first_layer
= rtv
->u
.tex
.last_layer
=
419 util_clear_render_target(pipe
, rtv
, &color
, box
->x
, box
->y
,
420 box
->width
, box
->height
);
422 /* restore layer values */
423 rtv
->u
.tex
.first_layer
= first_layer
;
424 rtv
->u
.tex
.last_layer
= last_layer
;
428 pipe_surface_reference(&surface
, NULL
);
432 * \brief Clear the whole render target using vgpu10 functionality
434 * \param svga[in] The svga context
435 * \param dst[in] The surface to clear
436 * \param color[in] Clear color
437 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
438 * command submission resources.
440 static enum pipe_error
441 svga_try_clear_render_target(struct svga_context
*svga
,
442 struct pipe_surface
*dst
,
443 const union pipe_color_union
*color
)
445 struct pipe_surface
*rtv
=
446 svga_validate_surface_view(svga
, svga_surface(dst
));
449 return PIPE_ERROR_OUT_OF_MEMORY
;
451 return SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
, color
->f
);
455 * \brief Clear part of render target using gallium blitter utilities
457 * \param svga[in] The svga context
458 * \param dst[in] The surface to clear
459 * \param color[in] Clear color
460 * \param dstx[in] Clear region left
461 * \param dsty[in] Clear region top
462 * \param width[in] Clear region width
463 * \param height[in] Clear region height
466 svga_blitter_clear_render_target(struct svga_context
*svga
,
467 struct pipe_surface
*dst
,
468 const union pipe_color_union
*color
,
469 unsigned dstx
, unsigned dsty
,
470 unsigned width
, unsigned height
)
473 util_blitter_save_framebuffer(svga
->blitter
, &svga
->curr
.framebuffer
);
475 util_blitter_clear_render_target(svga
->blitter
, dst
, color
,
476 dstx
, dsty
, width
, height
);
481 * \brief Clear render target pipe callback
483 * \param pipe[in] The pipe context
484 * \param dst[in] The surface to clear
485 * \param color[in] Clear color
486 * \param dstx[in] Clear region left
487 * \param dsty[in] Clear region top
488 * \param width[in] Clear region width
489 * \param height[in] Clear region height
490 * \param render_condition_enabled[in] Whether to use conditional rendering
491 * to clear (if elsewhere enabled).
494 svga_clear_render_target(struct pipe_context
*pipe
,
495 struct pipe_surface
*dst
,
496 const union pipe_color_union
*color
,
497 unsigned dstx
, unsigned dsty
,
498 unsigned width
, unsigned height
,
499 bool render_condition_enabled
)
501 struct svga_context
*svga
= svga_context( pipe
);
503 svga_toggle_render_condition(svga
, render_condition_enabled
, FALSE
);
504 if (!svga_have_vgpu10(svga
) || dstx
!= 0 || dsty
!= 0 ||
505 width
!= dst
->width
|| height
!= dst
->height
) {
506 svga_blitter_clear_render_target(svga
, dst
, color
, dstx
, dsty
, width
,
511 SVGA_RETRY_OOM(svga
, ret
, svga_try_clear_render_target(svga
, dst
,
513 assert (ret
== PIPE_OK
);
515 svga_toggle_render_condition(svga
, render_condition_enabled
, TRUE
);
518 void svga_init_clear_functions(struct svga_context
*svga
)
520 svga
->pipe
.clear_render_target
= svga_clear_render_target
;
521 svga
->pipe
.clear_texture
= svga_clear_texture
;
522 svga
->pipe
.clear
= svga_clear
;