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