renderer.c revision e31a04ea3bc957b2a43b910b1f51807b12da18a6
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * Copyright 2010 LunarG, Inc. 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 VMWARE 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#include "renderer.h" 29 30#include "vg_context.h" 31 32#include "pipe/p_context.h" 33#include "pipe/p_state.h" 34#include "util/u_inlines.h" 35#include "pipe/p_screen.h" 36#include "pipe/p_shader_tokens.h" 37 38#include "util/u_draw_quad.h" 39#include "util/u_simple_shaders.h" 40#include "util/u_memory.h" 41#include "util/u_sampler.h" 42 43#include "cso_cache/cso_context.h" 44#include "tgsi/tgsi_ureg.h" 45 46typedef enum { 47 RENDERER_STATE_INIT, 48 RENDERER_STATE_COPY, 49 RENDERER_STATE_DRAWTEX, 50 NUM_RENDERER_STATES 51} RendererState; 52 53typedef enum { 54 RENDERER_VS_PLAIN, 55 RENDERER_VS_COLOR, 56 RENDERER_VS_TEXTURE, 57 NUM_RENDERER_VS 58} RendererVs; 59 60typedef enum { 61 RENDERER_FS_COLOR, 62 RENDERER_FS_TEXTURE, 63 NUM_RENDERER_FS 64} RendererFs; 65 66struct renderer { 67 struct pipe_context *pipe; 68 struct vg_context *owner; 69 70 struct cso_context *cso; 71 72 void *fs; 73 74 VGfloat vertices[4][2][4]; 75 76 void *cached_vs[NUM_RENDERER_VS]; 77 void *cached_fs[NUM_RENDERER_FS]; 78 79 RendererState state; 80 81 /* state data */ 82 union { 83 struct { 84 VGint tex_width; 85 VGint tex_height; 86 } copy; 87 88 struct { 89 VGint tex_width; 90 VGint tex_height; 91 } drawtex; 92 } u; 93}; 94 95/** 96 * Return VG_TRUE if the renderer can use the resource as the asked bindings. 97 */ 98static VGboolean renderer_can_support(struct renderer *renderer, 99 struct pipe_resource *res, 100 unsigned bindings) 101{ 102 struct pipe_screen *screen = renderer->pipe->screen; 103 104 return screen->is_format_supported(screen, 105 res->format, res->target, 0, bindings, 0); 106} 107 108/** 109 * Create a simple vertex shader that passes through position and the given 110 * attribute. 111 */ 112static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name) 113{ 114 struct ureg_program *ureg; 115 struct ureg_src src[2], constants[2]; 116 struct ureg_dst dst[2], tmp; 117 int i; 118 119 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 120 if (!ureg) 121 return NULL; 122 123 /* position in surface coordinates */ 124 src[0] = ureg_DECL_vs_input(ureg, 0); 125 dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 126 tmp = ureg_DECL_temporary(ureg); 127 for (i = 0; i < 2; i++) 128 constants[i] = ureg_DECL_constant(ureg, i); 129 130 /* transform to clipped coordinates */ 131 ureg_MUL(ureg, tmp, src[0], constants[0]); 132 ureg_ADD(ureg, tmp, ureg_src(tmp), constants[1]); 133 ureg_MOV(ureg, dst[0], ureg_src(tmp)); 134 135 if (semantic_name >= 0) { 136 src[1] = ureg_DECL_vs_input(ureg, 1); 137 dst[1] = ureg_DECL_output(ureg, semantic_name, 0); 138 ureg_MOV(ureg, dst[1], src[1]); 139 } 140 141 ureg_END(ureg); 142 143 return ureg_create_shader_and_destroy(ureg, pipe); 144} 145 146/** 147 * Set renderer vertex shader. 148 * 149 * This function modifies vertex_shader state. 150 */ 151static void renderer_set_vs(struct renderer *r, RendererVs id) 152{ 153 /* create as needed */ 154 if (!r->cached_vs[id]) { 155 int semantic_name = -1; 156 157 switch (id) { 158 case RENDERER_VS_PLAIN: 159 break; 160 case RENDERER_VS_COLOR: 161 semantic_name = TGSI_SEMANTIC_COLOR; 162 break; 163 case RENDERER_VS_TEXTURE: 164 semantic_name = TGSI_SEMANTIC_GENERIC; 165 break; 166 default: 167 assert(!"Unknown renderer vs id"); 168 break; 169 } 170 171 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name); 172 } 173 174 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]); 175} 176 177/** 178 * Set renderer fragment shader. 179 * 180 * This function modifies fragment_shader state. 181 */ 182static void renderer_set_fs(struct renderer *r, RendererFs id) 183{ 184 /* create as needed */ 185 if (!r->cached_fs[id]) { 186 void *fs = NULL; 187 188 switch (id) { 189 case RENDERER_FS_COLOR: 190 fs = util_make_fragment_passthrough_shader(r->pipe); 191 break; 192 case RENDERER_FS_TEXTURE: 193 fs = util_make_fragment_tex_shader(r->pipe, 194 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR); 195 break; 196 default: 197 assert(!"Unknown renderer fs id"); 198 break; 199 } 200 201 r->cached_fs[id] = fs; 202 } 203 204 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]); 205} 206 207/** 208 * Set renderer target. 209 * 210 * This function modifies framebuffer and viewport states. 211 */ 212static void renderer_set_target(struct renderer *r, 213 struct pipe_surface *cbuf, 214 struct pipe_surface *zsbuf, 215 VGboolean y0_top) 216{ 217 struct pipe_framebuffer_state fb; 218 219 memset(&fb, 0, sizeof(fb)); 220 fb.width = cbuf->width; 221 fb.height = cbuf->height; 222 fb.cbufs[0] = cbuf; 223 fb.nr_cbufs = 1; 224 fb.zsbuf = zsbuf; 225 cso_set_framebuffer(r->cso, &fb); 226 227 vg_set_viewport(r->owner, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM); 228} 229 230/** 231 * Set renderer blend state. Blending is disabled. 232 * 233 * This function modifies blend state. 234 */ 235static void renderer_set_blend(struct renderer *r, 236 VGbitfield channel_mask) 237{ 238 struct pipe_blend_state blend; 239 240 memset(&blend, 0, sizeof(blend)); 241 242 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 243 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 244 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 245 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 246 247 if (channel_mask & VG_RED) 248 blend.rt[0].colormask |= PIPE_MASK_R; 249 if (channel_mask & VG_GREEN) 250 blend.rt[0].colormask |= PIPE_MASK_G; 251 if (channel_mask & VG_BLUE) 252 blend.rt[0].colormask |= PIPE_MASK_B; 253 if (channel_mask & VG_ALPHA) 254 blend.rt[0].colormask |= PIPE_MASK_A; 255 256 cso_set_blend(r->cso, &blend); 257} 258 259/** 260 * Set renderer sampler and view states. 261 * 262 * This function modifies samplers and fragment_sampler_views states. 263 */ 264static void renderer_set_samplers(struct renderer *r, 265 uint num_views, 266 struct pipe_sampler_view **views) 267{ 268 struct pipe_sampler_state sampler; 269 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST; 270 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 271 uint i; 272 273 memset(&sampler, 0, sizeof(sampler)); 274 275 sampler.min_img_filter = tex_filter; 276 sampler.mag_img_filter = tex_filter; 277 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 278 279 sampler.wrap_s = tex_wrap; 280 sampler.wrap_t = tex_wrap; 281 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 282 283 sampler.normalized_coords = 1; 284 285 /* set samplers */ 286 for (i = 0; i < num_views; i++) 287 cso_single_sampler(r->cso, i, &sampler); 288 cso_single_sampler_done(r->cso); 289 290 /* set views */ 291 cso_set_fragment_sampler_views(r->cso, num_views, views); 292} 293 294/** 295 * Setup renderer quad position. 296 */ 297static void renderer_quad_pos(struct renderer *r, 298 VGfloat x0, VGfloat y0, 299 VGfloat x1, VGfloat y1, 300 VGboolean scissor) 301{ 302 VGfloat z; 303 304 /* the depth test is used for scissoring */ 305 z = (scissor) ? 0.0f : 1.0f; 306 307 /* positions */ 308 r->vertices[0][0][0] = x0; 309 r->vertices[0][0][1] = y0; 310 r->vertices[0][0][2] = z; 311 312 r->vertices[1][0][0] = x1; 313 r->vertices[1][0][1] = y0; 314 r->vertices[1][0][2] = z; 315 316 r->vertices[2][0][0] = x1; 317 r->vertices[2][0][1] = y1; 318 r->vertices[2][0][2] = z; 319 320 r->vertices[3][0][0] = x0; 321 r->vertices[3][0][1] = y1; 322 r->vertices[3][0][2] = z; 323} 324 325/** 326 * Setup renderer quad texture coordinates. 327 */ 328static void renderer_quad_texcoord(struct renderer *r, 329 VGfloat x0, VGfloat y0, 330 VGfloat x1, VGfloat y1, 331 VGint tex_width, VGint tex_height) 332{ 333 VGfloat s0, t0, s1, t1, r0, q0; 334 VGint i; 335 336 s0 = x0 / tex_width; 337 s1 = x1 / tex_width; 338 t0 = y0 / tex_height; 339 t1 = y1 / tex_height; 340 r0 = 0.0f; 341 q0 = 1.0f; 342 343 /* texcoords */ 344 r->vertices[0][1][0] = s0; 345 r->vertices[0][1][1] = t0; 346 347 r->vertices[1][1][0] = s1; 348 r->vertices[1][1][1] = t0; 349 350 r->vertices[2][1][0] = s1; 351 r->vertices[2][1][1] = t1; 352 353 r->vertices[3][1][0] = s0; 354 r->vertices[3][1][1] = t1; 355 356 for (i = 0; i < 4; i++) { 357 r->vertices[i][1][2] = r0; 358 r->vertices[i][1][3] = q0; 359 } 360} 361 362/** 363 * Draw renderer quad. 364 */ 365static void renderer_quad_draw(struct renderer *r) 366{ 367 struct pipe_resource *buf; 368 369 buf = pipe_user_buffer_create(r->pipe->screen, 370 r->vertices, 371 sizeof(r->vertices), 372 PIPE_BIND_VERTEX_BUFFER); 373 if (buf) { 374 cso_set_vertex_elements(r->cso, 2, r->owner->velems); 375 util_draw_vertex_buffer(r->pipe, buf, 0, 376 PIPE_PRIM_TRIANGLE_FAN, 377 Elements(r->vertices), /* verts */ 378 Elements(r->vertices[0])); /* attribs/vert */ 379 380 pipe_resource_reference(&buf, NULL); 381 } 382} 383 384/** 385 * Prepare the renderer for copying. 386 */ 387VGboolean renderer_copy_begin(struct renderer *renderer, 388 struct pipe_surface *dst, 389 VGboolean y0_top, 390 struct pipe_sampler_view *src) 391{ 392 assert(renderer->state == RENDERER_STATE_INIT); 393 394 /* sanity check */ 395 if (!renderer_can_support(renderer, 396 dst->texture, PIPE_BIND_RENDER_TARGET) || 397 !renderer_can_support(renderer, 398 src->texture, PIPE_BIND_SAMPLER_VIEW)) 399 return VG_FALSE; 400 401 cso_save_framebuffer(renderer->cso); 402 cso_save_viewport(renderer->cso); 403 cso_save_blend(renderer->cso); 404 cso_save_samplers(renderer->cso); 405 cso_save_fragment_sampler_views(renderer->cso); 406 cso_save_fragment_shader(renderer->cso); 407 cso_save_vertex_shader(renderer->cso); 408 409 renderer_set_target(renderer, dst, NULL, y0_top); 410 411 renderer_set_blend(renderer, ~0); 412 renderer_set_samplers(renderer, 1, &src); 413 414 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 415 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 416 417 /* remember the texture size */ 418 renderer->u.copy.tex_width = src->texture->width0; 419 renderer->u.copy.tex_height = src->texture->height0; 420 renderer->state = RENDERER_STATE_COPY; 421 422 return VG_TRUE; 423} 424 425/** 426 * Draw into the destination rectangle given by (x, y, w, h). The texture is 427 * sampled from within the rectangle given by (sx, sy, sw, sh). 428 * 429 * The coordinates are in surface coordinates. 430 */ 431void renderer_copy(struct renderer *renderer, 432 VGint x, VGint y, VGint w, VGint h, 433 VGint sx, VGint sy, VGint sw, VGint sh) 434{ 435 assert(renderer->state == RENDERER_STATE_COPY); 436 437 /* there is no depth buffer for scissoring anyway */ 438 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); 439 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 440 renderer->u.copy.tex_width, 441 renderer->u.copy.tex_height); 442 443 renderer_quad_draw(renderer); 444} 445 446/** 447 * End copying and restore the states. 448 */ 449void renderer_copy_end(struct renderer *renderer) 450{ 451 assert(renderer->state == RENDERER_STATE_COPY); 452 453 cso_restore_framebuffer(renderer->cso); 454 cso_restore_viewport(renderer->cso); 455 cso_restore_blend(renderer->cso); 456 cso_restore_samplers(renderer->cso); 457 cso_restore_fragment_sampler_views(renderer->cso); 458 cso_restore_fragment_shader(renderer->cso); 459 cso_restore_vertex_shader(renderer->cso); 460 461 renderer->state = RENDERER_STATE_INIT; 462} 463 464/** 465 * Prepare the renderer for textured drawing. 466 */ 467VGboolean renderer_drawtex_begin(struct renderer *renderer, 468 struct pipe_sampler_view *src) 469{ 470 assert(renderer->state == RENDERER_STATE_INIT); 471 472 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW)) 473 return VG_FALSE; 474 475 cso_save_blend(renderer->cso); 476 cso_save_samplers(renderer->cso); 477 cso_save_fragment_sampler_views(renderer->cso); 478 cso_save_fragment_shader(renderer->cso); 479 cso_save_vertex_shader(renderer->cso); 480 481 renderer_set_blend(renderer, ~0); 482 483 renderer_set_samplers(renderer, 1, &src); 484 485 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 486 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 487 488 /* remember the texture size */ 489 renderer->u.drawtex.tex_width = src->texture->width0; 490 renderer->u.drawtex.tex_height = src->texture->height0; 491 renderer->state = RENDERER_STATE_DRAWTEX; 492 493 return VG_TRUE; 494} 495 496/** 497 * Draw into the destination rectangle given by (x, y, w, h). The texture is 498 * sampled from within the rectangle given by (sx, sy, sw, sh). 499 * 500 * The coordinates are in surface coordinates. 501 */ 502void renderer_drawtex(struct renderer *renderer, 503 VGint x, VGint y, VGint w, VGint h, 504 VGint sx, VGint sy, VGint sw, VGint sh) 505{ 506 assert(renderer->state == RENDERER_STATE_DRAWTEX); 507 508 /* with scissoring */ 509 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE); 510 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 511 renderer->u.drawtex.tex_width, 512 renderer->u.drawtex.tex_height); 513 514 renderer_quad_draw(renderer); 515} 516 517/** 518 * End textured drawing and restore the states. 519 */ 520void renderer_drawtex_end(struct renderer *renderer) 521{ 522 assert(renderer->state == RENDERER_STATE_DRAWTEX); 523 524 cso_restore_blend(renderer->cso); 525 cso_restore_samplers(renderer->cso); 526 cso_restore_fragment_sampler_views(renderer->cso); 527 cso_restore_fragment_shader(renderer->cso); 528 cso_restore_vertex_shader(renderer->cso); 529 530 renderer->state = RENDERER_STATE_INIT; 531} 532 533static void setup_shaders(struct renderer *ctx) 534{ 535 struct pipe_context *pipe = ctx->pipe; 536 /* fragment shader */ 537 ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D, 538 TGSI_INTERPOLATE_LINEAR); 539} 540 541struct renderer * renderer_create(struct vg_context *owner) 542{ 543 VGint i; 544 struct renderer *renderer = CALLOC_STRUCT(renderer); 545 546 if (!renderer) 547 return NULL; 548 549 renderer->owner = owner; 550 renderer->pipe = owner->pipe; 551 renderer->cso = owner->cso_context; 552 553 setup_shaders(renderer); 554 555 /* init vertex data that doesn't change */ 556 for (i = 0; i < 4; i++) 557 renderer->vertices[i][0][3] = 1.0f; /* w */ 558 559 renderer->state = RENDERER_STATE_INIT; 560 561 return renderer; 562} 563 564void renderer_destroy(struct renderer *ctx) 565{ 566 int i; 567 568 for (i = 0; i < NUM_RENDERER_VS; i++) { 569 if (ctx->cached_vs[i]) 570 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]); 571 } 572 for (i = 0; i < NUM_RENDERER_FS; i++) { 573 if (ctx->cached_fs[i]) 574 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]); 575 } 576 577#if 0 578 if (ctx->fs) { 579 cso_delete_fragment_shader(ctx->cso, ctx->fs); 580 ctx->fs = NULL; 581 } 582#endif 583 FREE(ctx); 584} 585 586void renderer_draw_quad(struct renderer *r, 587 VGfloat x1, VGfloat y1, 588 VGfloat x2, VGfloat y2, 589 VGfloat depth) 590{ 591 assert(r->state == RENDERER_STATE_INIT); 592 assert(floatsEqual(depth, 0.0f)); 593 594 renderer_quad_pos(r, x1, y1, x2, y2, VG_TRUE); 595 renderer_quad_draw(r); 596} 597 598void renderer_draw_texture(struct renderer *r, 599 struct pipe_resource *tex, 600 VGfloat x1offset, VGfloat y1offset, 601 VGfloat x2offset, VGfloat y2offset, 602 VGfloat x1, VGfloat y1, 603 VGfloat x2, VGfloat y2) 604{ 605 assert(r->state == RENDERER_STATE_INIT); 606 assert(tex->width0 != 0); 607 assert(tex->height0 != 0); 608 609 cso_save_vertex_shader(r->cso); 610 611 renderer_set_vs(r, RENDERER_VS_TEXTURE); 612 613 renderer_quad_pos(r, x1, y1, x2, y2, VG_TRUE); 614 renderer_quad_texcoord(r, x1offset, y1offset, 615 x2offset, y2offset, tex->width0, tex->height0); 616 renderer_quad_draw(r); 617 618 cso_restore_vertex_shader(r->cso); 619} 620 621void renderer_copy_texture(struct renderer *ctx, 622 struct pipe_sampler_view *src, 623 VGfloat sx1, VGfloat sy1, 624 VGfloat sx2, VGfloat sy2, 625 struct pipe_resource *dst, 626 VGfloat dx1, VGfloat dy1, 627 VGfloat dx2, VGfloat dy2) 628{ 629 struct pipe_surface *surf; 630 VGint x, y, w, h, sx, sy, sw, sh; 631 632 /* get the destination surface */ 633 surf = ctx->pipe->screen->get_tex_surface(ctx->pipe->screen, 634 dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET); 635 if (!surf) 636 return; 637 638 assert(ctx->state == RENDERER_STATE_INIT); 639 assert(src->texture->width0 != 0); 640 assert(src->texture->height0 != 0); 641 assert(dst->width0 != 0); 642 assert(dst->height0 != 0); 643 644 x = (VGint) dx1; 645 y = (VGint) dy1; 646 w = (VGint) (dx2 - dx1); 647 h = (VGint) (dy2 - dy1); 648 assert(floatsEqual(x, dx1) && 649 floatsEqual(y, dy1) && 650 floatsEqual(w, (dx2 - dx1)) && 651 floatsEqual(h, (dy2 - dy1))); 652 653 sx = (VGint) sx1; 654 sy = (VGint) sy1; 655 sw = (VGint) (sx2 - sx1); 656 sh = (VGint) (sy2 - sy1); 657 assert(floatsEqual(sx, sx1) && 658 floatsEqual(sy, sy1) && 659 floatsEqual(sw, (sx2 - sx1)) && 660 floatsEqual(sh, (sy2 - sy1))); 661 662 if (renderer_copy_begin(ctx, surf, VG_TRUE, src)) { 663 renderer_copy(ctx, x, y, w, h, sx, sy, sw, sh); 664 renderer_copy_end(ctx); 665 } 666 667 pipe_surface_reference(&surf, NULL); 668} 669 670void renderer_copy_surface(struct renderer *ctx, 671 struct pipe_surface *src, 672 int srcX0, int srcY0, 673 int srcX1, int srcY1, 674 struct pipe_surface *dst, 675 int dstX0, int dstY0, 676 int dstX1, int dstY1, 677 float z, unsigned filter) 678{ 679 struct pipe_context *pipe = ctx->pipe; 680 struct pipe_screen *screen = pipe->screen; 681 struct pipe_sampler_view view_templ; 682 struct pipe_sampler_view *view; 683 struct pipe_resource texTemp, *tex; 684 struct pipe_subresource subsrc, subdst; 685 struct st_framebuffer *stfb = ctx->owner->draw_buffer; 686 const int srcW = abs(srcX1 - srcX0); 687 const int srcH = abs(srcY1 - srcY0); 688 const int srcLeft = MIN2(srcX0, srcX1); 689 const int srcTop = MIN2(srcY0, srcY1); 690 691 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 692 filter == PIPE_TEX_MIPFILTER_LINEAR); 693 694 if (srcLeft != srcX0) { 695 /* left-right flip */ 696 int tmp = dstX0; 697 dstX0 = dstX1; 698 dstX1 = tmp; 699 } 700 701 if (srcTop != srcY0) { 702 /* up-down flip */ 703 int tmp = dstY0; 704 dstY0 = dstY1; 705 dstY1 = tmp; 706 } 707 708 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 709 0, PIPE_BIND_SAMPLER_VIEW, 0)); 710 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 711 0, PIPE_BIND_SAMPLER_VIEW, 0)); 712 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 713 0, PIPE_BIND_RENDER_TARGET, 0)); 714 715 /* 716 * XXX for now we're always creating a temporary texture. 717 * Strictly speaking that's not always needed. 718 */ 719 720 /* create temp texture */ 721 memset(&texTemp, 0, sizeof(texTemp)); 722 texTemp.target = PIPE_TEXTURE_2D; 723 texTemp.format = src->format; 724 texTemp.last_level = 0; 725 texTemp.width0 = srcW; 726 texTemp.height0 = srcH; 727 texTemp.depth0 = 1; 728 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 729 730 tex = screen->resource_create(screen, &texTemp); 731 if (!tex) 732 return; 733 734 u_sampler_view_default_template(&view_templ, tex, tex->format); 735 view = pipe->create_sampler_view(pipe, tex, &view_templ); 736 737 if (!view) 738 return; 739 740 subdst.face = 0; 741 subdst.level = 0; 742 subsrc.face = src->face; 743 subsrc.level = src->level; 744 745 pipe->resource_copy_region(pipe, 746 tex, subdst, 0, 0, 0, /* dest */ 747 src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */ 748 srcW, srcH); /* size */ 749 750 assert(floatsEqual(z, 0.0f)); 751 752 /* draw */ 753 if (stfb->strb->surface == dst) { 754 /* transform back to surface coordinates */ 755 dstY0 = dst->height - dstY0; 756 dstY1 = dst->height - dstY1; 757 758 if (renderer_drawtex_begin(ctx, view)) { 759 renderer_drawtex(ctx, 760 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 761 0, 0, view->texture->width0, view->texture->height0); 762 renderer_drawtex_end(ctx); 763 } 764 } 765 else { 766 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) { 767 renderer_copy(ctx, 768 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 769 0, 0, view->texture->width0, view->texture->height0); 770 renderer_copy_end(ctx); 771 } 772 } 773} 774 775void renderer_texture_quad(struct renderer *r, 776 struct pipe_resource *tex, 777 VGfloat x1offset, VGfloat y1offset, 778 VGfloat x2offset, VGfloat y2offset, 779 VGfloat x1, VGfloat y1, 780 VGfloat x2, VGfloat y2, 781 VGfloat x3, VGfloat y3, 782 VGfloat x4, VGfloat y4) 783{ 784 const VGfloat z = 0.0f; 785 786 assert(r->state == RENDERER_STATE_INIT); 787 assert(tex->width0 != 0); 788 assert(tex->height0 != 0); 789 790 cso_save_vertex_shader(r->cso); 791 792 renderer_set_vs(r, RENDERER_VS_TEXTURE); 793 794 /* manually set up positions */ 795 r->vertices[0][0][0] = x1; 796 r->vertices[0][0][1] = y1; 797 r->vertices[0][0][2] = z; 798 799 r->vertices[1][0][0] = x2; 800 r->vertices[1][0][1] = y2; 801 r->vertices[1][0][2] = z; 802 803 r->vertices[2][0][0] = x3; 804 r->vertices[2][0][1] = y3; 805 r->vertices[2][0][2] = z; 806 807 r->vertices[3][0][0] = x4; 808 r->vertices[3][0][1] = y4; 809 r->vertices[3][0][2] = z; 810 811 /* texcoords */ 812 renderer_quad_texcoord(r, x1offset, y1offset, 813 x2offset, y2offset, tex->width0, tex->height0); 814 815 renderer_quad_draw(r); 816 817 cso_restore_vertex_shader(r->cso); 818} 819