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
);
329 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
330 box
->height
== surface
->height
) {
331 /* clearing whole surface, use direct VGPU10 command */
334 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
337 if (ret
!= PIPE_OK
) {
338 /* flush and try again */
339 svga_context_flush(svga
, NULL
);
340 ret
= SVGA3D_vgpu10_ClearDepthStencilView(svga
->swc
, dsv
,
343 assert(ret
== PIPE_OK
);
347 /* To clear subtexture use software fallback */
349 util_blitter_save_framebuffer(svga
->blitter
,
350 &svga
->curr
.framebuffer
);
352 util_blitter_clear_depth_stencil(svga
->blitter
,
356 box
->width
, box
->height
);
360 /* non depth-stencil formats */
363 /* If data is NULL, the texture image is filled with zeros */
364 color
.f
[0] = color
.f
[1] = color
.f
[2] = color
.f
[3] = 0;
367 if (util_format_is_pure_sint(surface
->format
)) {
369 desc
->unpack_rgba_sint(color
.i
, 0, data
, 0, 1, 1);
371 else if (util_format_is_pure_uint(surface
->format
)) {
372 /* unsigned integer */
373 desc
->unpack_rgba_uint(color
.ui
, 0, data
, 0, 1, 1);
377 desc
->unpack_rgba_float(color
.f
, 0, data
, 0, 1, 1);
381 /* Setup render target view */
382 struct pipe_surface
*rtv
=
383 svga_validate_surface_view(svga
, svga_surface_dst
);
388 if (box
->x
== 0 && box
->y
== 0 && box
->width
== surface
->width
&&
389 box
->height
== surface
->height
) {
390 struct pipe_framebuffer_state
*curr
= &svga
->curr
.framebuffer
;
392 if (is_integer_target(curr
, PIPE_CLEAR_COLOR
) &&
393 !ints_fit_in_floats(&color
)) {
394 /* To clear full texture with integer format */
395 clear_buffers_with_quad(svga
, PIPE_CLEAR_COLOR
, &color
, 0.0, 0);
398 /* clearing whole surface using VGPU10 command */
399 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
401 if (ret
!= PIPE_OK
) {
402 svga_context_flush(svga
,NULL
);
403 ret
= SVGA3D_vgpu10_ClearRenderTargetView(svga
->swc
, rtv
,
405 assert(ret
== PIPE_OK
);
410 /* To clear subtexture use software fallback */
413 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
414 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
415 * util_clear_render_target() for PIPE_TEXTURE_3D.
417 if (rtv
->texture
->target
!= PIPE_TEXTURE_3D
&&
418 pipe
->screen
->is_format_supported(pipe
->screen
, rtv
->format
,
419 rtv
->texture
->target
,
420 rtv
->texture
->nr_samples
,
421 PIPE_BIND_RENDER_TARGET
)) {
422 /* clear with quad drawing */
423 util_blitter_save_framebuffer(svga
->blitter
,
424 &svga
->curr
.framebuffer
);
426 util_blitter_clear_render_target(svga
->blitter
,
430 box
->width
, box
->height
);
433 /* clear with map/write/unmap */
435 /* store layer values */
436 unsigned first_layer
= rtv
->u
.tex
.first_layer
;
437 unsigned last_layer
= rtv
->u
.tex
.last_layer
;
438 unsigned box_depth
= last_layer
- first_layer
+ 1;
440 for (unsigned i
= 0; i
< box_depth
; i
++) {
441 rtv
->u
.tex
.first_layer
= rtv
->u
.tex
.last_layer
=
443 util_clear_render_target(pipe
, rtv
, &color
, box
->x
, box
->y
,
444 box
->width
, box
->height
);
446 /* restore layer values */
447 rtv
->u
.tex
.first_layer
= first_layer
;
448 rtv
->u
.tex
.last_layer
= last_layer
;