u_blit.c revision a7f3697eb849376dda23556df479127909cb7fd4
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 depthstencil_keep; 61 struct pipe_depth_stencil_alpha_state depthstencil_write; 62 struct pipe_rasterizer_state rasterizer; 63 struct pipe_sampler_state sampler; 64 struct pipe_viewport_state viewport; 65 struct pipe_vertex_element velem[2]; 66 enum pipe_texture_target internal_target; 67 68 void *vs; 69 void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1]; 70 void *fs_depth[PIPE_MAX_TEXTURE_TYPES]; 71 72 struct pipe_resource *vbuf; /**< quad vertices */ 73 unsigned vbuf_slot; 74 75 float vertices[4][2][4]; /**< vertex/texcoords for quad */ 76}; 77 78 79/** 80 * Create state object for blit. 81 * Intended to be created once and re-used for many blit() calls. 82 */ 83struct blit_state * 84util_create_blit(struct pipe_context *pipe, struct cso_context *cso) 85{ 86 struct blit_state *ctx; 87 uint i; 88 89 ctx = CALLOC_STRUCT(blit_state); 90 if (!ctx) 91 return NULL; 92 93 ctx->pipe = pipe; 94 ctx->cso = cso; 95 96 /* disabled blending/masking */ 97 ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA; 98 99 /* no-op depth/stencil/alpha */ 100 ctx->depthstencil_write.depth.enabled = 1; 101 ctx->depthstencil_write.depth.writemask = 1; 102 ctx->depthstencil_write.depth.func = PIPE_FUNC_ALWAYS; 103 104 /* rasterizer */ 105 ctx->rasterizer.cull_face = PIPE_FACE_NONE; 106 ctx->rasterizer.gl_rasterization_rules = 1; 107 ctx->rasterizer.depth_clip = 1; 108 109 /* samplers */ 110 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 111 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 112 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 113 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 114 ctx->sampler.min_img_filter = 0; /* set later */ 115 ctx->sampler.mag_img_filter = 0; /* set later */ 116 117 /* vertex elements state */ 118 for (i = 0; i < 2; i++) { 119 ctx->velem[i].src_offset = i * 4 * sizeof(float); 120 ctx->velem[i].instance_divisor = 0; 121 ctx->velem[i].vertex_buffer_index = 0; 122 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 123 } 124 125 ctx->vbuf = NULL; 126 127 /* init vertex data that doesn't change */ 128 for (i = 0; i < 4; i++) { 129 ctx->vertices[i][0][3] = 1.0f; /* w */ 130 ctx->vertices[i][1][2] = 0.0f; /* r */ 131 ctx->vertices[i][1][3] = 1.0f; /* q */ 132 } 133 134 if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES)) 135 ctx->internal_target = PIPE_TEXTURE_2D; 136 else 137 ctx->internal_target = PIPE_TEXTURE_RECT; 138 139 return ctx; 140} 141 142 143/** 144 * Destroy a blit context 145 */ 146void 147util_destroy_blit(struct blit_state *ctx) 148{ 149 struct pipe_context *pipe = ctx->pipe; 150 unsigned i, j; 151 152 if (ctx->vs) 153 pipe->delete_vs_state(pipe, ctx->vs); 154 155 for (i = 0; i < Elements(ctx->fs); i++) { 156 for (j = 0; j < Elements(ctx->fs[i]); j++) { 157 if (ctx->fs[i][j]) 158 pipe->delete_fs_state(pipe, ctx->fs[i][j]); 159 } 160 } 161 162 for (i = 0; i < Elements(ctx->fs_depth); i++) { 163 if (ctx->fs_depth[i]) { 164 pipe->delete_fs_state(pipe, ctx->fs_depth[i]); 165 } 166 } 167 168 pipe_resource_reference(&ctx->vbuf, NULL); 169 170 FREE(ctx); 171} 172 173 174/** 175 * Helper function to set the fragment shaders. 176 */ 177static INLINE void 178set_fragment_shader(struct blit_state *ctx, uint writemask, 179 enum pipe_texture_target pipe_tex) 180{ 181 if (!ctx->fs[pipe_tex][writemask]) { 182 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 183 184 ctx->fs[pipe_tex][writemask] = 185 util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex, 186 TGSI_INTERPOLATE_LINEAR, 187 writemask); 188 } 189 190 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]); 191} 192 193 194/** 195 * Helper function to set the depthwrite shader. 196 */ 197static INLINE void 198set_depth_fragment_shader(struct blit_state *ctx, 199 enum pipe_texture_target pipe_tex) 200{ 201 if (!ctx->fs_depth[pipe_tex]) { 202 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex); 203 204 ctx->fs_depth[pipe_tex] = 205 util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex, 206 TGSI_INTERPOLATE_LINEAR); 207 } 208 209 cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]); 210} 211 212 213/** 214 * Helper function to set the vertex shader. 215 */ 216static INLINE void 217set_vertex_shader(struct blit_state *ctx) 218{ 219 /* vertex shader - still required to provide the linkage between 220 * fragment shader input semantics and vertex_element/buffers. 221 */ 222 if (!ctx->vs) { 223 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 224 TGSI_SEMANTIC_GENERIC }; 225 const uint semantic_indexes[] = { 0, 0 }; 226 ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2, 227 semantic_names, 228 semantic_indexes); 229 } 230 231 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 232} 233 234 235/** 236 * Get offset of next free slot in vertex buffer for quad vertices. 237 */ 238static unsigned 239get_next_slot( struct blit_state *ctx ) 240{ 241 const unsigned max_slots = 4096 / sizeof ctx->vertices; 242 243 if (ctx->vbuf_slot >= max_slots) { 244 pipe_resource_reference(&ctx->vbuf, NULL); 245 ctx->vbuf_slot = 0; 246 } 247 248 if (!ctx->vbuf) { 249 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 250 PIPE_BIND_VERTEX_BUFFER, 251 PIPE_USAGE_STREAM, 252 max_slots * sizeof ctx->vertices); 253 } 254 255 return ctx->vbuf_slot++ * sizeof ctx->vertices; 256} 257 258 259 260 261/** 262 * Setup vertex data for the textured quad we'll draw. 263 * Note: y=0=top 264 */ 265static unsigned 266setup_vertex_data_tex(struct blit_state *ctx, 267 float x0, float y0, float x1, float y1, 268 float s0, float t0, float s1, float t1, 269 float z) 270{ 271 unsigned offset; 272 273 ctx->vertices[0][0][0] = x0; 274 ctx->vertices[0][0][1] = y0; 275 ctx->vertices[0][0][2] = z; 276 ctx->vertices[0][1][0] = s0; /*s*/ 277 ctx->vertices[0][1][1] = t0; /*t*/ 278 279 ctx->vertices[1][0][0] = x1; 280 ctx->vertices[1][0][1] = y0; 281 ctx->vertices[1][0][2] = z; 282 ctx->vertices[1][1][0] = s1; /*s*/ 283 ctx->vertices[1][1][1] = t0; /*t*/ 284 285 ctx->vertices[2][0][0] = x1; 286 ctx->vertices[2][0][1] = y1; 287 ctx->vertices[2][0][2] = z; 288 ctx->vertices[2][1][0] = s1; 289 ctx->vertices[2][1][1] = t1; 290 291 ctx->vertices[3][0][0] = x0; 292 ctx->vertices[3][0][1] = y1; 293 ctx->vertices[3][0][2] = z; 294 ctx->vertices[3][1][0] = s0; 295 ctx->vertices[3][1][1] = t1; 296 297 offset = get_next_slot( ctx ); 298 299 if (ctx->vbuf) { 300 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, 301 offset, sizeof(ctx->vertices), ctx->vertices); 302 } 303 304 return offset; 305} 306 307 308/** 309 * \return TRUE if two regions overlap, FALSE otherwise 310 */ 311static boolean 312regions_overlap(int srcX0, int srcY0, 313 int srcX1, int srcY1, 314 int dstX0, int dstY0, 315 int dstX1, int dstY1) 316{ 317 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) 318 return FALSE; /* src completely left of dst */ 319 320 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) 321 return FALSE; /* dst completely left of src */ 322 323 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) 324 return FALSE; /* src completely above dst */ 325 326 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) 327 return FALSE; /* dst completely above src */ 328 329 return TRUE; /* some overlap */ 330} 331 332 333/** 334 * Can we blit from src format to dest format with a simple copy? 335 */ 336static boolean 337formats_compatible(enum pipe_format src_format, 338 enum pipe_format dst_format) 339{ 340 if (src_format == dst_format) { 341 return TRUE; 342 } 343 else { 344 const struct util_format_description *src_desc = 345 util_format_description(src_format); 346 const struct util_format_description *dst_desc = 347 util_format_description(dst_format); 348 return util_is_format_compatible(src_desc, dst_desc); 349 } 350} 351 352 353/** 354 * Copy pixel block from src surface to dst surface. 355 * Overlapping regions are acceptable. 356 * Flipping and stretching are supported. 357 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR 358 * \param writemask controls which channels in the dest surface are sourced 359 * from the src surface. Disabled channels are sourced 360 * from (0,0,0,1). 361 * XXX need some control over blitting stencil. 362 */ 363void 364util_blit_pixels(struct blit_state *ctx, 365 struct pipe_resource *src_tex, 366 unsigned src_level, 367 int srcX0, int srcY0, 368 int srcX1, int srcY1, 369 int srcZ0, 370 struct pipe_surface *dst, 371 int dstX0, int dstY0, 372 int dstX1, int dstY1, 373 float z, uint filter, 374 uint writemask) 375{ 376 struct pipe_context *pipe = ctx->pipe; 377 struct pipe_screen *screen = pipe->screen; 378 enum pipe_format src_format, dst_format; 379 struct pipe_sampler_view *sampler_view = NULL; 380 struct pipe_sampler_view sv_templ; 381 struct pipe_surface *dst_surface; 382 struct pipe_framebuffer_state fb; 383 const int srcW = abs(srcX1 - srcX0); 384 const int srcH = abs(srcY1 - srcY0); 385 unsigned offset; 386 boolean overlap, dst_is_depth; 387 float s0, t0, s1, t1; 388 boolean normalized; 389 390 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 391 filter == PIPE_TEX_MIPFILTER_LINEAR); 392 393 assert(src_level <= src_tex->last_level); 394 395 /* do the regions overlap? */ 396 overlap = src_tex == dst->texture && 397 dst->u.tex.level == src_level && 398 dst->u.tex.first_layer == srcZ0 && 399 regions_overlap(srcX0, srcY0, srcX1, srcY1, 400 dstX0, dstY0, dstX1, dstY1); 401 402 src_format = util_format_linear(src_tex->format); 403 dst_format = util_format_linear(dst->format); 404 405 /* 406 * Check for simple case: no format conversion, no flipping, no stretching, 407 * no overlapping. 408 * Filter mode should not matter since there's no stretching. 409 */ 410 if (formats_compatible(src_format, dst_format) && 411 srcX0 < srcX1 && 412 dstX0 < dstX1 && 413 srcY0 < srcY1 && 414 dstY0 < dstY1 && 415 (dstX1 - dstX0) == (srcX1 - srcX0) && 416 (dstY1 - dstY0) == (srcY1 - srcY0) && 417 !overlap) { 418 struct pipe_box src_box; 419 src_box.x = srcX0; 420 src_box.y = srcY0; 421 src_box.z = srcZ0; 422 src_box.width = srcW; 423 src_box.height = srcH; 424 src_box.depth = 1; 425 pipe->resource_copy_region(pipe, 426 dst->texture, dst->u.tex.level, 427 dstX0, dstY0, dst->u.tex.first_layer,/* dest */ 428 src_tex, src_level, 429 &src_box); 430 return; 431 } 432 433 if (dst_format == dst->format) { 434 dst_surface = dst; 435 } else { 436 struct pipe_surface templ = *dst; 437 templ.format = dst_format; 438 dst_surface = pipe->create_surface(pipe, dst->texture, &templ); 439 } 440 441 /* Create a temporary texture when src and dest alias. 442 */ 443 if (src_tex == dst_surface->texture && 444 dst_surface->u.tex.level == src_level && 445 dst_surface->u.tex.first_layer == srcZ0) { 446 /* Make a temporary texture which contains a copy of the source pixels. 447 * Then we'll sample from the temporary texture. 448 */ 449 struct pipe_resource texTemp; 450 struct pipe_resource *tex; 451 struct pipe_sampler_view sv_templ; 452 struct pipe_box src_box; 453 const int srcLeft = MIN2(srcX0, srcX1); 454 const int srcTop = MIN2(srcY0, srcY1); 455 456 if (srcLeft != srcX0) { 457 /* left-right flip */ 458 int tmp = dstX0; 459 dstX0 = dstX1; 460 dstX1 = tmp; 461 } 462 463 if (srcTop != srcY0) { 464 /* up-down flip */ 465 int tmp = dstY0; 466 dstY0 = dstY1; 467 dstY1 = tmp; 468 } 469 470 /* create temp texture */ 471 memset(&texTemp, 0, sizeof(texTemp)); 472 texTemp.target = ctx->internal_target; 473 texTemp.format = src_format; 474 texTemp.last_level = 0; 475 texTemp.width0 = srcW; 476 texTemp.height0 = srcH; 477 texTemp.depth0 = 1; 478 texTemp.array_size = 1; 479 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 480 481 tex = screen->resource_create(screen, &texTemp); 482 if (!tex) 483 return; 484 485 src_box.x = srcLeft; 486 src_box.y = srcTop; 487 src_box.z = srcZ0; 488 src_box.width = srcW; 489 src_box.height = srcH; 490 src_box.depth = 1; 491 /* load temp texture */ 492 pipe->resource_copy_region(pipe, 493 tex, 0, 0, 0, 0, /* dest */ 494 src_tex, src_level, &src_box); 495 496 normalized = tex->target != PIPE_TEXTURE_RECT; 497 if(normalized) { 498 s0 = 0.0f; 499 s1 = 1.0f; 500 t0 = 0.0f; 501 t1 = 1.0f; 502 } 503 else { 504 s0 = 0; 505 s1 = srcW; 506 t0 = 0; 507 t1 = srcH; 508 } 509 510 u_sampler_view_default_template(&sv_templ, tex, tex->format); 511 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); 512 513 if (!sampler_view) { 514 pipe_resource_reference(&tex, NULL); 515 return; 516 } 517 pipe_resource_reference(&tex, NULL); 518 } 519 else { 520 /* Directly sample from the source resource/texture */ 521 u_sampler_view_default_template(&sv_templ, src_tex, src_format); 522 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); 523 524 if (!sampler_view) { 525 return; 526 } 527 528 s0 = srcX0; 529 s1 = srcX1; 530 t0 = srcY0; 531 t1 = srcY1; 532 normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT; 533 if(normalized) 534 { 535 s0 /= (float)(u_minify(sampler_view->texture->width0, src_level)); 536 s1 /= (float)(u_minify(sampler_view->texture->width0, src_level)); 537 t0 /= (float)(u_minify(sampler_view->texture->height0, src_level)); 538 t1 /= (float)(u_minify(sampler_view->texture->height0, src_level)); 539 } 540 } 541 542 dst_is_depth = util_format_is_depth_or_stencil(dst_format); 543 544 assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target, 545 sampler_view->texture->nr_samples, 546 PIPE_BIND_SAMPLER_VIEW)); 547 assert(screen->is_format_supported(screen, dst_format, ctx->internal_target, 548 dst_surface->texture->nr_samples, 549 dst_is_depth ? PIPE_BIND_DEPTH_STENCIL : 550 PIPE_BIND_RENDER_TARGET)); 551 /* save state (restored below) */ 552 cso_save_blend(ctx->cso); 553 cso_save_depth_stencil_alpha(ctx->cso); 554 cso_save_rasterizer(ctx->cso); 555 cso_save_samplers(ctx->cso); 556 cso_save_fragment_sampler_views(ctx->cso); 557 cso_save_stream_outputs(ctx->cso); 558 cso_save_viewport(ctx->cso); 559 cso_save_framebuffer(ctx->cso); 560 cso_save_fragment_shader(ctx->cso); 561 cso_save_vertex_shader(ctx->cso); 562 cso_save_geometry_shader(ctx->cso); 563 cso_save_vertex_elements(ctx->cso); 564 cso_save_vertex_buffers(ctx->cso); 565 566 /* set misc state we care about */ 567 if (writemask) 568 cso_set_blend(ctx->cso, &ctx->blend_write_color); 569 else 570 cso_set_blend(ctx->cso, &ctx->blend_keep_color); 571 572 cso_set_depth_stencil_alpha(ctx->cso, 573 dst_is_depth ? &ctx->depthstencil_write : 574 &ctx->depthstencil_keep); 575 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 576 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 577 cso_set_stream_outputs(ctx->cso, 0, NULL, 0); 578 579 /* sampler */ 580 ctx->sampler.normalized_coords = normalized; 581 ctx->sampler.min_img_filter = filter; 582 ctx->sampler.mag_img_filter = filter; 583 ctx->sampler.min_lod = src_level; 584 ctx->sampler.max_lod = src_level; 585 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 586 cso_single_sampler_done(ctx->cso); 587 588 /* viewport */ 589 ctx->viewport.scale[0] = 0.5f * dst_surface->width; 590 ctx->viewport.scale[1] = 0.5f * dst_surface->height; 591 ctx->viewport.scale[2] = 0.5f; 592 ctx->viewport.scale[3] = 1.0f; 593 ctx->viewport.translate[0] = 0.5f * dst_surface->width; 594 ctx->viewport.translate[1] = 0.5f * dst_surface->height; 595 ctx->viewport.translate[2] = 0.5f; 596 ctx->viewport.translate[3] = 0.0f; 597 cso_set_viewport(ctx->cso, &ctx->viewport); 598 599 /* texture */ 600 cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); 601 602 /* shaders */ 603 if (dst_is_depth) { 604 set_depth_fragment_shader(ctx, sampler_view->texture->target); 605 } else { 606 set_fragment_shader(ctx, writemask, sampler_view->texture->target); 607 } 608 set_vertex_shader(ctx); 609 cso_set_geometry_shader_handle(ctx->cso, NULL); 610 611 /* drawing dest */ 612 memset(&fb, 0, sizeof(fb)); 613 fb.width = dst_surface->width; 614 fb.height = dst_surface->height; 615 if (dst_is_depth) { 616 fb.zsbuf = dst_surface; 617 } else { 618 fb.nr_cbufs = 1; 619 fb.cbufs[0] = dst_surface; 620 } 621 cso_set_framebuffer(ctx->cso, &fb); 622 623 /* draw quad */ 624 offset = setup_vertex_data_tex(ctx, 625 (float) dstX0 / dst_surface->width * 2.0f - 1.0f, 626 (float) dstY0 / dst_surface->height * 2.0f - 1.0f, 627 (float) dstX1 / dst_surface->width * 2.0f - 1.0f, 628 (float) dstY1 / dst_surface->height * 2.0f - 1.0f, 629 s0, t0, 630 s1, t1, 631 z); 632 633 if (ctx->vbuf) { 634 util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, offset, 635 PIPE_PRIM_TRIANGLE_FAN, 636 4, /* verts */ 637 2); /* attribs/vert */ 638 } 639 640 /* restore state we changed */ 641 cso_restore_blend(ctx->cso); 642 cso_restore_depth_stencil_alpha(ctx->cso); 643 cso_restore_rasterizer(ctx->cso); 644 cso_restore_samplers(ctx->cso); 645 cso_restore_fragment_sampler_views(ctx->cso); 646 cso_restore_viewport(ctx->cso); 647 cso_restore_framebuffer(ctx->cso); 648 cso_restore_fragment_shader(ctx->cso); 649 cso_restore_vertex_shader(ctx->cso); 650 cso_restore_geometry_shader(ctx->cso); 651 cso_restore_vertex_elements(ctx->cso); 652 cso_restore_vertex_buffers(ctx->cso); 653 cso_restore_stream_outputs(ctx->cso); 654 655 pipe_sampler_view_reference(&sampler_view, NULL); 656 if (dst_surface != dst) 657 pipe_surface_reference(&dst_surface, NULL); 658} 659 660 661/** 662 * Copy pixel block from src texture to dst surface. 663 * The sampler view's first_level field indicates the source 664 * mipmap level to use. 665 * XXX need some control over blitting Z and/or stencil. 666 */ 667void 668util_blit_pixels_tex(struct blit_state *ctx, 669 struct pipe_sampler_view *src_sampler_view, 670 int srcX0, int srcY0, 671 int srcX1, int srcY1, 672 struct pipe_surface *dst, 673 int dstX0, int dstY0, 674 int dstX1, int dstY1, 675 float z, uint filter) 676{ 677 boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT; 678 struct pipe_framebuffer_state fb; 679 float s0, t0, s1, t1; 680 unsigned offset; 681 struct pipe_resource *tex = src_sampler_view->texture; 682 683 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 684 filter == PIPE_TEX_MIPFILTER_LINEAR); 685 686 assert(tex); 687 assert(tex->width0 != 0); 688 assert(tex->height0 != 0); 689 690 s0 = srcX0; 691 s1 = srcX1; 692 t0 = srcY0; 693 t1 = srcY1; 694 695 if(normalized) 696 { 697 /* normalize according to the mipmap level's size */ 698 int level = src_sampler_view->u.tex.first_level; 699 float w = (float) u_minify(tex->width0, level); 700 float h = (float) u_minify(tex->height0, level); 701 s0 /= w; 702 s1 /= w; 703 t0 /= h; 704 t1 /= h; 705 } 706 707 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, 708 PIPE_TEXTURE_2D, 709 dst->texture->nr_samples, 710 PIPE_BIND_RENDER_TARGET)); 711 712 /* save state (restored below) */ 713 cso_save_blend(ctx->cso); 714 cso_save_depth_stencil_alpha(ctx->cso); 715 cso_save_rasterizer(ctx->cso); 716 cso_save_samplers(ctx->cso); 717 cso_save_fragment_sampler_views(ctx->cso); 718 cso_save_stream_outputs(ctx->cso); 719 cso_save_viewport(ctx->cso); 720 cso_save_framebuffer(ctx->cso); 721 cso_save_fragment_shader(ctx->cso); 722 cso_save_vertex_shader(ctx->cso); 723 cso_save_geometry_shader(ctx->cso); 724 cso_save_vertex_elements(ctx->cso); 725 cso_save_vertex_buffers(ctx->cso); 726 727 /* set misc state we care about */ 728 cso_set_blend(ctx->cso, &ctx->blend_write_color); 729 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil_keep); 730 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 731 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 732 cso_set_stream_outputs(ctx->cso, 0, NULL, 0); 733 734 /* sampler */ 735 ctx->sampler.normalized_coords = normalized; 736 ctx->sampler.min_img_filter = filter; 737 ctx->sampler.mag_img_filter = filter; 738 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 739 cso_single_sampler_done(ctx->cso); 740 741 /* viewport */ 742 ctx->viewport.scale[0] = 0.5f * dst->width; 743 ctx->viewport.scale[1] = 0.5f * dst->height; 744 ctx->viewport.scale[2] = 0.5f; 745 ctx->viewport.scale[3] = 1.0f; 746 ctx->viewport.translate[0] = 0.5f * dst->width; 747 ctx->viewport.translate[1] = 0.5f * dst->height; 748 ctx->viewport.translate[2] = 0.5f; 749 ctx->viewport.translate[3] = 0.0f; 750 cso_set_viewport(ctx->cso, &ctx->viewport); 751 752 /* texture */ 753 cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view); 754 755 /* shaders */ 756 set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW, 757 src_sampler_view->texture->target); 758 set_vertex_shader(ctx); 759 cso_set_geometry_shader_handle(ctx->cso, NULL); 760 761 /* drawing dest */ 762 memset(&fb, 0, sizeof(fb)); 763 fb.width = dst->width; 764 fb.height = dst->height; 765 fb.nr_cbufs = 1; 766 fb.cbufs[0] = dst; 767 cso_set_framebuffer(ctx->cso, &fb); 768 769 /* draw quad */ 770 offset = setup_vertex_data_tex(ctx, 771 (float) dstX0 / dst->width * 2.0f - 1.0f, 772 (float) dstY0 / dst->height * 2.0f - 1.0f, 773 (float) dstX1 / dst->width * 2.0f - 1.0f, 774 (float) dstY1 / dst->height * 2.0f - 1.0f, 775 s0, t0, s1, t1, 776 z); 777 778 util_draw_vertex_buffer(ctx->pipe, ctx->cso, 779 ctx->vbuf, offset, 780 PIPE_PRIM_TRIANGLE_FAN, 781 4, /* verts */ 782 2); /* attribs/vert */ 783 784 /* restore state we changed */ 785 cso_restore_blend(ctx->cso); 786 cso_restore_depth_stencil_alpha(ctx->cso); 787 cso_restore_rasterizer(ctx->cso); 788 cso_restore_samplers(ctx->cso); 789 cso_restore_fragment_sampler_views(ctx->cso); 790 cso_restore_viewport(ctx->cso); 791 cso_restore_framebuffer(ctx->cso); 792 cso_restore_fragment_shader(ctx->cso); 793 cso_restore_vertex_shader(ctx->cso); 794 cso_restore_geometry_shader(ctx->cso); 795 cso_restore_vertex_elements(ctx->cso); 796 cso_restore_vertex_buffers(ctx->cso); 797 cso_restore_stream_outputs(ctx->cso); 798} 799