u_blit.c revision 815b75705f5e3f0f7db025368da37bb14395de9a
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_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 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_resource_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 PIPE_BIND_VERTEX_BUFFER, 190 max_slots * sizeof ctx->vertices); 191 } 192 193 return ctx->vbuf_slot++ * sizeof ctx->vertices; 194} 195 196 197 198 199/** 200 * Setup vertex data for the textured quad we'll draw. 201 * Note: y=0=top 202 */ 203static unsigned 204setup_vertex_data_tex(struct blit_state *ctx, 205 float x0, float y0, float x1, float y1, 206 float s0, float t0, float s1, float t1, 207 float z) 208{ 209 unsigned offset; 210 211 ctx->vertices[0][0][0] = x0; 212 ctx->vertices[0][0][1] = y0; 213 ctx->vertices[0][0][2] = z; 214 ctx->vertices[0][1][0] = s0; /*s*/ 215 ctx->vertices[0][1][1] = t0; /*t*/ 216 217 ctx->vertices[1][0][0] = x1; 218 ctx->vertices[1][0][1] = y0; 219 ctx->vertices[1][0][2] = z; 220 ctx->vertices[1][1][0] = s1; /*s*/ 221 ctx->vertices[1][1][1] = t0; /*t*/ 222 223 ctx->vertices[2][0][0] = x1; 224 ctx->vertices[2][0][1] = y1; 225 ctx->vertices[2][0][2] = z; 226 ctx->vertices[2][1][0] = s1; 227 ctx->vertices[2][1][1] = t1; 228 229 ctx->vertices[3][0][0] = x0; 230 ctx->vertices[3][0][1] = y1; 231 ctx->vertices[3][0][2] = z; 232 ctx->vertices[3][1][0] = s0; 233 ctx->vertices[3][1][1] = t1; 234 235 offset = get_next_slot( ctx ); 236 237 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf, 238 offset, sizeof(ctx->vertices), ctx->vertices); 239 240 return offset; 241} 242 243 244/** 245 * \return TRUE if two regions overlap, FALSE otherwise 246 */ 247static boolean 248regions_overlap(int srcX0, int srcY0, 249 int srcX1, int srcY1, 250 int dstX0, int dstY0, 251 int dstX1, int dstY1) 252{ 253 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1)) 254 return FALSE; /* src completely left of dst */ 255 256 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1)) 257 return FALSE; /* dst completely left of src */ 258 259 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1)) 260 return FALSE; /* src completely above dst */ 261 262 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1)) 263 return FALSE; /* dst completely above src */ 264 265 return TRUE; /* some overlap */ 266} 267 268 269/** 270 * Copy pixel block from src surface to dst surface. 271 * Overlapping regions are acceptable. 272 * Flipping and stretching are supported. 273 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR 274 * \param writemask controls which channels in the dest surface are sourced 275 * from the src surface. Disabled channels are sourced 276 * from (0,0,0,1). 277 * XXX need some control over blitting Z and/or stencil. 278 */ 279void 280util_blit_pixels_writemask(struct blit_state *ctx, 281 struct pipe_resource *src_tex, 282 struct pipe_subresource srcsub, 283 int srcX0, int srcY0, 284 int srcX1, int srcY1, 285 int srcZ0, 286 struct pipe_surface *dst, 287 int dstX0, int dstY0, 288 int dstX1, int dstY1, 289 float z, uint filter, 290 uint writemask) 291{ 292 struct pipe_context *pipe = ctx->pipe; 293 struct pipe_screen *screen = pipe->screen; 294 struct pipe_sampler_view *sampler_view = NULL; 295 struct pipe_sampler_view sv_templ; 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(srcsub.level <= src_tex->last_level); 307 308 /* do the regions overlap? */ 309 overlap = src_tex == dst->texture && 310 dst->face == srcsub.face && 311 dst->level == srcsub.level && 312 dst->zslice == srcZ0 && 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 (dst->format == src_tex->format && 322 srcX0 < srcX1 && 323 dstX0 < dstX1 && 324 srcY0 < srcY1 && 325 dstY0 < dstY1 && 326 (dstX1 - dstX0) == (srcX1 - srcX0) && 327 (dstY1 - dstY0) == (srcY1 - srcY0) && 328 !overlap) { 329 struct pipe_subresource subdst; 330 subdst.face = dst->face; 331 subdst.level = dst->level; 332 pipe->resource_copy_region(pipe, 333 dst->texture, subdst, 334 dstX0, dstY0, dst->zslice,/* dest */ 335 src_tex, srcsub, 336 srcX0, srcY0, srcZ0,/* src */ 337 srcW, srcH); /* size */ 338 return; 339 } 340 341 342 /* Create a temporary texture when src and dest alias or when src 343 * is anything other than a 2d texture. 344 * XXX should just use appropriate shader to access 1d / 3d slice / cube face, 345 * much like the u_blitter code does (should be pretty trivial). 346 * 347 * This can still be improved upon. 348 */ 349 if ((src_tex == dst->texture && 350 dst->face == srcsub.face && 351 dst->level == srcsub.level && 352 dst->zslice == srcZ0) || 353 src_tex->target != PIPE_TEXTURE_2D) 354 { 355 struct pipe_resource texTemp; 356 struct pipe_resource *tex; 357 struct pipe_sampler_view sv_templ; 358 struct pipe_subresource texsub; 359 const int srcLeft = MIN2(srcX0, srcX1); 360 const int srcTop = MIN2(srcY0, srcY1); 361 362 if (srcLeft != srcX0) { 363 /* left-right flip */ 364 int tmp = dstX0; 365 dstX0 = dstX1; 366 dstX1 = tmp; 367 } 368 369 if (srcTop != srcY0) { 370 /* up-down flip */ 371 int tmp = dstY0; 372 dstY0 = dstY1; 373 dstY1 = tmp; 374 } 375 376 /* create temp texture */ 377 memset(&texTemp, 0, sizeof(texTemp)); 378 texTemp.target = PIPE_TEXTURE_2D; 379 texTemp.format = src_tex->format; 380 texTemp.last_level = 0; 381 texTemp.width0 = srcW; 382 texTemp.height0 = srcH; 383 texTemp.depth0 = 1; 384 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 385 386 tex = screen->resource_create(screen, &texTemp); 387 if (!tex) 388 return; 389 390 texsub.face = 0; 391 texsub.level = 0; 392 /* load temp texture */ 393 pipe->resource_copy_region(pipe, 394 tex, texsub, 0, 0, 0, /* dest */ 395 src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */ 396 srcW, srcH); /* size */ 397 398 s0 = 0.0f; 399 s1 = 1.0f; 400 t0 = 0.0f; 401 t1 = 1.0f; 402 403 u_sampler_view_default_template(&sv_templ, tex, tex->format); 404 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); 405 406 if (!sampler_view) { 407 pipe_resource_reference(&tex, NULL); 408 return; 409 } 410 pipe_resource_reference(&tex, NULL); 411 } 412 else { 413 u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format); 414 sv_templ.first_level = sv_templ.last_level = srcsub.level; 415 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); 416 417 if (!sampler_view) { 418 return; 419 } 420 421 s0 = srcX0 / (float)(u_minify(sampler_view->texture->width0, srcsub.level)); 422 s1 = srcX1 / (float)(u_minify(sampler_view->texture->width0, srcsub.level)); 423 t0 = srcY0 / (float)(u_minify(sampler_view->texture->height0, srcsub.level)); 424 t1 = srcY1 / (float)(u_minify(sampler_view->texture->height0, srcsub.level)); 425 } 426 427 428 assert(screen->is_format_supported(screen, sampler_view->format, PIPE_TEXTURE_2D, 429 sampler_view->texture->nr_samples, 430 PIPE_BIND_SAMPLER_VIEW, 0)); 431 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 432 dst->texture->nr_samples, 433 PIPE_BIND_RENDER_TARGET, 0)); 434 435 /* save state (restored below) */ 436 cso_save_blend(ctx->cso); 437 cso_save_depth_stencil_alpha(ctx->cso); 438 cso_save_rasterizer(ctx->cso); 439 cso_save_samplers(ctx->cso); 440 cso_save_fragment_sampler_views(ctx->cso); 441 cso_save_viewport(ctx->cso); 442 cso_save_framebuffer(ctx->cso); 443 cso_save_fragment_shader(ctx->cso); 444 cso_save_vertex_shader(ctx->cso); 445 cso_save_clip(ctx->cso); 446 cso_save_vertex_elements(ctx->cso); 447 448 /* set misc state we care about */ 449 cso_set_blend(ctx->cso, &ctx->blend); 450 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 451 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 452 cso_set_clip(ctx->cso, &ctx->clip); 453 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 454 455 /* sampler */ 456 ctx->sampler.min_img_filter = filter; 457 ctx->sampler.mag_img_filter = filter; 458 /* we've limited this already with the sampler view but you never know... */ 459 ctx->sampler.min_lod = srcsub.level; 460 ctx->sampler.max_lod = srcsub.level; 461 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 462 cso_single_sampler_done(ctx->cso); 463 464 /* viewport */ 465 ctx->viewport.scale[0] = 0.5f * dst->width; 466 ctx->viewport.scale[1] = 0.5f * dst->height; 467 ctx->viewport.scale[2] = 0.5f; 468 ctx->viewport.scale[3] = 1.0f; 469 ctx->viewport.translate[0] = 0.5f * dst->width; 470 ctx->viewport.translate[1] = 0.5f * dst->height; 471 ctx->viewport.translate[2] = 0.5f; 472 ctx->viewport.translate[3] = 0.0f; 473 cso_set_viewport(ctx->cso, &ctx->viewport); 474 475 /* texture */ 476 cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view); 477 478 if (ctx->fs[writemask] == NULL) 479 ctx->fs[writemask] = 480 util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D, 481 writemask); 482 483 /* shaders */ 484 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]); 485 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 486 487 /* drawing dest */ 488 memset(&fb, 0, sizeof(fb)); 489 fb.width = dst->width; 490 fb.height = dst->height; 491 fb.nr_cbufs = 1; 492 fb.cbufs[0] = dst; 493 cso_set_framebuffer(ctx->cso, &fb); 494 495 /* draw quad */ 496 offset = setup_vertex_data_tex(ctx, 497 (float) dstX0 / dst->width * 2.0f - 1.0f, 498 (float) dstY0 / dst->height * 2.0f - 1.0f, 499 (float) dstX1 / dst->width * 2.0f - 1.0f, 500 (float) dstY1 / dst->height * 2.0f - 1.0f, 501 s0, t0, 502 s1, t1, 503 z); 504 505 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset, 506 PIPE_PRIM_TRIANGLE_FAN, 507 4, /* verts */ 508 2); /* attribs/vert */ 509 510 /* restore state we changed */ 511 cso_restore_blend(ctx->cso); 512 cso_restore_depth_stencil_alpha(ctx->cso); 513 cso_restore_rasterizer(ctx->cso); 514 cso_restore_samplers(ctx->cso); 515 cso_restore_fragment_sampler_views(ctx->cso); 516 cso_restore_viewport(ctx->cso); 517 cso_restore_framebuffer(ctx->cso); 518 cso_restore_fragment_shader(ctx->cso); 519 cso_restore_vertex_shader(ctx->cso); 520 cso_restore_clip(ctx->cso); 521 cso_restore_vertex_elements(ctx->cso); 522 523 pipe_sampler_view_reference(&sampler_view, NULL); 524} 525 526 527void 528util_blit_pixels(struct blit_state *ctx, 529 struct pipe_resource *src_tex, 530 struct pipe_subresource srcsub, 531 int srcX0, int srcY0, 532 int srcX1, int srcY1, 533 int srcZ, 534 struct pipe_surface *dst, 535 int dstX0, int dstY0, 536 int dstX1, int dstY1, 537 float z, uint filter ) 538{ 539 util_blit_pixels_writemask( ctx, src_tex, 540 srcsub, 541 srcX0, srcY0, 542 srcX1, srcY1, 543 srcZ, 544 dst, 545 dstX0, dstY0, 546 dstX1, dstY1, 547 z, filter, 548 TGSI_WRITEMASK_XYZW ); 549} 550 551 552/* Release vertex buffer at end of frame to avoid synchronous 553 * rendering. 554 */ 555void util_blit_flush( struct blit_state *ctx ) 556{ 557 pipe_resource_reference(&ctx->vbuf, NULL); 558 ctx->vbuf_slot = 0; 559} 560 561 562 563/** 564 * Copy pixel block from src texture to dst surface. 565 * 566 * XXX Should support selection of level. 567 * XXX need some control over blitting Z and/or stencil. 568 */ 569void 570util_blit_pixels_tex(struct blit_state *ctx, 571 struct pipe_sampler_view *src_sampler_view, 572 int srcX0, int srcY0, 573 int srcX1, int srcY1, 574 struct pipe_surface *dst, 575 int dstX0, int dstY0, 576 int dstX1, int dstY1, 577 float z, uint filter) 578{ 579 struct pipe_framebuffer_state fb; 580 float s0, t0, s1, t1; 581 unsigned offset; 582 struct pipe_resource *tex = src_sampler_view->texture; 583 584 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 585 filter == PIPE_TEX_MIPFILTER_LINEAR); 586 587 assert(tex); 588 assert(tex->width0 != 0); 589 assert(tex->height0 != 0); 590 591 s0 = srcX0 / (float)tex->width0; 592 s1 = srcX1 / (float)tex->width0; 593 t0 = srcY0 / (float)tex->height0; 594 t1 = srcY1 / (float)tex->height0; 595 596 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format, 597 PIPE_TEXTURE_2D, 598 dst->texture->nr_samples, 599 PIPE_BIND_RENDER_TARGET, 600 0)); 601 602 /* save state (restored below) */ 603 cso_save_blend(ctx->cso); 604 cso_save_depth_stencil_alpha(ctx->cso); 605 cso_save_rasterizer(ctx->cso); 606 cso_save_samplers(ctx->cso); 607 cso_save_fragment_sampler_views(ctx->cso); 608 cso_save_framebuffer(ctx->cso); 609 cso_save_fragment_shader(ctx->cso); 610 cso_save_vertex_shader(ctx->cso); 611 cso_save_clip(ctx->cso); 612 cso_save_vertex_elements(ctx->cso); 613 614 /* set misc state we care about */ 615 cso_set_blend(ctx->cso, &ctx->blend); 616 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); 617 cso_set_rasterizer(ctx->cso, &ctx->rasterizer); 618 cso_set_clip(ctx->cso, &ctx->clip); 619 cso_set_vertex_elements(ctx->cso, 2, ctx->velem); 620 621 /* sampler */ 622 ctx->sampler.min_img_filter = filter; 623 ctx->sampler.mag_img_filter = filter; 624 cso_single_sampler(ctx->cso, 0, &ctx->sampler); 625 cso_single_sampler_done(ctx->cso); 626 627 /* viewport */ 628 ctx->viewport.scale[0] = 0.5f * dst->width; 629 ctx->viewport.scale[1] = 0.5f * dst->height; 630 ctx->viewport.scale[2] = 0.5f; 631 ctx->viewport.scale[3] = 1.0f; 632 ctx->viewport.translate[0] = 0.5f * dst->width; 633 ctx->viewport.translate[1] = 0.5f * dst->height; 634 ctx->viewport.translate[2] = 0.5f; 635 ctx->viewport.translate[3] = 0.0f; 636 cso_set_viewport(ctx->cso, &ctx->viewport); 637 638 /* texture */ 639 cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view); 640 641 /* shaders */ 642 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]); 643 cso_set_vertex_shader_handle(ctx->cso, ctx->vs); 644 645 /* drawing dest */ 646 memset(&fb, 0, sizeof(fb)); 647 fb.width = dst->width; 648 fb.height = dst->height; 649 fb.nr_cbufs = 1; 650 fb.cbufs[0] = dst; 651 cso_set_framebuffer(ctx->cso, &fb); 652 653 /* draw quad */ 654 offset = setup_vertex_data_tex(ctx, 655 (float) dstX0 / dst->width * 2.0f - 1.0f, 656 (float) dstY0 / dst->height * 2.0f - 1.0f, 657 (float) dstX1 / dst->width * 2.0f - 1.0f, 658 (float) dstY1 / dst->height * 2.0f - 1.0f, 659 s0, t0, s1, t1, 660 z); 661 662 util_draw_vertex_buffer(ctx->pipe, 663 ctx->vbuf, offset, 664 PIPE_PRIM_TRIANGLE_FAN, 665 4, /* verts */ 666 2); /* attribs/vert */ 667 668 /* restore state we changed */ 669 cso_restore_blend(ctx->cso); 670 cso_restore_depth_stencil_alpha(ctx->cso); 671 cso_restore_rasterizer(ctx->cso); 672 cso_restore_samplers(ctx->cso); 673 cso_restore_fragment_sampler_views(ctx->cso); 674 cso_restore_framebuffer(ctx->cso); 675 cso_restore_fragment_shader(ctx->cso); 676 cso_restore_vertex_shader(ctx->cso); 677 cso_restore_clip(ctx->cso); 678 cso_restore_vertex_elements(ctx->cso); 679} 680