u_blit.c revision df65fc8100f267b3167012d4f8502cf9eed526df
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#include "util/u_surface.h" 51#include "util/u_rect.h" 52 53#include "cso_cache/cso_context.h" 54 55 56struct blit_state 57{ 58 struct pipe_context *pipe; 59 struct cso_context *cso; 60 61 struct pipe_blend_state blend; 62 struct pipe_depth_stencil_alpha_state depthstencil; 63 struct pipe_rasterizer_state rasterizer; 64 struct pipe_sampler_state sampler; 65 struct pipe_viewport_state viewport; 66 struct pipe_clip_state clip; 67 struct pipe_vertex_element velem[2]; 68 69 void *vs; 70 void *fs[TGSI_WRITEMASK_XYZW + 1]; 71 72 struct pipe_buffer *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 memset(&ctx->blend, 0, sizeof(ctx->blend)); 98 ctx->blend.rt[0].colormask = PIPE_MASK_RGBA; 99 100 /* no-op depth/stencil/alpha */ 101 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil)); 102 103 /* rasterizer */ 104 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer)); 105 ctx->rasterizer.front_winding = PIPE_WINDING_CW; 106 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; 107 ctx->rasterizer.gl_rasterization_rules = 1; 108 109 /* samplers */ 110 memset(&ctx->sampler, 0, sizeof(ctx->sampler)); 111 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 112 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 113 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 114 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 115 ctx->sampler.min_img_filter = 0; /* set later */ 116 ctx->sampler.mag_img_filter = 0; /* set later */ 117 ctx->sampler.normalized_coords = 1; 118 119 /* vertex elements state */ 120 memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2); 121 for (i = 0; i < 2; i++) { 122 ctx->velem[i].src_offset = i * 4 * sizeof(float); 123 ctx->velem[i].instance_divisor = 0; 124 ctx->velem[i].vertex_buffer_index = 0; 125 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 126 } 127 128 /* vertex shader - still required to provide the linkage between 129 * fragment shader input semantics and vertex_element/buffers. 130 */ 131 { 132 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, 133 TGSI_SEMANTIC_GENERIC }; 134 const uint semantic_indexes[] = { 0, 0 }; 135 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, 136 semantic_indexes); 137 } 138 139 /* fragment shader */ 140 ctx->fs[TGSI_WRITEMASK_XYZW] = 141 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D); 142 ctx->vbuf = NULL; 143 144 /* init vertex data that doesn't change */ 145 for (i = 0; i < 4; i++) { 146 ctx->vertices[i][0][3] = 1.0f; /* w */ 147 ctx->vertices[i][1][2] = 0.0f; /* r */ 148 ctx->vertices[i][1][3] = 1.0f; /* q */ 149 } 150 151 return ctx; 152} 153 154 155/** 156 * Destroy a blit context 157 */ 158void 159util_destroy_blit(struct blit_state *ctx) 160{ 161 struct pipe_context *pipe = ctx->pipe; 162 unsigned i; 163 164 pipe->delete_vs_state(pipe, ctx->vs); 165 166 for (i = 0; i < Elements(ctx->fs); i++) 167 if (ctx->fs[i]) 168 pipe->delete_fs_state(pipe, ctx->fs[i]); 169 170 pipe_buffer_reference(&ctx->vbuf, NULL); 171 172 FREE(ctx); 173} 174 175 176/** 177 * Get offset of next free slot in vertex buffer for quad vertices. 178 */ 179static unsigned 180get_next_slot( struct blit_state *ctx ) 181{ 182 const unsigned max_slots = 4096 / sizeof ctx->vertices; 183 184 if (ctx->vbuf_slot >= max_slots) 185 util_blit_flush( ctx ); 186 187 if (!ctx->vbuf) { 188 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, 189 32, 190 PIPE_BUFFER_USAGE_VERTEX, 191 max_slots * sizeof ctx->vertices); 192 } 193 194 return ctx->vbuf_slot++ * sizeof ctx->vertices; 195} 196 197 198 199 200 201/** 202 * Setup vertex data for the textured quad we'll draw. 203 * Note: y=0=top 204 */ 205static unsigned 206setup_vertex_data_tex(struct blit_state *ctx, 207 float x0, float y0, float x1, float y1, 208 float s0, float t0, float s1, float t1, 209 float z) 210{ 211 unsigned offset; 212 213 ctx->vertices[0][0][0] = x0; 214 ctx->vertices[0][0][1] = y0; 215 ctx->vertices[0][0][2] = z; 216 ctx->vertices[0][1][0] = s0; /*s*/ 217 ctx->vertices[0][1][1] = t0; /*t*/ 218 219 ctx->vertices[1][0][0] = x1; 220 ctx->vertices[1][0][1] = y0; 221 ctx->vertices[1][0][2] = z; 222 ctx->vertices[1][1][0] = s1; /*s*/ 223 ctx->vertices[1][1][1] = t0; /*t*/ 224 225 ctx->vertices[2][0][0] = x1; 226 ctx->vertices[2][0][1] = y1; 227 ctx->vertices[2][0][2] = z; 228 ctx->vertices[2][1][0] = s1; 229 ctx->vertices[2][1][1] = t1; 230 231 ctx->vertices[3][0][0] = x0; 232 ctx->vertices[3][0][1] = y1; 233 ctx->vertices[3][0][2] = z; 234 ctx->vertices[3][1][0] = s0; 235 ctx->vertices[3][1][1] = t1; 236 237 offset = get_next_slot( ctx ); 238 239 pipe_buffer_write_nooverlap(ctx->pipe->screen, ctx->vbuf, 240 offset, sizeof(ctx->vertices), ctx->vertices); 241 242 return offset; 243} 244 245 246/** 247 * \return TRUE if two regions overlap, FALSE otherwise 248 */ 249static boolean 250regions_overlap(int srcX0, int srcY0, 251 int srcX1, int srcY1, 252 int dstX0, int dstY0, 253 int dstX1, int dstY1) 254{ 255 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) 256 return FALSE; /* src completely left of dst */ 257 258 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) 259 return FALSE; /* dst completely left of src */ 260 261 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) 262 return FALSE; /* src completely above dst */ 263 264 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) 265 return FALSE; /* dst completely above src */ 266 267 return TRUE; /* some overlap */ 268} 269 270 271/** 272 * Copy pixel block from src surface to dst surface. 273 * Overlapping regions are acceptable. 274 * Flipping and stretching are supported. 275 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR 276 * \param writemask controls which channels in the dest surface are sourced 277 * from the src surface. Disabled channels are sourced 278 * from (0,0,0,1). 279 * XXX need some control over blitting Z and/or stencil. 280 */ 281void 282util_blit_pixels_writemask(struct blit_state *ctx, 283 struct pipe_surface *src, 284 struct pipe_sampler_view *src_sampler_view, 285 int srcX0, int srcY0, 286 int srcX1, int srcY1, 287 struct pipe_surface *dst, 288 int dstX0, int dstY0, 289 int dstX1, int dstY1, 290 float z, uint filter, 291 uint writemask) 292{ 293 struct pipe_context *pipe = ctx->pipe; 294 struct pipe_screen *screen = pipe->screen; 295 struct pipe_sampler_view *sampler_view = NULL; 296 struct pipe_framebuffer_state fb; 297 const int srcW = abs(srcX1 - srcX0); 298 const int srcH = abs(srcY1 - srcY0); 299 unsigned offset; 300 boolean overlap; 301 float s0, t0, s1, t1; 302 303 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 304 filter == PIPE_TEX_MIPFILTER_LINEAR); 305 306 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 307 PIPE_TEXTURE_USAGE_SAMPLER, 0)); 308 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 309 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 310 311 /* do the regions overlap? */ 312 overlap = util_same_surface(src, dst) && 313 regions_overlap(srcX0, srcY0, srcX1, srcY1, 314 dstX0, dstY0, dstX1, dstY1); 315 316 /* 317 * Check for simple case: no format conversion, no flipping, no stretching, 318 * no overlapping. 319 * Filter mode should not matter since there's no stretching. 320 */ 321 if (pipe->surface_copy && 322 dst->format == src->format && 323 srcX0 < srcX1 && 324 dstX0 < dstX1 && 325 srcY0 < srcY1 && 326 dstY0 < dstY1 && 327 (dstX1 - dstX0) == (srcX1 - srcX0) && 328 (dstY1 - dstY0) == (srcY1 - srcY0) && 329 !overlap) { 330 pipe->surface_copy(pipe, 331 dst, dstX0, dstY0, /* dest */ 332 src, srcX0, srcY0, /* src */ 333 srcW, srcH); /* size */ 334 return; 335 } 336 337 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 338 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 339 340 /* Create a temporary texture when src and dest alias or when src 341 * is anything other than a single-level 2d texture. 342 * 343 * This can still be improved upon. 344 */ 345 if (util_same_surface(src, dst) || 346 src->texture->target != PIPE_TEXTURE_2D || 347 src->texture->last_level != 0) 348 { 349 struct pipe_texture texTemp; 350 struct pipe_texture *tex; 351 struct pipe_sampler_view sv_templ; 352 struct pipe_surface *texSurf; 353 const int srcLeft = MIN2(srcX0, srcX1); 354 const int srcTop = MIN2(srcY0, srcY1); 355 356 if (srcLeft != srcX0) { 357 /* left-right flip */ 358 int tmp = dstX0; 359 dstX0 = dstX1; 360 dstX1 = tmp; 361 } 362 363 if (srcTop != srcY0) { 364 /* up-down flip */ 365 int tmp = dstY0; 366 dstY0 = dstY1; 367 dstY1 = tmp; 368 } 369 370 /* create temp texture */ 371 memset(&texTemp, 0, sizeof(texTemp)); 372 texTemp.target = PIPE_TEXTURE_2D; 373 texTemp.format = src->format; 374 texTemp.last_level = 0; 375 texTemp.width0 = srcW; 376 texTemp.height0 = srcH; 377 texTemp.depth0 = 1; 378 379 tex = screen->texture_create(screen, &texTemp); 380 if (!tex) 381 return; 382 383 u_sampler_view_default_template(&sv_templ, tex, tex->format); 384 385 sampler_view = ctx->pipe->create_sampler_view(ctx->pipe, tex, &sv_templ); 386 if (!sampler_view) { 387 pipe_texture_reference(&tex, NULL); 388 return; 389 } 390 391 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, 392 PIPE_BUFFER_USAGE_GPU_WRITE); 393 394 /* load temp texture */ 395 if (pipe->surface_copy) { 396 pipe->surface_copy(pipe, 397 texSurf, 0, 0, /* dest */ 398 src, srcLeft, srcTop, /* src */ 399 srcW, srcH); /* size */ 400 } else { 401 util_surface_copy(pipe, FALSE, 402 texSurf, 0, 0, /* dest */ 403 src, srcLeft, srcTop, /* src */ 404 srcW, srcH); /* size */ 405 } 406 407 /* free the surface, update the texture if necessary. 408 */ 409 pipe_surface_reference(&texSurf, NULL); 410 s0 = 0.0f; 411 s1 = 1.0f; 412 t0 = 0.0f; 413 t1 = 1.0f; 414 415 pipe_texture_reference(&tex, NULL); 416 } 417 else { 418 pipe_sampler_view_reference(&sampler_view, src_sampler_view); 419 s0 = srcX0 / (float)src->texture->width0; 420 s1 = srcX1 / (float)src->texture->width0; 421 t0 = srcY0 / (float)src->texture->height0; 422 t1 = srcY1 / (float)src->texture->height0; 423 } 424 425 426 427 /* save state (restored below) */ 428 cso_save_blend(ctx->cso); 429 cso_save_depth_stencil_alpha(ctx->cso); 430 cso_save_rasterizer(ctx->cso); 431 cso_save_samplers(ctx->cso); 432 cso_save_fragment_sampler_views(ctx->cso); 433 cso_save_viewport(ctx->cso); 434 cso_save_framebuffer(ctx->cso); 435 cso_save_fragment_shader(ctx->cso); 436 cso_save_vertex_shader(ctx->cso); 437 cso_save_clip(ctx->cso); 438 cso_save_vertex_elements(ctx->cso); 439 440 /* set misc state we care about */ 441 cso_set_blend(ctx->cso, &ctx->blend); 442 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 443 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 444 cso_set_clip(ctx->cso, &ctx->clip); 445 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 446 447 /* sampler */ 448 ctx->sampler.min_img_filter = filter; 449 ctx->sampler.mag_img_filter = filter; 450 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 451 cso_single_sampler_done(ctx->cso); 452 453 /* viewport */ 454 ctx->viewport.scale[0] = 0.5f * dst->width; 455 ctx->viewport.scale[1] = 0.5f * dst->height; 456 ctx->viewport.scale[2] = 0.5f; 457 ctx->viewport.scale[3] = 1.0f; 458 ctx->viewport.translate[0] = 0.5f * dst->width; 459 ctx->viewport.translate[1] = 0.5f * dst->height; 460 ctx->viewport.translate[2] = 0.5f; 461 ctx->viewport.translate[3] = 0.0f; 462 cso_set_viewport(ctx->cso, &ctx->viewport); 463 464 /* texture */ 465 cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); 466 467 if (ctx->fs[writemask] == NULL) 468 ctx->fs[writemask] = 469 util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D, 470 writemask); 471 472 /* shaders */ 473 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]); 474 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 475 476 /* drawing dest */ 477 memset(&fb, 0, sizeof(fb)); 478 fb.width = dst->width; 479 fb.height = dst->height; 480 fb.nr_cbufs = 1; 481 fb.cbufs[0] = dst; 482 cso_set_framebuffer(ctx->cso, &fb); 483 484 /* draw quad */ 485 offset = setup_vertex_data_tex(ctx, 486 (float) dstX0 / dst->width * 2.0f - 1.0f, 487 (float) dstY0 / dst->height * 2.0f - 1.0f, 488 (float) dstX1 / dst->width * 2.0f - 1.0f, 489 (float) dstY1 / dst->height * 2.0f - 1.0f, 490 s0, t0, 491 s1, t1, 492 z); 493 494 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset, 495 PIPE_PRIM_TRIANGLE_FAN, 496 4, /* verts */ 497 2); /* attribs/vert */ 498 499 /* restore state we changed */ 500 cso_restore_blend(ctx->cso); 501 cso_restore_depth_stencil_alpha(ctx->cso); 502 cso_restore_rasterizer(ctx->cso); 503 cso_restore_samplers(ctx->cso); 504 cso_restore_fragment_sampler_views(ctx->cso); 505 cso_restore_viewport(ctx->cso); 506 cso_restore_framebuffer(ctx->cso); 507 cso_restore_fragment_shader(ctx->cso); 508 cso_restore_vertex_shader(ctx->cso); 509 cso_restore_clip(ctx->cso); 510 cso_restore_vertex_elements(ctx->cso); 511 512 pipe_sampler_view_reference(&sampler_view, NULL); 513} 514 515 516void 517util_blit_pixels(struct blit_state *ctx, 518 struct pipe_surface *src, 519 struct pipe_sampler_view *src_sampler_view, 520 int srcX0, int srcY0, 521 int srcX1, int srcY1, 522 struct pipe_surface *dst, 523 int dstX0, int dstY0, 524 int dstX1, int dstY1, 525 float z, uint filter ) 526{ 527 util_blit_pixels_writemask( ctx, src, src_sampler_view, 528 srcX0, srcY0, 529 srcX1, srcY1, 530 dst, 531 dstX0, dstY0, 532 dstX1, dstY1, 533 z, filter, 534 TGSI_WRITEMASK_XYZW ); 535} 536 537 538/* Release vertex buffer at end of frame to avoid synchronous 539 * rendering. 540 */ 541void util_blit_flush( struct blit_state *ctx ) 542{ 543 pipe_buffer_reference(&ctx->vbuf, NULL); 544 ctx->vbuf_slot = 0; 545} 546 547 548 549/** 550 * Copy pixel block from src texture to dst surface. 551 * Overlapping regions are acceptable. 552 * 553 * XXX Should support selection of level. 554 * XXX need some control over blitting Z and/or stencil. 555 */ 556void 557util_blit_pixels_tex(struct blit_state *ctx, 558 struct pipe_texture *tex, 559 int srcX0, int srcY0, 560 int srcX1, int srcY1, 561 struct pipe_surface *dst, 562 int dstX0, int dstY0, 563 int dstX1, int dstY1, 564 float z, uint filter) 565{ 566 struct pipe_framebuffer_state fb; 567 float s0, t0, s1, t1; 568 unsigned offset; 569 570 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 571 filter == PIPE_TEX_MIPFILTER_LINEAR); 572 573 assert(tex->width0 != 0); 574 assert(tex->height0 != 0); 575 576 s0 = srcX0 / (float)tex->width0; 577 s1 = srcX1 / (float)tex->width0; 578 t0 = srcY0 / (float)tex->height0; 579 t1 = srcY1 / (float)tex->height0; 580 581 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, 582 PIPE_TEXTURE_2D, 583 PIPE_TEXTURE_USAGE_RENDER_TARGET, 584 0)); 585 586 /* save state (restored below) */ 587 cso_save_blend(ctx->cso); 588 cso_save_depth_stencil_alpha(ctx->cso); 589 cso_save_rasterizer(ctx->cso); 590 cso_save_samplers(ctx->cso); 591 cso_save_sampler_textures(ctx->cso); 592 cso_save_framebuffer(ctx->cso); 593 cso_save_fragment_shader(ctx->cso); 594 cso_save_vertex_shader(ctx->cso); 595 cso_save_clip(ctx->cso); 596 cso_save_vertex_elements(ctx->cso); 597 598 /* set misc state we care about */ 599 cso_set_blend(ctx->cso, &ctx->blend); 600 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 601 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 602 cso_set_clip(ctx->cso, &ctx->clip); 603 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 604 605 /* sampler */ 606 ctx->sampler.min_img_filter = filter; 607 ctx->sampler.mag_img_filter = filter; 608 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 609 cso_single_sampler_done(ctx->cso); 610 611 /* viewport */ 612 ctx->viewport.scale[0] = 0.5f * dst->width; 613 ctx->viewport.scale[1] = 0.5f * dst->height; 614 ctx->viewport.scale[2] = 0.5f; 615 ctx->viewport.scale[3] = 1.0f; 616 ctx->viewport.translate[0] = 0.5f * dst->width; 617 ctx->viewport.translate[1] = 0.5f * dst->height; 618 ctx->viewport.translate[2] = 0.5f; 619 ctx->viewport.translate[3] = 0.0f; 620 cso_set_viewport(ctx->cso, &ctx->viewport); 621 622 /* texture */ 623 cso_set_sampler_textures(ctx->cso, 1, &tex); 624 625 /* shaders */ 626 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]); 627 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 628 629 /* drawing dest */ 630 memset(&fb, 0, sizeof(fb)); 631 fb.width = dst->width; 632 fb.height = dst->height; 633 fb.nr_cbufs = 1; 634 fb.cbufs[0] = dst; 635 cso_set_framebuffer(ctx->cso, &fb); 636 637 /* draw quad */ 638 offset = setup_vertex_data_tex(ctx, 639 (float) dstX0 / dst->width * 2.0f - 1.0f, 640 (float) dstY0 / dst->height * 2.0f - 1.0f, 641 (float) dstX1 / dst->width * 2.0f - 1.0f, 642 (float) dstY1 / dst->height * 2.0f - 1.0f, 643 s0, t0, s1, t1, 644 z); 645 646 util_draw_vertex_buffer(ctx->pipe, 647 ctx->vbuf, offset, 648 PIPE_PRIM_TRIANGLE_FAN, 649 4, /* verts */ 650 2); /* attribs/vert */ 651 652 /* restore state we changed */ 653 cso_restore_blend(ctx->cso); 654 cso_restore_depth_stencil_alpha(ctx->cso); 655 cso_restore_rasterizer(ctx->cso); 656 cso_restore_samplers(ctx->cso); 657 cso_restore_sampler_textures(ctx->cso); 658 cso_restore_framebuffer(ctx->cso); 659 cso_restore_fragment_shader(ctx->cso); 660 cso_restore_vertex_shader(ctx->cso); 661 cso_restore_clip(ctx->cso); 662 cso_restore_vertex_elements(ctx->cso); 663} 664