1/********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 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: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 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 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26#include "svga_cmd.h" 27#include "svga_debug.h" 28 29#include "pipe/p_defines.h" 30#include "util/u_pack_color.h" 31#include "util/u_surface.h" 32 33#include "svga_context.h" 34#include "svga_state.h" 35#include "svga_surface.h" 36 37 38/** 39 * Saving blitter states before doing any blitter operation 40 */ 41static void 42begin_blit(struct svga_context *svga) 43{ 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, 0); 61 util_blitter_save_fragment_constant_buffer_slot(svga->blitter, 62 &svga->curr.constbufs[PIPE_SHADER_FRAGMENT][0]); 63} 64 65 66/** 67 * Clear the whole color buffer(s) by drawing a quad. For VGPU10 we use 68 * this when clearing integer render targets. We'll also clear the 69 * depth and/or stencil buffers if the clear_buffers mask specifies them. 70 */ 71static void 72clear_buffers_with_quad(struct svga_context *svga, 73 unsigned clear_buffers, 74 const union pipe_color_union *color, 75 double depth, unsigned stencil) 76{ 77 const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; 78 79 begin_blit(svga); 80 util_blitter_clear(svga->blitter, 81 fb->width, fb->height, 82 1, /* num_layers */ 83 clear_buffers, color, 84 depth, stencil, 85 util_framebuffer_get_num_samples(fb) > 1); 86} 87 88 89/** 90 * Check if any of the color buffers are integer buffers. 91 */ 92static boolean 93is_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers) 94{ 95 unsigned i; 96 97 for (i = 0; i < fb->nr_cbufs; i++) { 98 if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && 99 fb->cbufs[i] && 100 util_format_is_pure_integer(fb->cbufs[i]->format)) { 101 return TRUE; 102 } 103 } 104 return FALSE; 105} 106 107 108/** 109 * Check if the integer values in the clear color can be represented 110 * by floats. If so, we can use the VGPU10 ClearRenderTargetView command. 111 * Otherwise, we need to clear with a quad. 112 */ 113static boolean 114ints_fit_in_floats(const union pipe_color_union *color) 115{ 116 const int max = 1 << 24; 117 return (color->i[0] <= max && 118 color->i[1] <= max && 119 color->i[2] <= max && 120 color->i[3] <= max); 121} 122 123 124static enum pipe_error 125try_clear(struct svga_context *svga, 126 unsigned buffers, 127 const union pipe_color_union *color, 128 double depth, 129 unsigned stencil) 130{ 131 enum pipe_error ret = PIPE_OK; 132 SVGA3dRect rect = { 0, 0, 0, 0 }; 133 boolean restore_viewport = FALSE; 134 SVGA3dClearFlag flags = 0; 135 struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; 136 union util_color uc = {0}; 137 138 ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR); 139 if (ret != PIPE_OK) 140 return ret; 141 142 if (svga->rebind.flags.rendertargets) { 143 ret = svga_reemit_framebuffer_bindings(svga); 144 if (ret != PIPE_OK) { 145 return ret; 146 } 147 } 148 149 if (buffers & PIPE_CLEAR_COLOR) { 150 flags |= SVGA3D_CLEAR_COLOR; 151 util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); 152 153 rect.w = fb->width; 154 rect.h = fb->height; 155 } 156 157 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) { 158 if (buffers & PIPE_CLEAR_DEPTH) 159 flags |= SVGA3D_CLEAR_DEPTH; 160 161 if (buffers & PIPE_CLEAR_STENCIL) 162 flags |= SVGA3D_CLEAR_STENCIL; 163 164 rect.w = MAX2(rect.w, fb->zsbuf->width); 165 rect.h = MAX2(rect.h, fb->zsbuf->height); 166 } 167 168 if (!svga_have_vgpu10(svga) && 169 !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) { 170 restore_viewport = TRUE; 171 ret = SVGA3D_SetViewport(svga->swc, &rect); 172 if (ret != PIPE_OK) 173 return ret; 174 } 175 176 if (svga_have_vgpu10(svga)) { 177 if (flags & SVGA3D_CLEAR_COLOR) { 178 unsigned i; 179 bool int_target = is_integer_target(fb, buffers); 180 181 if (int_target && !ints_fit_in_floats(color)) { 182 clear_buffers_with_quad(svga, buffers, color, depth, stencil); 183 /* We also cleared depth/stencil, so that's done */ 184 flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL); 185 } 186 else { 187 struct pipe_surface *rtv; 188 float rgba[4]; 189 190 if (int_target) { 191 rgba[0] = (float) color->i[0]; 192 rgba[1] = (float) color->i[1]; 193 rgba[2] = (float) color->i[2]; 194 rgba[3] = (float) color->i[3]; 195 } 196 else { 197 rgba[0] = color->f[0]; 198 rgba[1] = color->f[1]; 199 rgba[2] = color->f[2]; 200 rgba[3] = color->f[3]; 201 } 202 203 /* Issue VGPU10 Clear commands */ 204 for (i = 0; i < fb->nr_cbufs; i++) { 205 if ((fb->cbufs[i] == NULL) || 206 !(buffers & (PIPE_CLEAR_COLOR0 << i))) 207 continue; 208 209 rtv = svga_validate_surface_view(svga, 210 svga_surface(fb->cbufs[i])); 211 if (!rtv) 212 return PIPE_ERROR_OUT_OF_MEMORY; 213 214 ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, rgba); 215 if (ret != PIPE_OK) 216 return ret; 217 } 218 } 219 } 220 if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) { 221 struct pipe_surface *dsv = 222 svga_validate_surface_view(svga, svga_surface(fb->zsbuf)); 223 if (!dsv) 224 return PIPE_ERROR_OUT_OF_MEMORY; 225 226 ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags, 227 stencil, (float) depth); 228 if (ret != PIPE_OK) 229 return ret; 230 } 231 } 232 else { 233 ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil, 234 rect.x, rect.y, rect.w, rect.h); 235 if (ret != PIPE_OK) 236 return ret; 237 } 238 239 if (restore_viewport) { 240 ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport); 241 } 242 243 return ret; 244} 245 246/** 247 * Clear the given surface to the specified value. 248 * No masking, no scissor (clear entire buffer). 249 */ 250static void 251svga_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state, 252 const union pipe_color_union *color, 253 double depth, unsigned stencil) 254{ 255 struct svga_context *svga = svga_context( pipe ); 256 enum pipe_error ret; 257 258 if (buffers & PIPE_CLEAR_COLOR) { 259 struct svga_winsys_surface *h = NULL; 260 if (svga->curr.framebuffer.cbufs[0]) { 261 h = svga_surface(svga->curr.framebuffer.cbufs[0])->handle; 262 } 263 SVGA_DBG(DEBUG_DMA, "clear sid %p\n", h); 264 } 265 266 /* flush any queued prims (don't want them to appear after the clear!) */ 267 svga_hwtnl_flush_retry(svga); 268 269 SVGA_RETRY_OOM(svga, ret, try_clear( svga, buffers, color, depth, stencil)); 270 271 /* 272 * Mark target surfaces as dirty 273 * TODO Mark only cleared surfaces. 274 */ 275 svga_mark_surfaces_dirty(svga); 276 277 assert (ret == PIPE_OK); 278} 279 280 281static void 282svga_clear_texture(struct pipe_context *pipe, 283 struct pipe_resource *res, 284 unsigned level, 285 const struct pipe_box *box, 286 const void *data) 287{ 288 struct svga_context *svga = svga_context(pipe); 289 struct svga_surface *svga_surface_dst; 290 struct pipe_surface tmpl; 291 struct pipe_surface *surface; 292 293 memset(&tmpl, 0, sizeof(tmpl)); 294 tmpl.format = res->format; 295 tmpl.u.tex.first_layer = box->z; 296 tmpl.u.tex.last_layer = box->z + box->depth - 1; 297 tmpl.u.tex.level = level; 298 299 surface = pipe->create_surface(pipe, res, &tmpl); 300 if (surface == NULL) { 301 debug_printf("failed to create surface\n"); 302 return; 303 } 304 svga_surface_dst = svga_surface(surface); 305 306 union pipe_color_union color; 307 const struct util_format_description *desc = 308 util_format_description(surface->format); 309 310 if (util_format_is_depth_or_stencil(surface->format)) { 311 float depth; 312 uint8_t stencil; 313 unsigned clear_flags = 0; 314 315 /* If data is NULL, then set depthValue and stencilValue to zeros */ 316 if (data == NULL) { 317 depth = 0.0; 318 stencil = 0; 319 } 320 else { 321 util_format_unpack_z_float(surface->format, &depth, data, 1); 322 util_format_unpack_s_8uint(surface->format, &stencil, data, 1); 323 } 324 325 if (util_format_has_depth(desc)) { 326 clear_flags |= PIPE_CLEAR_DEPTH; 327 } 328 if (util_format_has_stencil(desc)) { 329 clear_flags |= PIPE_CLEAR_STENCIL; 330 } 331 332 /* Setup depth stencil view */ 333 struct pipe_surface *dsv = 334 svga_validate_surface_view(svga, svga_surface_dst); 335 336 if (!dsv) { 337 pipe_surface_reference(&surface, NULL); 338 return; 339 } 340 341 if (box->x == 0 && box->y == 0 && box->width == surface->width && 342 box->height == surface->height) { 343 /* clearing whole surface, use direct VGPU10 command */ 344 assert(svga_surface(dsv)->view_id != SVGA3D_INVALID_ID); 345 346 SVGA_RETRY(svga, SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, 347 clear_flags, 348 stencil, depth)); 349 } 350 else { 351 /* To clear subtexture use software fallback */ 352 353 util_blitter_save_framebuffer(svga->blitter, 354 &svga->curr.framebuffer); 355 begin_blit(svga); 356 util_blitter_clear_depth_stencil(svga->blitter, 357 dsv, clear_flags, 358 depth,stencil, 359 box->x, box->y, 360 box->width, box->height); 361 } 362 } 363 else { 364 /* non depth-stencil formats */ 365 366 if (data == NULL) { 367 /* If data is NULL, the texture image is filled with zeros */ 368 color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0; 369 } 370 else { 371 util_format_unpack_rgba(surface->format, &color, data, 1); 372 } 373 374 /* Setup render target view */ 375 struct pipe_surface *rtv = 376 svga_validate_surface_view(svga, svga_surface_dst); 377 378 if (!rtv) { 379 pipe_surface_reference(&surface, NULL); 380 return; 381 } 382 383 if (box->x == 0 && box->y == 0 && box->width == surface->width && 384 box->height == surface->height) { 385 struct pipe_framebuffer_state *curr = &svga->curr.framebuffer; 386 bool int_target = is_integer_target(curr, PIPE_CLEAR_COLOR); 387 388 if (int_target && !ints_fit_in_floats(&color)) { 389 /* To clear full texture with integer format */ 390 clear_buffers_with_quad(svga, PIPE_CLEAR_COLOR, &color, 0.0, 0); 391 } 392 else { 393 float rgba[4]; 394 395 if (int_target) { 396 rgba[0] = (float) color.i[0]; 397 rgba[1] = (float) color.i[1]; 398 rgba[2] = (float) color.i[2]; 399 rgba[3] = (float) color.i[3]; 400 } 401 else { 402 rgba[0] = color.f[0]; 403 rgba[1] = color.f[1]; 404 rgba[2] = color.f[2]; 405 rgba[3] = color.f[3]; 406 } 407 408 /* clearing whole surface using VGPU10 command */ 409 assert(svga_surface(rtv)->view_id != SVGA3D_INVALID_ID); 410 SVGA_RETRY(svga, SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, 411 rgba)); 412 } 413 } 414 else { 415 /* To clear subtexture use software fallback */ 416 417 /** 418 * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D 419 * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use 420 * util_clear_render_target() for PIPE_TEXTURE_3D. 421 */ 422 if (rtv->texture->target != PIPE_TEXTURE_3D && 423 pipe->screen->is_format_supported(pipe->screen, rtv->format, 424 rtv->texture->target, 425 rtv->texture->nr_samples, 426 rtv->texture->nr_storage_samples, 427 PIPE_BIND_RENDER_TARGET)) { 428 /* clear with quad drawing */ 429 util_blitter_save_framebuffer(svga->blitter, 430 &svga->curr.framebuffer); 431 begin_blit(svga); 432 util_blitter_clear_render_target(svga->blitter, 433 rtv, 434 &color, 435 box->x, box->y, 436 box->width, box->height); 437 } 438 else { 439 /* clear with map/write/unmap */ 440 441 /* store layer values */ 442 unsigned first_layer = rtv->u.tex.first_layer; 443 unsigned last_layer = rtv->u.tex.last_layer; 444 unsigned box_depth = last_layer - first_layer + 1; 445 446 for (unsigned i = 0; i < box_depth; i++) { 447 rtv->u.tex.first_layer = rtv->u.tex.last_layer = 448 first_layer + i; 449 util_clear_render_target(pipe, rtv, &color, box->x, box->y, 450 box->width, box->height); 451 } 452 /* restore layer values */ 453 rtv->u.tex.first_layer = first_layer; 454 rtv->u.tex.last_layer = last_layer; 455 } 456 } 457 } 458 pipe_surface_reference(&surface, NULL); 459} 460 461/** 462 * \brief Clear the whole render target using vgpu10 functionality 463 * 464 * \param svga[in] The svga context 465 * \param dst[in] The surface to clear 466 * \param color[in] Clear color 467 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of 468 * command submission resources. 469 */ 470static enum pipe_error 471svga_try_clear_render_target(struct svga_context *svga, 472 struct pipe_surface *dst, 473 const union pipe_color_union *color) 474{ 475 struct pipe_surface *rtv = 476 svga_validate_surface_view(svga, svga_surface(dst)); 477 478 if (!rtv) 479 return PIPE_ERROR_OUT_OF_MEMORY; 480 481 assert(svga_surface(rtv)->view_id != SVGA3D_INVALID_ID); 482 return SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, color->f); 483 } 484 485/** 486 * \brief Clear part of render target using gallium blitter utilities 487 * 488 * \param svga[in] The svga context 489 * \param dst[in] The surface to clear 490 * \param color[in] Clear color 491 * \param dstx[in] Clear region left 492 * \param dsty[in] Clear region top 493 * \param width[in] Clear region width 494 * \param height[in] Clear region height 495 */ 496static void 497svga_blitter_clear_render_target(struct svga_context *svga, 498 struct pipe_surface *dst, 499 const union pipe_color_union *color, 500 unsigned dstx, unsigned dsty, 501 unsigned width, unsigned height) 502{ 503 begin_blit(svga); 504 util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); 505 506 util_blitter_clear_render_target(svga->blitter, dst, color, 507 dstx, dsty, width, height); 508} 509 510 511/** 512 * \brief Clear render target pipe callback 513 * 514 * \param pipe[in] The pipe context 515 * \param dst[in] The surface to clear 516 * \param color[in] Clear color 517 * \param dstx[in] Clear region left 518 * \param dsty[in] Clear region top 519 * \param width[in] Clear region width 520 * \param height[in] Clear region height 521 * \param render_condition_enabled[in] Whether to use conditional rendering 522 * to clear (if elsewhere enabled). 523 */ 524static void 525svga_clear_render_target(struct pipe_context *pipe, 526 struct pipe_surface *dst, 527 const union pipe_color_union *color, 528 unsigned dstx, unsigned dsty, 529 unsigned width, unsigned height, 530 bool render_condition_enabled) 531{ 532 struct svga_context *svga = svga_context( pipe ); 533 534 svga_toggle_render_condition(svga, render_condition_enabled, FALSE); 535 if (!svga_have_vgpu10(svga) || dstx != 0 || dsty != 0 || 536 width != dst->width || height != dst->height) { 537 svga_blitter_clear_render_target(svga, dst, color, dstx, dsty, width, 538 height); 539 } else { 540 enum pipe_error ret; 541 542 SVGA_RETRY_OOM(svga, ret, svga_try_clear_render_target(svga, dst, 543 color)); 544 assert (ret == PIPE_OK); 545 } 546 svga_toggle_render_condition(svga, render_condition_enabled, TRUE); 547} 548 549void svga_init_clear_functions(struct svga_context *svga) 550{ 551 svga->pipe.clear_render_target = svga_clear_render_target; 552 svga->pipe.clear_texture = svga_clear_texture; 553 svga->pipe.clear = svga_clear; 554} 555