u_blit.c revision 6b3f1ae12b7d53bf88cdcf0e78803e929cdf5bbd
1/************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * @file 30 * Copy/blit pixel rect between surfaces 31 * 32 * @author Brian Paul 33 */ 34 35 36#include "pipe/p_context.h" 37#include "util/u_debug.h" 38#include "pipe/p_defines.h" 39#include "util/u_inlines.h" 40#include "pipe/p_shader_tokens.h" 41#include "pipe/p_state.h" 42 43#include "util/u_blit.h" 44#include "util/u_draw_quad.h" 45#include "util/u_format.h" 46#include "util/u_math.h" 47#include "util/u_memory.h" 48#include "util/u_sampler.h" 49#include "util/u_simple_shaders.h" 50 51#include "cso_cache/cso_context.h" 52 53 54struct blit_state 55{ 56 struct pipe_context *pipe; 57 struct cso_context *cso; 58 59 struct pipe_blend_state blend_write_color, blend_keep_color; 60 struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil; 61 struct pipe_depth_stencil_alpha_state dsa_write_depthstencil; 62 struct pipe_depth_stencil_alpha_state dsa_write_depth; 63 struct pipe_depth_stencil_alpha_state dsa_write_stencil; 64 struct pipe_rasterizer_state rasterizer; 65 struct pipe_sampler_state sampler; 66 struct pipe_viewport_state viewport; 67 struct pipe_vertex_element velem[2]; 68 enum pipe_texture_target internal_target; 69 70 void *vs; 71 void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1]; 72 void *fs_depthstencil[PIPE_MAX_TEXTURE_TYPES]; 73 void *fs_depth[PIPE_MAX_TEXTURE_TYPES]; 74 void *fs_stencil[PIPE_MAX_TEXTURE_TYPES]; 75 76 struct pipe_resource *vbuf; /**< quad vertices */ 77 unsigned vbuf_slot; 78 79 float vertices[4][2][4]; /**< vertex/texcoords for quad */ 80 81 boolean has_stencil_export; 82}; 83 84 85/** 86 * Create state object for blit. 87 * Intended to be created once and re-used for many blit() calls. 88 */ 89struct blit_state * 90util_create_blit(struct pipe_context *pipe, struct cso_context *cso) 91{ 92 struct blit_state *ctx; 93 uint i; 94 95 ctx = CALLOC_STRUCT(blit_state); 96 if (!ctx) 97 return NULL; 98 99 ctx->pipe = pipe; 100 ctx->cso = cso; 101 102 /* disabled blending/masking */ 103 ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA; 104 105 /* depth stencil states */ 106 ctx->dsa_write_depth.depth.enabled = 1; 107 ctx->dsa_write_depth.depth.writemask = 1; 108 ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS; 109 ctx->dsa_write_stencil.stencil[0].enabled = 1; 110 ctx->dsa_write_stencil.stencil[0].func = PIPE_FUNC_ALWAYS; 111 ctx->dsa_write_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 112 ctx->dsa_write_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 113 ctx->dsa_write_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 114 ctx->dsa_write_stencil.stencil[0].valuemask = 0xff; 115 ctx->dsa_write_stencil.stencil[0].writemask = 0xff; 116 ctx->dsa_write_depthstencil.depth = ctx->dsa_write_depth.depth; 117 ctx->dsa_write_depthstencil.stencil[0] = ctx->dsa_write_stencil.stencil[0]; 118 119 /* rasterizer */ 120 ctx->rasterizer.cull_face = PIPE_FACE_NONE; 121 ctx->rasterizer.gl_rasterization_rules = 1; 122 ctx->rasterizer.depth_clip = 1; 123 124 /* samplers */ 125 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 126 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 127 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 128 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 129 ctx->sampler.min_img_filter = 0; /* set later */ 130 ctx->sampler.mag_img_filter = 0; /* set later */ 131 132 /* vertex elements state */ 133 for (i = 0; i < 2; i++) { 134 ctx->velem[i].src_offset = i * 4 * sizeof(float); 135 ctx->velem[i].instance_divisor = 0; 136 ctx->velem[i].vertex_buffer_index = 0; 137 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 138 } 139 140 ctx->vbuf = NULL; 141 142 /* init vertex data that doesn't change */ 143 for (i = 0; i < 4; i++) { 144 ctx->vertices[i][0][3] = 1.0f; /* w */ 145 ctx->vertices[i][1][2] = 0.0f; /* r */ 146 ctx->vertices[i][1][3] = 1.0f; /* q */ 147 } 148 149 if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) 150 ctx->internal_target = PIPE_TEXTURE_2D; 151 else 152 ctx->internal_target = PIPE_TEXTURE_RECT; 153 154 ctx->has_stencil_export = 155 pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT); 156 157 return ctx; 158} 159 160 161/** 162 * Destroy a blit context 163 */ 164void 165util_destroy_blit(struct blit_state *ctx) 166{ 167 struct pipe_context *pipe = ctx->pipe; 168 unsigned i, j; 169 170 if (ctx->vs) 171 pipe->delete_vs_state(pipe, ctx->vs); 172 173 for (i = 0; i < Elements(ctx->fs); i++) { 174 for (j = 0; j < Elements(ctx->fs[i]); j++) { 175 if (ctx->fs[i][j]) 176 pipe->delete_fs_state(pipe, ctx->fs[i][j]); 177 } 178 } 179 180 for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { 181 if (ctx->fs_depthstencil[i]) { 182 pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]); 183 } 184 if (ctx->fs_depth[i]) { 185 pipe->delete_fs_state(pipe, ctx->fs_depth[i]); 186 } 187 if (ctx->fs_stencil[i]) { 188 pipe->delete_fs_state(pipe, ctx->fs_stencil[i]); 189 } 190 } 191 192 pipe_resource_reference(&ctx->vbuf, NULL); 193 194 FREE(ctx); 195} 196 197 198/** 199 * Helper function to set the fragment shaders. 200 */ 201static INLINE void 202set_fragment_shader(struct blit_state *ctx, uint writemask, 203 enum pipe_texture_target pipe_tex) 204{ 205 if (!ctx->fs[pipe_tex][writemask]) { 206 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 207 208 ctx->fs[pipe_tex][writemask] = 209 util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex, 210 TGSI_INTERPOLATE_LINEAR, 211 writemask); 212 } 213 214 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]); 215} 216 217 218/** 219 * Helper function to set the shader which writes depth and stencil. 220 */ 221static INLINE void 222set_depthstencil_fragment_shader(struct blit_state *ctx, 223 enum pipe_texture_target pipe_tex) 224{ 225 if (!ctx->fs_depthstencil[pipe_tex]) { 226 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 227 228 ctx->fs_depthstencil[pipe_tex] = 229 util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex, 230 TGSI_INTERPOLATE_LINEAR); 231 } 232 233 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]); 234} 235 236 237/** 238 * Helper function to set the shader which writes depth. 239 */ 240static INLINE void 241set_depth_fragment_shader(struct blit_state *ctx, 242 enum pipe_texture_target pipe_tex) 243{ 244 if (!ctx->fs_depth[pipe_tex]) { 245 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 246 247 ctx->fs_depth[pipe_tex] = 248 util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex, 249 TGSI_INTERPOLATE_LINEAR); 250 } 251 252 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]); 253} 254 255 256/** 257 * Helper function to set the shader which writes stencil. 258 */ 259static INLINE void 260set_stencil_fragment_shader(struct blit_state *ctx, 261 enum pipe_texture_target pipe_tex) 262{ 263 if (!ctx->fs_stencil[pipe_tex]) { 264 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 265 266 ctx->fs_stencil[pipe_tex] = 267 util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex, 268 TGSI_INTERPOLATE_LINEAR); 269 } 270 271 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]); 272} 273 274 275/** 276 * Helper function to set the vertex shader. 277 */ 278static INLINE void 279set_vertex_shader(struct blit_state *ctx) 280{ 281 /* vertex shader - still required to provide the linkage between 282 * fragment shader input semantics and vertex_element/buffers. 283 */ 284 if (!ctx->vs) { 285 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 286 TGSI_SEMANTIC_GENERIC }; 287 const uint semantic_indexes[] = { 0, 0 }; 288 ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, 289 semantic_names, 290 semantic_indexes); 291 } 292 293 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 294} 295 296 297/** 298 * Get offset of next free slot in vertex buffer for quad vertices. 299 */ 300static unsigned 301get_next_slot( struct blit_state *ctx ) 302{ 303 const unsigned max_slots = 4096 / sizeof ctx->vertices; 304 305 if (ctx->vbuf_slot >= max_slots) { 306 pipe_resource_reference(&ctx->vbuf, NULL); 307 ctx->vbuf_slot = 0; 308 } 309 310 if (!ctx->vbuf) { 311 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 312 PIPE_BIND_VERTEX_BUFFER, 313 PIPE_USAGE_STREAM, 314 max_slots * sizeof ctx->vertices); 315 } 316 317 return ctx->vbuf_slot++ * sizeof ctx->vertices; 318} 319 320 321 322 323/** 324 * Setup vertex data for the textured quad we'll draw. 325 * Note: y=0=top 326 */ 327static unsigned 328setup_vertex_data_tex(struct blit_state *ctx, 329 float x0, float y0, float x1, float y1, 330 float s0, float t0, float s1, float t1, 331 float z) 332{ 333 unsigned offset; 334 335 ctx->vertices[0][0][0] = x0; 336 ctx->vertices[0][0][1] = y0; 337 ctx->vertices[0][0][2] = z; 338 ctx->vertices[0][1][0] = s0; /*s*/ 339 ctx->vertices[0][1][1] = t0; /*t*/ 340 341 ctx->vertices[1][0][0] = x1; 342 ctx->vertices[1][0][1] = y0; 343 ctx->vertices[1][0][2] = z; 344 ctx->vertices[1][1][0] = s1; /*s*/ 345 ctx->vertices[1][1][1] = t0; /*t*/ 346 347 ctx->vertices[2][0][0] = x1; 348 ctx->vertices[2][0][1] = y1; 349 ctx->vertices[2][0][2] = z; 350 ctx->vertices[2][1][0] = s1; 351 ctx->vertices[2][1][1] = t1; 352 353 ctx->vertices[3][0][0] = x0; 354 ctx->vertices[3][0][1] = y1; 355 ctx->vertices[3][0][2] = z; 356 ctx->vertices[3][1][0] = s0; 357 ctx->vertices[3][1][1] = t1; 358 359 offset = get_next_slot( ctx ); 360 361 if (ctx->vbuf) { 362 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, 363 offset, sizeof(ctx->vertices), ctx->vertices); 364 } 365 366 return offset; 367} 368 369 370/** 371 * \return TRUE if two regions overlap, FALSE otherwise 372 */ 373static boolean 374regions_overlap(int srcX0, int srcY0, 375 int srcX1, int srcY1, 376 int dstX0, int dstY0, 377 int dstX1, int dstY1) 378{ 379 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) 380 return FALSE; /* src completely left of dst */ 381 382 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) 383 return FALSE; /* dst completely left of src */ 384 385 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) 386 return FALSE; /* src completely above dst */ 387 388 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) 389 return FALSE; /* dst completely above src */ 390 391 return TRUE; /* some overlap */ 392} 393 394 395/** 396 * Can we blit from src format to dest format with a simple copy? 397 */ 398static boolean 399formats_compatible(enum pipe_format src_format, 400 enum pipe_format dst_format) 401{ 402 if (src_format == dst_format) { 403 return TRUE; 404 } 405 else { 406 const struct util_format_description *src_desc = 407 util_format_description(src_format); 408 const struct util_format_description *dst_desc = 409 util_format_description(dst_format); 410 return util_is_format_compatible(src_desc, dst_desc); 411 } 412} 413 414 415/** 416 * Copy pixel block from src surface to dst surface. 417 * Overlapping regions are acceptable. 418 * Flipping and stretching are supported. 419 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR 420 * \param writemask controls which channels in the dest surface are sourced 421 * from the src surface. Disabled channels are sourced 422 * from (0,0,0,1). 423 */ 424void 425util_blit_pixels(struct blit_state *ctx, 426 struct pipe_resource *src_tex, 427 unsigned src_level, 428 int srcX0, int srcY0, 429 int srcX1, int srcY1, 430 int srcZ0, 431 struct pipe_surface *dst, 432 int dstX0, int dstY0, 433 int dstX1, int dstY1, 434 float z, uint filter, 435 uint writemask, uint zs_writemask) 436{ 437 struct pipe_context *pipe = ctx->pipe; 438 struct pipe_screen *screen = pipe->screen; 439 enum pipe_format src_format, dst_format; 440 struct pipe_sampler_view *sampler_view = NULL; 441 struct pipe_sampler_view sv_templ; 442 struct pipe_surface *dst_surface; 443 struct pipe_framebuffer_state fb; 444 const int srcW = abs(srcX1 - srcX0); 445 const int srcH = abs(srcY1 - srcY0); 446 unsigned offset; 447 boolean overlap; 448 float s0, t0, s1, t1; 449 boolean normalized; 450 boolean is_stencil, is_depth, blit_depth, blit_stencil; 451 const struct util_format_description *src_desc = 452 util_format_description(src_tex->format); 453 454 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 455 filter == PIPE_TEX_MIPFILTER_LINEAR); 456 457 assert(src_level <= src_tex->last_level); 458 459 /* do the regions overlap? */ 460 overlap = src_tex == dst->texture && 461 dst->u.tex.level == src_level && 462 dst->u.tex.first_layer == srcZ0 && 463 regions_overlap(srcX0, srcY0, srcX1, srcY1, 464 dstX0, dstY0, dstX1, dstY1); 465 466 src_format = util_format_linear(src_tex->format); 467 dst_format = util_format_linear(dst->format); 468 469 /* See whether we will blit depth or stencil. */ 470 is_depth = util_format_has_depth(src_desc); 471 is_stencil = util_format_has_stencil(src_desc); 472 473 blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z); 474 blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL); 475 476 assert((writemask && !zs_writemask && !is_depth && !is_stencil) || 477 (!writemask && (blit_depth || blit_stencil))); 478 479 /* 480 * Check for simple case: no format conversion, no flipping, no stretching, 481 * no overlapping, same number of samples. 482 * Filter mode should not matter since there's no stretching. 483 */ 484 if (formats_compatible(src_format, dst_format) && 485 src_tex->nr_samples == dst->texture->nr_samples && 486 is_stencil == blit_stencil && 487 is_depth == blit_depth && 488 srcX0 < srcX1 && 489 dstX0 < dstX1 && 490 srcY0 < srcY1 && 491 dstY0 < dstY1 && 492 (dstX1 - dstX0) == (srcX1 - srcX0) && 493 (dstY1 - dstY0) == (srcY1 - srcY0) && 494 !overlap) { 495 struct pipe_box src_box; 496 src_box.x = srcX0; 497 src_box.y = srcY0; 498 src_box.z = srcZ0; 499 src_box.width = srcW; 500 src_box.height = srcH; 501 src_box.depth = 1; 502 pipe->resource_copy_region(pipe, 503 dst->texture, dst->u.tex.level, 504 dstX0, dstY0, dst->u.tex.first_layer,/* dest */ 505 src_tex, src_level, 506 &src_box); 507 return; 508 } 509 510 /* It's a mistake to call this function with a stencil format and 511 * without shader stencil export. We don't do software fallbacks here. 512 * Ignore stencil and only copy depth. 513 */ 514 if (blit_stencil && !ctx->has_stencil_export) { 515 blit_stencil = FALSE; 516 517 if (!blit_depth) 518 return; 519 } 520 521 if (dst_format == dst->format) { 522 dst_surface = dst; 523 } else { 524 struct pipe_surface templ = *dst; 525 templ.format = dst_format; 526 dst_surface = pipe->create_surface(pipe, dst->texture, &templ); 527 } 528 529 /* Create a temporary texture when src and dest alias. 530 */ 531 if (src_tex == dst_surface->texture && 532 dst_surface->u.tex.level == src_level && 533 dst_surface->u.tex.first_layer == srcZ0) { 534 /* Make a temporary texture which contains a copy of the source pixels. 535 * Then we'll sample from the temporary texture. 536 */ 537 struct pipe_resource texTemp; 538 struct pipe_resource *tex; 539 struct pipe_sampler_view sv_templ; 540 struct pipe_box src_box; 541 const int srcLeft = MIN2(srcX0, srcX1); 542 const int srcTop = MIN2(srcY0, srcY1); 543 544 if (srcLeft != srcX0) { 545 /* left-right flip */ 546 int tmp = dstX0; 547 dstX0 = dstX1; 548 dstX1 = tmp; 549 } 550 551 if (srcTop != srcY0) { 552 /* up-down flip */ 553 int tmp = dstY0; 554 dstY0 = dstY1; 555 dstY1 = tmp; 556 } 557 558 /* create temp texture */ 559 memset(&texTemp, 0, sizeof(texTemp)); 560 texTemp.target = ctx->internal_target; 561 texTemp.format = src_format; 562 texTemp.last_level = 0; 563 texTemp.width0 = srcW; 564 texTemp.height0 = srcH; 565 texTemp.depth0 = 1; 566 texTemp.array_size = 1; 567 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 568 569 tex = screen->resource_create(screen, &texTemp); 570 if (!tex) 571 return; 572 573 src_box.x = srcLeft; 574 src_box.y = srcTop; 575 src_box.z = srcZ0; 576 src_box.width = srcW; 577 src_box.height = srcH; 578 src_box.depth = 1; 579 /* load temp texture */ 580 pipe->resource_copy_region(pipe, 581 tex, 0, 0, 0, 0, /* dest */ 582 src_tex, src_level, &src_box); 583 584 normalized = tex->target != PIPE_TEXTURE_RECT; 585 if(normalized) { 586 s0 = 0.0f; 587 s1 = 1.0f; 588 t0 = 0.0f; 589 t1 = 1.0f; 590 } 591 else { 592 s0 = 0; 593 s1 = srcW; 594 t0 = 0; 595 t1 = srcH; 596 } 597 598 u_sampler_view_default_template(&sv_templ, tex, tex->format); 599 if (!blit_depth && blit_stencil) { 600 /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ 601 sv_templ.format = util_format_stencil_only(tex->format); 602 assert(sv_templ.format != PIPE_FORMAT_NONE); 603 } 604 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); 605 606 if (!sampler_view) { 607 pipe_resource_reference(&tex, NULL); 608 return; 609 } 610 pipe_resource_reference(&tex, NULL); 611 } 612 else { 613 /* Directly sample from the source resource/texture */ 614 u_sampler_view_default_template(&sv_templ, src_tex, src_format); 615 if (!blit_depth && blit_stencil) { 616 /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ 617 sv_templ.format = util_format_stencil_only(src_format); 618 assert(sv_templ.format != PIPE_FORMAT_NONE); 619 } 620 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); 621 622 if (!sampler_view) { 623 return; 624 } 625 626 s0 = srcX0; 627 s1 = srcX1; 628 t0 = srcY0; 629 t1 = srcY1; 630 normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT; 631 if(normalized) 632 { 633 s0 /= (float)(u_minify(sampler_view->texture->width0, src_level)); 634 s1 /= (float)(u_minify(sampler_view->texture->width0, src_level)); 635 t0 /= (float)(u_minify(sampler_view->texture->height0, src_level)); 636 t1 /= (float)(u_minify(sampler_view->texture->height0, src_level)); 637 } 638 } 639 640 assert(screen->is_format_supported(screen, sampler_view->format, 641 ctx->internal_target, sampler_view->texture->nr_samples, 642 PIPE_BIND_SAMPLER_VIEW)); 643 assert(screen->is_format_supported(screen, dst_format, ctx->internal_target, 644 dst_surface->texture->nr_samples, 645 is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL : 646 PIPE_BIND_RENDER_TARGET)); 647 648 /* save state (restored below) */ 649 cso_save_blend(ctx->cso); 650 cso_save_depth_stencil_alpha(ctx->cso); 651 cso_save_rasterizer(ctx->cso); 652 cso_save_sample_mask(ctx->cso); 653 cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); 654 cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); 655 cso_save_stream_outputs(ctx->cso); 656 cso_save_viewport(ctx->cso); 657 cso_save_framebuffer(ctx->cso); 658 cso_save_fragment_shader(ctx->cso); 659 cso_save_vertex_shader(ctx->cso); 660 cso_save_geometry_shader(ctx->cso); 661 cso_save_vertex_elements(ctx->cso); 662 cso_save_vertex_buffers(ctx->cso); 663 664 /* set misc state we care about */ 665 if (writemask) 666 cso_set_blend(ctx->cso, &ctx->blend_write_color); 667 else 668 cso_set_blend(ctx->cso, &ctx->blend_keep_color); 669 670 cso_set_sample_mask(ctx->cso, ~0); 671 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 672 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 673 cso_set_stream_outputs(ctx->cso, 0, NULL, 0); 674 675 /* default sampler state */ 676 ctx->sampler.normalized_coords = normalized; 677 ctx->sampler.min_img_filter = filter; 678 ctx->sampler.mag_img_filter = filter; 679 ctx->sampler.min_lod = src_level; 680 ctx->sampler.max_lod = src_level; 681 682 /* Depth stencil state, fragment shader and sampler setup depending on what 683 * we blit. 684 */ 685 if (blit_depth && blit_stencil) { 686 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); 687 /* don't filter stencil */ 688 ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 689 ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 690 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler); 691 692 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil); 693 set_depthstencil_fragment_shader(ctx, sampler_view->texture->target); 694 } 695 else if (blit_depth) { 696 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); 697 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth); 698 set_depth_fragment_shader(ctx, sampler_view->texture->target); 699 } 700 else if (blit_stencil) { 701 /* don't filter stencil */ 702 ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 703 ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 704 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); 705 706 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil); 707 set_stencil_fragment_shader(ctx, sampler_view->texture->target); 708 } 709 else { /* color */ 710 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); 711 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); 712 set_fragment_shader(ctx, writemask, sampler_view->texture->target); 713 } 714 cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); 715 716 /* textures */ 717 if (blit_depth && blit_stencil) { 718 /* Setup two samplers, one for depth and the other one for stencil. */ 719 struct pipe_sampler_view templ; 720 struct pipe_sampler_view *views[2]; 721 722 templ = *sampler_view; 723 templ.format = util_format_stencil_only(templ.format); 724 assert(templ.format != PIPE_FORMAT_NONE); 725 726 views[0] = sampler_view; 727 views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ); 728 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views); 729 730 pipe_sampler_view_reference(&views[1], NULL); 731 } 732 else { 733 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view); 734 } 735 736 /* viewport */ 737 ctx->viewport.scale[0] = 0.5f * dst_surface->width; 738 ctx->viewport.scale[1] = 0.5f * dst_surface->height; 739 ctx->viewport.scale[2] = 0.5f; 740 ctx->viewport.scale[3] = 1.0f; 741 ctx->viewport.translate[0] = 0.5f * dst_surface->width; 742 ctx->viewport.translate[1] = 0.5f * dst_surface->height; 743 ctx->viewport.translate[2] = 0.5f; 744 ctx->viewport.translate[3] = 0.0f; 745 cso_set_viewport(ctx->cso, &ctx->viewport); 746 747 set_vertex_shader(ctx); 748 cso_set_geometry_shader_handle(ctx->cso, NULL); 749 750 /* drawing dest */ 751 memset(&fb, 0, sizeof(fb)); 752 fb.width = dst_surface->width; 753 fb.height = dst_surface->height; 754 if (blit_depth || blit_stencil) { 755 fb.zsbuf = dst_surface; 756 } else { 757 fb.nr_cbufs = 1; 758 fb.cbufs[0] = dst_surface; 759 } 760 cso_set_framebuffer(ctx->cso, &fb); 761 762 /* draw quad */ 763 offset = setup_vertex_data_tex(ctx, 764 (float) dstX0 / dst_surface->width * 2.0f - 1.0f, 765 (float) dstY0 / dst_surface->height * 2.0f - 1.0f, 766 (float) dstX1 / dst_surface->width * 2.0f - 1.0f, 767 (float) dstY1 / dst_surface->height * 2.0f - 1.0f, 768 s0, t0, 769 s1, t1, 770 z); 771 772 if (ctx->vbuf) { 773 util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset, 774 PIPE_PRIM_TRIANGLE_FAN, 775 4, /* verts */ 776 2); /* attribs/vert */ 777 } 778 779 /* restore state we changed */ 780 cso_restore_blend(ctx->cso); 781 cso_restore_depth_stencil_alpha(ctx->cso); 782 cso_restore_rasterizer(ctx->cso); 783 cso_restore_sample_mask(ctx->cso); 784 cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); 785 cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); 786 cso_restore_viewport(ctx->cso); 787 cso_restore_framebuffer(ctx->cso); 788 cso_restore_fragment_shader(ctx->cso); 789 cso_restore_vertex_shader(ctx->cso); 790 cso_restore_geometry_shader(ctx->cso); 791 cso_restore_vertex_elements(ctx->cso); 792 cso_restore_vertex_buffers(ctx->cso); 793 cso_restore_stream_outputs(ctx->cso); 794 795 pipe_sampler_view_reference(&sampler_view, NULL); 796 if (dst_surface != dst) 797 pipe_surface_reference(&dst_surface, NULL); 798} 799 800 801/** 802 * Copy pixel block from src texture to dst surface. 803 * The sampler view's first_level field indicates the source 804 * mipmap level to use. 805 * XXX need some control over blitting Z and/or stencil. 806 */ 807void 808util_blit_pixels_tex(struct blit_state *ctx, 809 struct pipe_sampler_view *src_sampler_view, 810 int srcX0, int srcY0, 811 int srcX1, int srcY1, 812 struct pipe_surface *dst, 813 int dstX0, int dstY0, 814 int dstX1, int dstY1, 815 float z, uint filter) 816{ 817 boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT; 818 struct pipe_framebuffer_state fb; 819 float s0, t0, s1, t1; 820 unsigned offset; 821 struct pipe_resource *tex = src_sampler_view->texture; 822 823 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 824 filter == PIPE_TEX_MIPFILTER_LINEAR); 825 826 assert(tex); 827 assert(tex->width0 != 0); 828 assert(tex->height0 != 0); 829 830 s0 = srcX0; 831 s1 = srcX1; 832 t0 = srcY0; 833 t1 = srcY1; 834 835 if(normalized) 836 { 837 /* normalize according to the mipmap level's size */ 838 int level = src_sampler_view->u.tex.first_level; 839 float w = (float) u_minify(tex->width0, level); 840 float h = (float) u_minify(tex->height0, level); 841 s0 /= w; 842 s1 /= w; 843 t0 /= h; 844 t1 /= h; 845 } 846 847 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, 848 PIPE_TEXTURE_2D, 849 dst->texture->nr_samples, 850 PIPE_BIND_RENDER_TARGET)); 851 852 /* save state (restored below) */ 853 cso_save_blend(ctx->cso); 854 cso_save_depth_stencil_alpha(ctx->cso); 855 cso_save_rasterizer(ctx->cso); 856 cso_save_sample_mask(ctx->cso); 857 cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); 858 cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); 859 cso_save_stream_outputs(ctx->cso); 860 cso_save_viewport(ctx->cso); 861 cso_save_framebuffer(ctx->cso); 862 cso_save_fragment_shader(ctx->cso); 863 cso_save_vertex_shader(ctx->cso); 864 cso_save_geometry_shader(ctx->cso); 865 cso_save_vertex_elements(ctx->cso); 866 cso_save_vertex_buffers(ctx->cso); 867 868 /* set misc state we care about */ 869 cso_set_blend(ctx->cso, &ctx->blend_write_color); 870 cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); 871 cso_set_sample_mask(ctx->cso, ~0); 872 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 873 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 874 cso_set_stream_outputs(ctx->cso, 0, NULL, 0); 875 876 /* sampler */ 877 ctx->sampler.normalized_coords = normalized; 878 ctx->sampler.min_img_filter = filter; 879 ctx->sampler.mag_img_filter = filter; 880 cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); 881 cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); 882 883 /* viewport */ 884 ctx->viewport.scale[0] = 0.5f * dst->width; 885 ctx->viewport.scale[1] = 0.5f * dst->height; 886 ctx->viewport.scale[2] = 0.5f; 887 ctx->viewport.scale[3] = 1.0f; 888 ctx->viewport.translate[0] = 0.5f * dst->width; 889 ctx->viewport.translate[1] = 0.5f * dst->height; 890 ctx->viewport.translate[2] = 0.5f; 891 ctx->viewport.translate[3] = 0.0f; 892 cso_set_viewport(ctx->cso, &ctx->viewport); 893 894 /* texture */ 895 cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view); 896 897 /* shaders */ 898 set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW, 899 src_sampler_view->texture->target); 900 set_vertex_shader(ctx); 901 cso_set_geometry_shader_handle(ctx->cso, NULL); 902 903 /* drawing dest */ 904 memset(&fb, 0, sizeof(fb)); 905 fb.width = dst->width; 906 fb.height = dst->height; 907 fb.nr_cbufs = 1; 908 fb.cbufs[0] = dst; 909 cso_set_framebuffer(ctx->cso, &fb); 910 911 /* draw quad */ 912 offset = setup_vertex_data_tex(ctx, 913 (float) dstX0 / dst->width * 2.0f - 1.0f, 914 (float) dstY0 / dst->height * 2.0f - 1.0f, 915 (float) dstX1 / dst->width * 2.0f - 1.0f, 916 (float) dstY1 / dst->height * 2.0f - 1.0f, 917 s0, t0, s1, t1, 918 z); 919 920 util_draw_vertex_buffer(ctx->pipe, ctx->cso, 921 ctx->vbuf, offset, 922 PIPE_PRIM_TRIANGLE_FAN, 923 4, /* verts */ 924 2); /* attribs/vert */ 925 926 /* restore state we changed */ 927 cso_restore_blend(ctx->cso); 928 cso_restore_depth_stencil_alpha(ctx->cso); 929 cso_restore_rasterizer(ctx->cso); 930 cso_restore_sample_mask(ctx->cso); 931 cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); 932 cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); 933 cso_restore_viewport(ctx->cso); 934 cso_restore_framebuffer(ctx->cso); 935 cso_restore_fragment_shader(ctx->cso); 936 cso_restore_vertex_shader(ctx->cso); 937 cso_restore_geometry_shader(ctx->cso); 938 cso_restore_vertex_elements(ctx->cso); 939 cso_restore_vertex_buffers(ctx->cso); 940 cso_restore_stream_outputs(ctx->cso); 941} 942