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 */ 41 static void 42 begin_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_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); 59 } 60 61 62 /** 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. 66 */ 67 static void 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) 72 { 73 const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer; 74 75 begin_blit(svga); 76 util_blitter_clear(svga->blitter, 77 fb->width, fb->height, 78 1, /* num_layers */ 79 clear_buffers, color, 80 depth, stencil); 81 } 82 83 84 /** 85 * Check if any of the color buffers are integer buffers. 86 */ 87 static boolean 88 is_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers) 89 { 90 unsigned i; 91 92 for (i = 0; i < fb->nr_cbufs; i++) { 93 if ((buffers & (PIPE_CLEAR_COLOR0 << i)) && 94 fb->cbufs[i] && 95 util_format_is_pure_integer(fb->cbufs[i]->format)) { 96 return TRUE; 97 } 98 } 99 return FALSE; 100 } 101 102 103 /** 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. 107 */ 108 static boolean 109 ints_fit_in_floats(const union pipe_color_union *color) 110 { 111 const int max = 1 << 24; 112 return (color->i[0] <= max && 113 color->i[1] <= max && 114 color->i[2] <= max && 115 color->i[3] <= max); 116 } 117 118 119 static enum pipe_error 120 try_clear(struct svga_context *svga, 121 unsigned buffers, 122 const union pipe_color_union *color, 123 double depth, 124 unsigned stencil) 125 { 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}; 132 133 ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR); 134 if (ret != PIPE_OK) 135 return ret; 136 137 if (svga->rebind.flags.rendertargets) { 138 ret = svga_reemit_framebuffer_bindings(svga); 139 if (ret != PIPE_OK) { 140 return ret; 141 } 142 } 143 144 if (buffers & PIPE_CLEAR_COLOR) { 145 flags |= SVGA3D_CLEAR_COLOR; 146 util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); 147 148 rect.w = fb->width; 149 rect.h = fb->height; 150 } 151 152 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) { 153 if (buffers & PIPE_CLEAR_DEPTH) 154 flags |= SVGA3D_CLEAR_DEPTH; 155 156 if (buffers & PIPE_CLEAR_STENCIL) 157 flags |= SVGA3D_CLEAR_STENCIL; 158 159 rect.w = MAX2(rect.w, fb->zsbuf->width); 160 rect.h = MAX2(rect.h, fb->zsbuf->height); 161 } 162 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); 167 if (ret != PIPE_OK) 168 return ret; 169 } 170 171 if (svga_have_vgpu10(svga)) { 172 if (flags & SVGA3D_CLEAR_COLOR) { 173 unsigned i; 174 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); 179 } 180 else { 181 struct pipe_surface *rtv; 182 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))) 187 continue; 188 189 rtv = svga_validate_surface_view(svga, 190 svga_surface(fb->cbufs[i])); 191 if (!rtv) 192 return PIPE_ERROR_OUT_OF_MEMORY; 193 194 ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, 195 rtv, color->f); 196 if (ret != PIPE_OK) 197 return ret; 198 } 199 } 200 } 201 if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) { 202 struct pipe_surface *dsv = 203 svga_validate_surface_view(svga, svga_surface(fb->zsbuf)); 204 if (!dsv) 205 return PIPE_ERROR_OUT_OF_MEMORY; 206 207 ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags, 208 stencil, (float) depth); 209 if (ret != PIPE_OK) 210 return ret; 211 } 212 } 213 else { 214 ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil, 215 rect.x, rect.y, rect.w, rect.h); 216 if (ret != PIPE_OK) 217 return ret; 218 } 219 220 if (restore_viewport) { 221 ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport); 222 } 223 224 return ret; 225 } 226 227 /** 228 * Clear the given surface to the specified value. 229 * No masking, no scissor (clear entire buffer). 230 */ 231 static void 232 svga_clear(struct pipe_context *pipe, unsigned buffers, 233 const union pipe_color_union *color, 234 double depth, unsigned stencil) 235 { 236 struct svga_context *svga = svga_context( pipe ); 237 enum pipe_error ret; 238 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; 243 } 244 SVGA_DBG(DEBUG_DMA, "clear sid %p\n", h); 245 } 246 247 /* flush any queued prims (don't want them to appear after the clear!) */ 248 svga_hwtnl_flush_retry(svga); 249 250 ret = try_clear( svga, buffers, color, depth, stencil ); 251 252 if (ret == PIPE_ERROR_OUT_OF_MEMORY) { 253 /* Flush command buffer and retry: 254 */ 255 svga_context_flush( svga, NULL ); 256 257 ret = try_clear( svga, buffers, color, depth, stencil ); 258 } 259 260 /* 261 * Mark target surfaces as dirty 262 * TODO Mark only cleared surfaces. 263 */ 264 svga_mark_surfaces_dirty(svga); 265 266 assert (ret == PIPE_OK); 267 } 268 269 270 static void 271 svga_clear_texture(struct pipe_context *pipe, 272 struct pipe_resource *res, 273 unsigned level, 274 const struct pipe_box *box, 275 const void *data) 276 { 277 struct svga_context *svga = svga_context(pipe); 278 struct svga_surface *svga_surface_dst; 279 enum pipe_error ret; 280 struct pipe_surface tmpl; 281 struct pipe_surface *surface; 282 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; 288 289 surface = pipe->create_surface(pipe, res, &tmpl); 290 if (surface == NULL) { 291 debug_printf("failed to create surface\n"); 292 return; 293 } 294 svga_surface_dst = svga_surface(surface); 295 296 union pipe_color_union color; 297 const struct util_format_description *desc = 298 util_format_description(surface->format); 299 300 if (util_format_is_depth_or_stencil(surface->format)) { 301 float depth; 302 uint8_t stencil; 303 unsigned clear_flags = 0; 304 305 /* If data is NULL, then set depthValue and stencilValue to zeros */ 306 if (data == NULL) { 307 depth = 0.0; 308 stencil = 0; 309 } 310 else { 311 desc->unpack_z_float(&depth, 0, data, 0, 1, 1); 312 desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1); 313 } 314 315 if (util_format_has_depth(desc)) { 316 clear_flags |= PIPE_CLEAR_DEPTH; 317 } 318 if (util_format_has_stencil(desc)) { 319 clear_flags |= PIPE_CLEAR_STENCIL; 320 } 321 322 /* Setup depth stencil view */ 323 struct pipe_surface *dsv = 324 svga_validate_surface_view(svga, svga_surface_dst); 325 326 if (!dsv) { 327 pipe_surface_reference(&surface, NULL); 328 return; 329 } 330 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 */ 334 335 336 ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, 337 clear_flags, 338 stencil, depth); 339 if (ret != PIPE_OK) { 340 /* flush and try again */ 341 svga_context_flush(svga, NULL); 342 ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, 343 clear_flags, 344 stencil, depth); 345 assert(ret == PIPE_OK); 346 } 347 } 348 else { 349 /* To clear subtexture use software fallback */ 350 351 util_blitter_save_framebuffer(svga->blitter, 352 &svga->curr.framebuffer); 353 begin_blit(svga); 354 util_blitter_clear_depth_stencil(svga->blitter, 355 dsv, clear_flags, 356 depth,stencil, 357 box->x, box->y, 358 box->width, box->height); 359 } 360 } 361 else { 362 /* non depth-stencil formats */ 363 364 if (data == NULL) { 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; 367 } 368 else { 369 if (util_format_is_pure_sint(surface->format)) { 370 /* signed integer */ 371 desc->unpack_rgba_sint(color.i, 0, data, 0, 1, 1); 372 } 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); 376 } 377 else { 378 /* floating point */ 379 desc->unpack_rgba_float(color.f, 0, data, 0, 1, 1); 380 } 381 } 382 383 /* Setup render target view */ 384 struct pipe_surface *rtv = 385 svga_validate_surface_view(svga, svga_surface_dst); 386 387 if (!rtv) { 388 pipe_surface_reference(&surface, NULL); 389 return; 390 } 391 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; 395 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); 400 } 401 else { 402 /* clearing whole surface using VGPU10 command */ 403 ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, 404 color.f); 405 if (ret != PIPE_OK) { 406 svga_context_flush(svga,NULL); 407 ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, 408 color.f); 409 assert(ret == PIPE_OK); 410 } 411 } 412 } 413 else { 414 /* To clear subtexture use software fallback */ 415 416 /** 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. 420 */ 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 PIPE_BIND_RENDER_TARGET)) { 426 /* clear with quad drawing */ 427 util_blitter_save_framebuffer(svga->blitter, 428 &svga->curr.framebuffer); 429 begin_blit(svga); 430 util_blitter_clear_render_target(svga->blitter, 431 rtv, 432 &color, 433 box->x, box->y, 434 box->width, box->height); 435 } 436 else { 437 /* clear with map/write/unmap */ 438 439 /* store layer values */ 440 unsigned first_layer = rtv->u.tex.first_layer; 441 unsigned last_layer = rtv->u.tex.last_layer; 442 unsigned box_depth = last_layer - first_layer + 1; 443 444 for (unsigned i = 0; i < box_depth; i++) { 445 rtv->u.tex.first_layer = rtv->u.tex.last_layer = 446 first_layer + i; 447 util_clear_render_target(pipe, rtv, &color, box->x, box->y, 448 box->width, box->height); 449 } 450 /* restore layer values */ 451 rtv->u.tex.first_layer = first_layer; 452 rtv->u.tex.last_layer = last_layer; 453 } 454 } 455 } 456 pipe_surface_reference(&surface, NULL); 457 } 458 459 /** 460 * \brief Clear the whole render target using vgpu10 functionality 461 * 462 * \param svga[in] The svga context 463 * \param dst[in] The surface to clear 464 * \param color[in] Clear color 465 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of 466 * command submission resources. 467 */ 468 static enum pipe_error 469 svga_try_clear_render_target(struct svga_context *svga, 470 struct pipe_surface *dst, 471 const union pipe_color_union *color) 472 { 473 struct pipe_surface *rtv = 474 svga_validate_surface_view(svga, svga_surface(dst)); 475 476 if (!rtv) 477 return PIPE_ERROR_OUT_OF_MEMORY; 478 479 return SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, color->f); 480 } 481 482 /** 483 * \brief Clear part of render target using gallium blitter utilities 484 * 485 * \param svga[in] The svga context 486 * \param dst[in] The surface to clear 487 * \param color[in] Clear color 488 * \param dstx[in] Clear region left 489 * \param dsty[in] Clear region top 490 * \param width[in] Clear region width 491 * \param height[in] Clear region height 492 */ 493 static void 494 svga_blitter_clear_render_target(struct svga_context *svga, 495 struct pipe_surface *dst, 496 const union pipe_color_union *color, 497 unsigned dstx, unsigned dsty, 498 unsigned width, unsigned height) 499 { 500 begin_blit(svga); 501 util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); 502 503 util_blitter_clear_render_target(svga->blitter, dst, color, 504 dstx, dsty, width, height); 505 } 506 507 /** 508 * \brief Toggle conditional rendering if already enabled 509 * 510 * \param svga[in] The svga context 511 * \param render_condition_enabled[in] Whether to ignore requests to turn 512 * conditional rendering off 513 * \param on[in] Whether to turn conditional rendering on or off 514 */ 515 static void 516 svga_toggle_render_condition(struct svga_context *svga, 517 boolean render_condition_enabled, 518 boolean on) 519 { 520 SVGA3dQueryId query_id; 521 enum pipe_error ret; 522 523 if (render_condition_enabled || 524 svga->pred.query_id == SVGA3D_INVALID_ID) { 525 return; 526 } 527 528 /* 529 * If we get here, it means that the system supports 530 * conditional rendering since svga->pred.query_id has already been 531 * modified for this context and thus support has already been 532 * verified. 533 */ 534 query_id = on ? svga->pred.query_id : SVGA3D_INVALID_ID; 535 536 ret = SVGA3D_vgpu10_SetPredication(svga->swc, query_id, 537 (uint32) svga->pred.cond); 538 if (ret == PIPE_ERROR_OUT_OF_MEMORY) { 539 svga_context_flush(svga, NULL); 540 ret = SVGA3D_vgpu10_SetPredication(svga->swc, query_id, 541 (uint32) svga->pred.cond); 542 assert(ret == PIPE_OK); 543 } 544 } 545 546 /** 547 * \brief Clear render target pipe callback 548 * 549 * \param pipe[in] The pipe context 550 * \param dst[in] The surface to clear 551 * \param color[in] Clear color 552 * \param dstx[in] Clear region left 553 * \param dsty[in] Clear region top 554 * \param width[in] Clear region width 555 * \param height[in] Clear region height 556 * \param render_condition_enabled[in] Whether to use conditional rendering 557 * to clear (if elsewhere enabled). 558 */ 559 static void 560 svga_clear_render_target(struct pipe_context *pipe, 561 struct pipe_surface *dst, 562 const union pipe_color_union *color, 563 unsigned dstx, unsigned dsty, 564 unsigned width, unsigned height, 565 bool render_condition_enabled) 566 { 567 struct svga_context *svga = svga_context( pipe ); 568 569 svga_toggle_render_condition(svga, render_condition_enabled, FALSE); 570 if (!svga_have_vgpu10(svga) || dstx != 0 || dsty != 0 || 571 width != dst->width || height != dst->height) { 572 svga_blitter_clear_render_target(svga, dst, color, dstx, dsty, width, 573 height); 574 } else { 575 enum pipe_error ret; 576 577 ret = svga_try_clear_render_target(svga, dst, color); 578 if (ret == PIPE_ERROR_OUT_OF_MEMORY) { 579 svga_context_flush( svga, NULL ); 580 ret = svga_try_clear_render_target(svga, dst, color); 581 } 582 583 assert (ret == PIPE_OK); 584 } 585 svga_toggle_render_condition(svga, render_condition_enabled, TRUE); 586 } 587 588 void svga_init_clear_functions(struct svga_context *svga) 589 { 590 svga->pipe.clear_render_target = svga_clear_render_target; 591 svga->pipe.clear_texture = svga_clear_texture; 592 svga->pipe.clear = svga_clear; 593 } 594