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
);
294 if (util_format_is_depth_or_stencil(surface
->format
)) {
297 unsigned clear_flags
= 0;
299 /* If data is NULL, then set depthValue and stencilValue to zeros */
305 desc
->unpack_z_float(&depth
, 0, data
, 0, 1, 1);
306 desc
->unpack_s_8uint(&stencil
, 0, data
, 0, 1, 1);
309 if (util_format_has_depth(desc
)) {
310 clear_flags
|= PIPE_CLEAR_DEPTH
;
312 if (util_format_has_stencil(desc
)) {
313 clear_flags
|= PIPE_CLEAR_STENCIL
;
316 /* Setup depth stencil view */
317 struct pipe_surface
*dsv
=
318 svga_validate_surface_view(svga
, svga_surface_dst
);
321 pipe_surface_reference(&surface
, NULL
);
325 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
326 box
->height
== surface
->height
) {
327 /* clearing whole surface, use direct VGPU10 command */
330 SVGA_RETRY(svga
, SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
335 /* To clear subtexture use software fallback */
337 util_blitter_save_framebuffer(svga
->blitter
,
338 &svga
->curr
.framebuffer
);
340 util_blitter_clear_depth_stencil(svga
->blitter
,
344 box
->width
, box
->height
);
348 /* non depth-stencil formats */
351 /* If data is NULL, the texture image is filled with zeros */
352 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
355 util_format_unpack_rgba(surface
->format
, &color
, data
, 1);
358 /* Setup render target view */
359 struct pipe_surface
*rtv
=
360 svga_validate_surface_view(svga
, svga_surface_dst
);
363 pipe_surface_reference(&surface
, NULL
);
367 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
368 box
->height
== surface
->height
) {
369 struct pipe_framebuffer_state
*curr
= &svga
->curr
.framebuffer
;
371 if (is_integer_target(curr
, PIPE_CLEAR_COLOR
) &&
372 !ints_fit_in_floats(&color
)) {
373 /* To clear full texture with integer format */
374 clear_buffers_with_quad(svga
, PIPE_CLEAR_COLOR
, &color
, 0.0, 0);
377 /* clearing whole surface using VGPU10 command */
378 SVGA_RETRY(svga
, SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
383 /* To clear subtexture use software fallback */
386 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
387 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
388 * util_clear_render_target() for PIPE_TEXTURE_3D.
390 if (rtv
->texture
->target
!= PIPE_TEXTURE_3D
&&
391 pipe
->screen
->is_format_supported(pipe
->screen
, rtv
->format
,
392 rtv
->texture
->target
,
393 rtv
->texture
->nr_samples
,
394 rtv
->texture
->nr_storage_samples
,
395 PIPE_BIND_RENDER_TARGET
)) {
396 /* clear with quad drawing */
397 util_blitter_save_framebuffer(svga
->blitter
,
398 &svga
->curr
.framebuffer
);
400 util_blitter_clear_render_target(svga
->blitter
,
404 box
->width
, box
->height
);
407 /* clear with map/write/unmap */
409 /* store layer values */
410 unsigned first_layer
= rtv
->u
.tex
.first_layer
;
411 unsigned last_layer
= rtv
->u
.tex
.last_layer
;
412 unsigned box_depth
= last_layer
- first_layer
+ 1;
414 for (unsigned i
= 0; i
< box_depth
; i
++) {
415 rtv
->u
.tex
.first_layer
= rtv
->u
.tex
.last_layer
=
417 util_clear_render_target(pipe
, rtv
, &color
, box
->x
, box
->y
,
418 box
->width
, box
->height
);
420 /* restore layer values */
421 rtv
->u
.tex
.first_layer
= first_layer
;
422 rtv
->u
.tex
.last_layer
= last_layer
;
426 pipe_surface_reference(&surface
, NULL
);
430 * \brief Clear the whole render target using vgpu10 functionality
432 * \param svga[in] The svga context
433 * \param dst[in] The surface to clear
434 * \param color[in] Clear color
435 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
436 * command submission resources.
438 static enum pipe_error
439 svga_try_clear_render_target(struct svga_context
*svga
,
440 struct pipe_surface
*dst
,
441 const union pipe_color_union
*color
)
443 struct pipe_surface
*rtv
=
444 svga_validate_surface_view(svga
, svga_surface(dst
));
447 return PIPE_ERROR_OUT_OF_MEMORY
;
449 return SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
, color
->f
);
453 * \brief Clear part of render target using gallium blitter utilities
455 * \param svga[in] The svga context
456 * \param dst[in] The surface to clear
457 * \param color[in] Clear color
458 * \param dstx[in] Clear region left
459 * \param dsty[in] Clear region top
460 * \param width[in] Clear region width
461 * \param height[in] Clear region height
464 svga_blitter_clear_render_target(struct svga_context
*svga
,
465 struct pipe_surface
*dst
,
466 const union pipe_color_union
*color
,
467 unsigned dstx
, unsigned dsty
,
468 unsigned width
, unsigned height
)
471 util_blitter_save_framebuffer(svga
->blitter
, &svga
->curr
.framebuffer
);
473 util_blitter_clear_render_target(svga
->blitter
, dst
, color
,
474 dstx
, dsty
, width
, height
);
479 * \brief Clear render target pipe callback
481 * \param pipe[in] The pipe context
482 * \param dst[in] The surface to clear
483 * \param color[in] Clear color
484 * \param dstx[in] Clear region left
485 * \param dsty[in] Clear region top
486 * \param width[in] Clear region width
487 * \param height[in] Clear region height
488 * \param render_condition_enabled[in] Whether to use conditional rendering
489 * to clear (if elsewhere enabled).
492 svga_clear_render_target(struct pipe_context
*pipe
,
493 struct pipe_surface
*dst
,
494 const union pipe_color_union
*color
,
495 unsigned dstx
, unsigned dsty
,
496 unsigned width
, unsigned height
,
497 bool render_condition_enabled
)
499 struct svga_context
*svga
= svga_context( pipe
);
501 svga_toggle_render_condition(svga
, render_condition_enabled
, FALSE
);
502 if (!svga_have_vgpu10(svga
) || dstx
!= 0 || dsty
!= 0 ||
503 width
!= dst
->width
|| height
!= dst
->height
) {
504 svga_blitter_clear_render_target(svga
, dst
, color
, dstx
, dsty
, width
,
509 SVGA_RETRY_OOM(svga
, ret
, svga_try_clear_render_target(svga
, dst
,
511 assert (ret
== PIPE_OK
);
513 svga_toggle_render_condition(svga
, render_condition_enabled
, TRUE
);
516 void svga_init_clear_functions(struct svga_context
*svga
)
518 svga
->pipe
.clear_render_target
= svga_clear_render_target
;
519 svga
->pipe
.clear_texture
= svga_clear_texture
;
520 svga
->pipe
.clear
= svga_clear
;