renderer.c revision 3b71cb6ad6dabfefc9363a35872f4e70e1125603
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#include "image.h" 32 33#include "pipe/p_context.h" 34#include "pipe/p_state.h" 35#include "util/u_inlines.h" 36#include "pipe/p_screen.h" 37#include "pipe/p_shader_tokens.h" 38 39#include "util/u_draw_quad.h" 40#include "util/u_simple_shaders.h" 41#include "util/u_memory.h" 42#include "util/u_sampler.h" 43 44#include "cso_cache/cso_context.h" 45#include "tgsi/tgsi_ureg.h" 46 47typedef enum { 48 RENDERER_STATE_INIT, 49 RENDERER_STATE_COPY, 50 RENDERER_STATE_DRAWTEX, 51 RENDERER_STATE_SCISSOR, 52 RENDERER_STATE_CLEAR, 53 RENDERER_STATE_FILTER, 54 RENDERER_STATE_POLYGON_STENCIL, 55 RENDERER_STATE_POLYGON_FILL, 56 NUM_RENDERER_STATES 57} RendererState; 58 59typedef enum { 60 RENDERER_VS_PLAIN, 61 RENDERER_VS_COLOR, 62 RENDERER_VS_TEXTURE, 63 NUM_RENDERER_VS 64} RendererVs; 65 66typedef enum { 67 RENDERER_FS_COLOR, 68 RENDERER_FS_TEXTURE, 69 RENDERER_FS_SCISSOR, 70 NUM_RENDERER_FS 71} RendererFs; 72 73struct renderer { 74 struct pipe_context *pipe; 75 struct vg_context *owner; 76 77 struct cso_context *cso; 78 79 void *fs; 80 81 VGfloat vertices[4][2][4]; 82 83 void *cached_vs[NUM_RENDERER_VS]; 84 void *cached_fs[NUM_RENDERER_FS]; 85 86 RendererState state; 87 88 /* state data */ 89 union { 90 struct { 91 VGint tex_width; 92 VGint tex_height; 93 } copy; 94 95 struct { 96 VGint tex_width; 97 VGint tex_height; 98 } drawtex; 99 100 struct { 101 VGboolean restore_dsa; 102 } scissor; 103 104 struct { 105 VGboolean use_sampler; 106 VGint tex_width, tex_height; 107 } filter; 108 109 struct { 110 struct pipe_depth_stencil_alpha_state dsa; 111 VGboolean manual_two_sides; 112 VGboolean restore_dsa; 113 } polygon_stencil; 114 } u; 115}; 116 117/** 118 * Return VG_TRUE if the renderer can use the resource as the asked bindings. 119 */ 120static VGboolean renderer_can_support(struct renderer *renderer, 121 struct pipe_resource *res, 122 unsigned bindings) 123{ 124 struct pipe_screen *screen = renderer->pipe->screen; 125 126 return screen->is_format_supported(screen, 127 res->format, res->target, 0, bindings, 0); 128} 129 130/** 131 * Create a simple vertex shader that passes through position and the given 132 * attribute. 133 */ 134static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name) 135{ 136 struct ureg_program *ureg; 137 struct ureg_src src[2], constants[2]; 138 struct ureg_dst dst[2], tmp; 139 int i; 140 141 ureg = ureg_create(TGSI_PROCESSOR_VERTEX); 142 if (!ureg) 143 return NULL; 144 145 /* position in surface coordinates */ 146 src[0] = ureg_DECL_vs_input(ureg, 0); 147 dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 148 tmp = ureg_DECL_temporary(ureg); 149 for (i = 0; i < 2; i++) 150 constants[i] = ureg_DECL_constant(ureg, i); 151 152 /* transform to clipped coordinates */ 153 ureg_MUL(ureg, tmp, src[0], constants[0]); 154 ureg_ADD(ureg, tmp, ureg_src(tmp), constants[1]); 155 ureg_MOV(ureg, dst[0], ureg_src(tmp)); 156 157 if (semantic_name >= 0) { 158 src[1] = ureg_DECL_vs_input(ureg, 1); 159 dst[1] = ureg_DECL_output(ureg, semantic_name, 0); 160 ureg_MOV(ureg, dst[1], src[1]); 161 } 162 163 ureg_END(ureg); 164 165 return ureg_create_shader_and_destroy(ureg, pipe); 166} 167 168/** 169 * Set renderer vertex shader. 170 * 171 * This function modifies vertex_shader state. 172 */ 173static void renderer_set_vs(struct renderer *r, RendererVs id) 174{ 175 /* create as needed */ 176 if (!r->cached_vs[id]) { 177 int semantic_name = -1; 178 179 switch (id) { 180 case RENDERER_VS_PLAIN: 181 break; 182 case RENDERER_VS_COLOR: 183 semantic_name = TGSI_SEMANTIC_COLOR; 184 break; 185 case RENDERER_VS_TEXTURE: 186 semantic_name = TGSI_SEMANTIC_GENERIC; 187 break; 188 default: 189 assert(!"Unknown renderer vs id"); 190 break; 191 } 192 193 r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name); 194 } 195 196 cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]); 197} 198 199/** 200 * Create a simple fragment shader that sets the depth to 0.0f. 201 */ 202static void *create_scissor_fs(struct pipe_context *pipe) 203{ 204 struct ureg_program *ureg; 205 struct ureg_dst out; 206 struct ureg_src imm; 207 208 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 209 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 210 imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f); 211 212 ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm); 213 ureg_END(ureg); 214 215 return ureg_create_shader_and_destroy(ureg, pipe); 216} 217 218/** 219 * Set renderer fragment shader. 220 * 221 * This function modifies fragment_shader state. 222 */ 223static void renderer_set_fs(struct renderer *r, RendererFs id) 224{ 225 /* create as needed */ 226 if (!r->cached_fs[id]) { 227 void *fs = NULL; 228 229 switch (id) { 230 case RENDERER_FS_COLOR: 231 fs = util_make_fragment_passthrough_shader(r->pipe); 232 break; 233 case RENDERER_FS_TEXTURE: 234 fs = util_make_fragment_tex_shader(r->pipe, 235 TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR); 236 break; 237 case RENDERER_FS_SCISSOR: 238 fs = create_scissor_fs(r->pipe); 239 break; 240 default: 241 assert(!"Unknown renderer fs id"); 242 break; 243 } 244 245 r->cached_fs[id] = fs; 246 } 247 248 cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]); 249} 250 251/** 252 * Set renderer target. 253 * 254 * This function modifies framebuffer and viewport states. 255 */ 256static void renderer_set_target(struct renderer *r, 257 struct pipe_surface *cbuf, 258 struct pipe_surface *zsbuf, 259 VGboolean y0_top) 260{ 261 struct pipe_framebuffer_state fb; 262 263 memset(&fb, 0, sizeof(fb)); 264 fb.width = cbuf->width; 265 fb.height = cbuf->height; 266 fb.cbufs[0] = cbuf; 267 fb.nr_cbufs = 1; 268 fb.zsbuf = zsbuf; 269 cso_set_framebuffer(r->cso, &fb); 270 271 vg_set_viewport(r->owner, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM); 272} 273 274/** 275 * Set renderer blend state. Blending is disabled. 276 * 277 * This function modifies blend state. 278 */ 279static void renderer_set_blend(struct renderer *r, 280 VGbitfield channel_mask) 281{ 282 struct pipe_blend_state blend; 283 284 memset(&blend, 0, sizeof(blend)); 285 286 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 287 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 288 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 289 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 290 291 if (channel_mask & VG_RED) 292 blend.rt[0].colormask |= PIPE_MASK_R; 293 if (channel_mask & VG_GREEN) 294 blend.rt[0].colormask |= PIPE_MASK_G; 295 if (channel_mask & VG_BLUE) 296 blend.rt[0].colormask |= PIPE_MASK_B; 297 if (channel_mask & VG_ALPHA) 298 blend.rt[0].colormask |= PIPE_MASK_A; 299 300 cso_set_blend(r->cso, &blend); 301} 302 303/** 304 * Set renderer sampler and view states. 305 * 306 * This function modifies samplers and fragment_sampler_views states. 307 */ 308static void renderer_set_samplers(struct renderer *r, 309 uint num_views, 310 struct pipe_sampler_view **views) 311{ 312 struct pipe_sampler_state sampler; 313 unsigned tex_filter = PIPE_TEX_FILTER_NEAREST; 314 unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 315 uint i; 316 317 memset(&sampler, 0, sizeof(sampler)); 318 319 sampler.min_img_filter = tex_filter; 320 sampler.mag_img_filter = tex_filter; 321 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 322 323 sampler.wrap_s = tex_wrap; 324 sampler.wrap_t = tex_wrap; 325 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 326 327 sampler.normalized_coords = 1; 328 329 /* set samplers */ 330 for (i = 0; i < num_views; i++) 331 cso_single_sampler(r->cso, i, &sampler); 332 cso_single_sampler_done(r->cso); 333 334 /* set views */ 335 cso_set_fragment_sampler_views(r->cso, num_views, views); 336} 337 338/** 339 * Set custom renderer fragment shader, and optionally set samplers and views 340 * and upload the fragment constant buffer. 341 * 342 * This function modifies fragment_shader, samplers and fragment_sampler_views 343 * states. 344 */ 345static void renderer_set_custom_fs(struct renderer *renderer, 346 void *fs, 347 const struct pipe_sampler_state **samplers, 348 struct pipe_sampler_view **views, 349 VGint num_samplers, 350 const void *const_buffer, 351 VGint const_buffer_len) 352{ 353 cso_set_fragment_shader_handle(renderer->cso, fs); 354 355 /* set samplers and views */ 356 if (num_samplers) { 357 cso_set_samplers(renderer->cso, num_samplers, samplers); 358 cso_set_fragment_sampler_views(renderer->cso, num_samplers, views); 359 } 360 361 /* upload fs constant buffer */ 362 if (const_buffer_len) { 363 struct pipe_resource *cbuf; 364 365 cbuf = pipe_buffer_create(renderer->pipe->screen, 366 PIPE_BIND_CONSTANT_BUFFER, const_buffer_len); 367 pipe_buffer_write(renderer->pipe, cbuf, 0, 368 const_buffer_len, const_buffer); 369 renderer->pipe->set_constant_buffer(renderer->pipe, 370 PIPE_SHADER_FRAGMENT, 0, cbuf); 371 372 /* destroy cbuf automatically */ 373 pipe_resource_reference(&cbuf, NULL); 374 } 375} 376 377/** 378 * Setup renderer quad position. 379 */ 380static void renderer_quad_pos(struct renderer *r, 381 VGfloat x0, VGfloat y0, 382 VGfloat x1, VGfloat y1, 383 VGboolean scissor) 384{ 385 VGfloat z; 386 387 /* the depth test is used for scissoring */ 388 z = (scissor) ? 0.0f : 1.0f; 389 390 /* positions */ 391 r->vertices[0][0][0] = x0; 392 r->vertices[0][0][1] = y0; 393 r->vertices[0][0][2] = z; 394 395 r->vertices[1][0][0] = x1; 396 r->vertices[1][0][1] = y0; 397 r->vertices[1][0][2] = z; 398 399 r->vertices[2][0][0] = x1; 400 r->vertices[2][0][1] = y1; 401 r->vertices[2][0][2] = z; 402 403 r->vertices[3][0][0] = x0; 404 r->vertices[3][0][1] = y1; 405 r->vertices[3][0][2] = z; 406} 407 408/** 409 * Setup renderer quad texture coordinates. 410 */ 411static void renderer_quad_texcoord(struct renderer *r, 412 VGfloat x0, VGfloat y0, 413 VGfloat x1, VGfloat y1, 414 VGint tex_width, VGint tex_height) 415{ 416 VGfloat s0, t0, s1, t1, r0, q0; 417 VGint i; 418 419 s0 = x0 / tex_width; 420 s1 = x1 / tex_width; 421 t0 = y0 / tex_height; 422 t1 = y1 / tex_height; 423 r0 = 0.0f; 424 q0 = 1.0f; 425 426 /* texcoords */ 427 r->vertices[0][1][0] = s0; 428 r->vertices[0][1][1] = t0; 429 430 r->vertices[1][1][0] = s1; 431 r->vertices[1][1][1] = t0; 432 433 r->vertices[2][1][0] = s1; 434 r->vertices[2][1][1] = t1; 435 436 r->vertices[3][1][0] = s0; 437 r->vertices[3][1][1] = t1; 438 439 for (i = 0; i < 4; i++) { 440 r->vertices[i][1][2] = r0; 441 r->vertices[i][1][3] = q0; 442 } 443} 444 445/** 446 * Draw renderer quad. 447 */ 448static void renderer_quad_draw(struct renderer *r) 449{ 450 struct pipe_resource *buf; 451 452 buf = pipe_user_buffer_create(r->pipe->screen, 453 r->vertices, 454 sizeof(r->vertices), 455 PIPE_BIND_VERTEX_BUFFER); 456 if (buf) { 457 cso_set_vertex_elements(r->cso, 2, r->owner->velems); 458 util_draw_vertex_buffer(r->pipe, buf, 0, 459 PIPE_PRIM_TRIANGLE_FAN, 460 Elements(r->vertices), /* verts */ 461 Elements(r->vertices[0])); /* attribs/vert */ 462 463 pipe_resource_reference(&buf, NULL); 464 } 465} 466 467/** 468 * Prepare the renderer for copying. 469 */ 470VGboolean renderer_copy_begin(struct renderer *renderer, 471 struct pipe_surface *dst, 472 VGboolean y0_top, 473 struct pipe_sampler_view *src) 474{ 475 assert(renderer->state == RENDERER_STATE_INIT); 476 477 /* sanity check */ 478 if (!renderer_can_support(renderer, 479 dst->texture, PIPE_BIND_RENDER_TARGET) || 480 !renderer_can_support(renderer, 481 src->texture, PIPE_BIND_SAMPLER_VIEW)) 482 return VG_FALSE; 483 484 cso_save_framebuffer(renderer->cso); 485 cso_save_viewport(renderer->cso); 486 cso_save_blend(renderer->cso); 487 cso_save_samplers(renderer->cso); 488 cso_save_fragment_sampler_views(renderer->cso); 489 cso_save_fragment_shader(renderer->cso); 490 cso_save_vertex_shader(renderer->cso); 491 492 renderer_set_target(renderer, dst, NULL, y0_top); 493 494 renderer_set_blend(renderer, ~0); 495 renderer_set_samplers(renderer, 1, &src); 496 497 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 498 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 499 500 /* remember the texture size */ 501 renderer->u.copy.tex_width = src->texture->width0; 502 renderer->u.copy.tex_height = src->texture->height0; 503 renderer->state = RENDERER_STATE_COPY; 504 505 return VG_TRUE; 506} 507 508/** 509 * Draw into the destination rectangle given by (x, y, w, h). The texture is 510 * sampled from within the rectangle given by (sx, sy, sw, sh). 511 * 512 * The coordinates are in surface coordinates. 513 */ 514void renderer_copy(struct renderer *renderer, 515 VGint x, VGint y, VGint w, VGint h, 516 VGint sx, VGint sy, VGint sw, VGint sh) 517{ 518 assert(renderer->state == RENDERER_STATE_COPY); 519 520 /* there is no depth buffer for scissoring anyway */ 521 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); 522 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 523 renderer->u.copy.tex_width, 524 renderer->u.copy.tex_height); 525 526 renderer_quad_draw(renderer); 527} 528 529/** 530 * End copying and restore the states. 531 */ 532void renderer_copy_end(struct renderer *renderer) 533{ 534 assert(renderer->state == RENDERER_STATE_COPY); 535 536 cso_restore_framebuffer(renderer->cso); 537 cso_restore_viewport(renderer->cso); 538 cso_restore_blend(renderer->cso); 539 cso_restore_samplers(renderer->cso); 540 cso_restore_fragment_sampler_views(renderer->cso); 541 cso_restore_fragment_shader(renderer->cso); 542 cso_restore_vertex_shader(renderer->cso); 543 544 renderer->state = RENDERER_STATE_INIT; 545} 546 547/** 548 * Prepare the renderer for textured drawing. 549 */ 550VGboolean renderer_drawtex_begin(struct renderer *renderer, 551 struct pipe_sampler_view *src) 552{ 553 assert(renderer->state == RENDERER_STATE_INIT); 554 555 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW)) 556 return VG_FALSE; 557 558 cso_save_blend(renderer->cso); 559 cso_save_samplers(renderer->cso); 560 cso_save_fragment_sampler_views(renderer->cso); 561 cso_save_fragment_shader(renderer->cso); 562 cso_save_vertex_shader(renderer->cso); 563 564 renderer_set_blend(renderer, ~0); 565 566 renderer_set_samplers(renderer, 1, &src); 567 568 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 569 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 570 571 /* remember the texture size */ 572 renderer->u.drawtex.tex_width = src->texture->width0; 573 renderer->u.drawtex.tex_height = src->texture->height0; 574 renderer->state = RENDERER_STATE_DRAWTEX; 575 576 return VG_TRUE; 577} 578 579/** 580 * Draw into the destination rectangle given by (x, y, w, h). The texture is 581 * sampled from within the rectangle given by (sx, sy, sw, sh). 582 * 583 * The coordinates are in surface coordinates. 584 */ 585void renderer_drawtex(struct renderer *renderer, 586 VGint x, VGint y, VGint w, VGint h, 587 VGint sx, VGint sy, VGint sw, VGint sh) 588{ 589 assert(renderer->state == RENDERER_STATE_DRAWTEX); 590 591 /* with scissoring */ 592 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE); 593 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 594 renderer->u.drawtex.tex_width, 595 renderer->u.drawtex.tex_height); 596 597 renderer_quad_draw(renderer); 598} 599 600/** 601 * End textured drawing and restore the states. 602 */ 603void renderer_drawtex_end(struct renderer *renderer) 604{ 605 assert(renderer->state == RENDERER_STATE_DRAWTEX); 606 607 cso_restore_blend(renderer->cso); 608 cso_restore_samplers(renderer->cso); 609 cso_restore_fragment_sampler_views(renderer->cso); 610 cso_restore_fragment_shader(renderer->cso); 611 cso_restore_vertex_shader(renderer->cso); 612 613 renderer->state = RENDERER_STATE_INIT; 614} 615 616/** 617 * Prepare the renderer for scissor update. This will reset the depth buffer 618 * to 1.0f. 619 */ 620VGboolean renderer_scissor_begin(struct renderer *renderer, 621 VGboolean restore_dsa) 622{ 623 struct pipe_depth_stencil_alpha_state dsa; 624 625 assert(renderer->state == RENDERER_STATE_INIT); 626 627 if (restore_dsa) 628 cso_save_depth_stencil_alpha(renderer->cso); 629 cso_save_blend(renderer->cso); 630 cso_save_fragment_shader(renderer->cso); 631 632 /* enable depth writes */ 633 memset(&dsa, 0, sizeof(dsa)); 634 dsa.depth.enabled = 1; 635 dsa.depth.writemask = 1; 636 dsa.depth.func = PIPE_FUNC_ALWAYS; 637 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 638 639 /* disable color writes */ 640 renderer_set_blend(renderer, 0); 641 renderer_set_fs(renderer, RENDERER_FS_SCISSOR); 642 643 renderer->u.scissor.restore_dsa = restore_dsa; 644 renderer->state = RENDERER_STATE_SCISSOR; 645 646 /* clear the depth buffer to 1.0f */ 647 renderer->pipe->clear(renderer->pipe, 648 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0); 649 650 return VG_TRUE; 651} 652 653/** 654 * Add a scissor rectangle. Depth values inside the rectangle will be set to 655 * 0.0f. 656 */ 657void renderer_scissor(struct renderer *renderer, 658 VGint x, VGint y, VGint width, VGint height) 659{ 660 assert(renderer->state == RENDERER_STATE_SCISSOR); 661 662 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE); 663 renderer_quad_draw(renderer); 664} 665 666/** 667 * End scissor update and restore the states. 668 */ 669void renderer_scissor_end(struct renderer *renderer) 670{ 671 assert(renderer->state == RENDERER_STATE_SCISSOR); 672 673 if (renderer->u.scissor.restore_dsa) 674 cso_restore_depth_stencil_alpha(renderer->cso); 675 cso_restore_blend(renderer->cso); 676 cso_restore_fragment_shader(renderer->cso); 677 678 renderer->state = RENDERER_STATE_INIT; 679} 680 681/** 682 * Prepare the renderer for clearing. 683 */ 684VGboolean renderer_clear_begin(struct renderer *renderer) 685{ 686 assert(renderer->state == RENDERER_STATE_INIT); 687 688 cso_save_blend(renderer->cso); 689 cso_save_fragment_shader(renderer->cso); 690 cso_save_vertex_shader(renderer->cso); 691 692 renderer_set_blend(renderer, ~0); 693 renderer_set_fs(renderer, RENDERER_FS_COLOR); 694 renderer_set_vs(renderer, RENDERER_VS_COLOR); 695 696 renderer->state = RENDERER_STATE_CLEAR; 697 698 return VG_TRUE; 699} 700 701/** 702 * Clear the framebuffer with the specified region and color. 703 * 704 * The coordinates are in surface coordinates. 705 */ 706void renderer_clear(struct renderer *renderer, 707 VGint x, VGint y, VGint width, VGint height, 708 const VGfloat color[4]) 709{ 710 VGuint i; 711 712 assert(renderer->state == RENDERER_STATE_CLEAR); 713 714 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE); 715 for (i = 0; i < 4; i++) 716 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4); 717 718 renderer_quad_draw(renderer); 719} 720 721/** 722 * End clearing and retore the states. 723 */ 724void renderer_clear_end(struct renderer *renderer) 725{ 726 assert(renderer->state == RENDERER_STATE_CLEAR); 727 728 cso_restore_blend(renderer->cso); 729 cso_restore_fragment_shader(renderer->cso); 730 cso_restore_vertex_shader(renderer->cso); 731 732 renderer->state = RENDERER_STATE_INIT; 733} 734 735/** 736 * Prepare the renderer for image filtering. 737 */ 738VGboolean renderer_filter_begin(struct renderer *renderer, 739 struct pipe_resource *dst, 740 VGboolean y0_top, 741 VGbitfield channel_mask, 742 const struct pipe_sampler_state **samplers, 743 struct pipe_sampler_view **views, 744 VGint num_samplers, 745 void *fs, 746 const void *const_buffer, 747 VGint const_buffer_len) 748{ 749 struct pipe_surface *surf; 750 751 assert(renderer->state == RENDERER_STATE_INIT); 752 753 if (!fs) 754 return VG_FALSE; 755 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET)) 756 return VG_FALSE; 757 758 surf = renderer->pipe->screen->get_tex_surface(renderer->pipe->screen, 759 dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET); 760 if (!surf) 761 return VG_FALSE; 762 763 cso_save_framebuffer(renderer->cso); 764 cso_save_viewport(renderer->cso); 765 cso_save_blend(renderer->cso); 766 767 /* set the image as the target */ 768 renderer_set_target(renderer, surf, NULL, y0_top); 769 pipe_surface_reference(&surf, NULL); 770 771 renderer_set_blend(renderer, channel_mask); 772 773 if (num_samplers) { 774 struct pipe_resource *tex; 775 776 cso_save_samplers(renderer->cso); 777 cso_save_fragment_sampler_views(renderer->cso); 778 cso_save_fragment_shader(renderer->cso); 779 cso_save_vertex_shader(renderer->cso); 780 781 renderer_set_custom_fs(renderer, fs, 782 samplers, views, num_samplers, 783 const_buffer, const_buffer_len); 784 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 785 786 tex = views[0]->texture; 787 renderer->u.filter.tex_width = tex->width0; 788 renderer->u.filter.tex_height = tex->height0; 789 renderer->u.filter.use_sampler = VG_TRUE; 790 } 791 else { 792 cso_save_fragment_shader(renderer->cso); 793 794 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0, 795 const_buffer, const_buffer_len); 796 797 renderer->u.filter.use_sampler = VG_FALSE; 798 } 799 800 renderer->state = RENDERER_STATE_FILTER; 801 802 return VG_TRUE; 803} 804 805/** 806 * Draw into a rectangle of the destination with the specified region of the 807 * texture(s). 808 * 809 * The coordinates are in surface coordinates. 810 */ 811void renderer_filter(struct renderer *renderer, 812 VGint x, VGint y, VGint w, VGint h, 813 VGint sx, VGint sy, VGint sw, VGint sh) 814{ 815 assert(renderer->state == RENDERER_STATE_FILTER); 816 817 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); 818 if (renderer->u.filter.use_sampler) { 819 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 820 renderer->u.filter.tex_width, 821 renderer->u.filter.tex_height); 822 } 823 824 renderer_quad_draw(renderer); 825} 826 827/** 828 * End image filtering and restore the states. 829 */ 830void renderer_filter_end(struct renderer *renderer) 831{ 832 assert(renderer->state == RENDERER_STATE_FILTER); 833 834 if (renderer->u.filter.use_sampler) { 835 cso_restore_samplers(renderer->cso); 836 cso_restore_fragment_sampler_views(renderer->cso); 837 cso_restore_vertex_shader(renderer->cso); 838 } 839 840 cso_restore_framebuffer(renderer->cso); 841 cso_restore_viewport(renderer->cso); 842 cso_restore_blend(renderer->cso); 843 cso_restore_fragment_shader(renderer->cso); 844 845 renderer->state = RENDERER_STATE_INIT; 846} 847 848/** 849 * Prepare the renderer for polygon silhouette rendering. 850 */ 851VGboolean renderer_polygon_stencil_begin(struct renderer *renderer, 852 struct pipe_vertex_element *velem, 853 VGFillRule rule, 854 VGboolean restore_dsa) 855{ 856 struct pipe_depth_stencil_alpha_state *dsa; 857 VGboolean manual_two_sides; 858 859 assert(renderer->state == RENDERER_STATE_INIT); 860 861 cso_save_blend(renderer->cso); 862 cso_save_depth_stencil_alpha(renderer->cso); 863 864 cso_set_vertex_elements(renderer->cso, 1, velem); 865 866 /* disable color writes */ 867 renderer_set_blend(renderer, 0); 868 869 manual_two_sides = VG_FALSE; 870 dsa = &renderer->u.polygon_stencil.dsa; 871 memset(dsa, 0, sizeof(*dsa)); 872 if (rule == VG_EVEN_ODD) { 873 dsa->stencil[0].enabled = 1; 874 dsa->stencil[0].writemask = 1; 875 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; 876 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; 877 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; 878 dsa->stencil[0].func = PIPE_FUNC_ALWAYS; 879 dsa->stencil[0].valuemask = ~0; 880 } 881 else { 882 assert(rule == VG_NON_ZERO); 883 884 /* front face */ 885 dsa->stencil[0].enabled = 1; 886 dsa->stencil[0].writemask = ~0; 887 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; 888 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; 889 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; 890 dsa->stencil[0].func = PIPE_FUNC_ALWAYS; 891 dsa->stencil[0].valuemask = ~0; 892 893 if (renderer->pipe->screen->get_param(renderer->pipe->screen, 894 PIPE_CAP_TWO_SIDED_STENCIL)) { 895 /* back face */ 896 dsa->stencil[1] = dsa->stencil[0]; 897 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; 898 } 899 else { 900 manual_two_sides = VG_TRUE; 901 } 902 } 903 cso_set_depth_stencil_alpha(renderer->cso, dsa); 904 905 if (manual_two_sides) 906 cso_save_rasterizer(renderer->cso); 907 908 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides; 909 renderer->u.polygon_stencil.restore_dsa = restore_dsa; 910 renderer->state = RENDERER_STATE_POLYGON_STENCIL; 911 912 return VG_TRUE; 913} 914 915/** 916 * Render a polygon silhouette to stencil buffer. 917 */ 918void renderer_polygon_stencil(struct renderer *renderer, 919 struct pipe_vertex_buffer *vbuf, 920 VGuint mode, VGuint start, VGuint count) 921{ 922 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); 923 924 renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf); 925 926 if (!renderer->u.polygon_stencil.manual_two_sides) { 927 util_draw_arrays(renderer->pipe, mode, start, count); 928 } 929 else { 930 struct pipe_rasterizer_state raster; 931 struct pipe_depth_stencil_alpha_state dsa; 932 933 /* TODO do not access owner state */ 934 raster = renderer->owner->state.g3d.rasterizer; 935 dsa = renderer->u.polygon_stencil.dsa; 936 937 /* front */ 938 raster.cull_face = PIPE_FACE_BACK; 939 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; 940 941 cso_set_rasterizer(renderer->cso, &raster); 942 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 943 util_draw_arrays(renderer->pipe, mode, start, count); 944 945 /* back */ 946 raster.cull_face = PIPE_FACE_FRONT; 947 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; 948 949 cso_set_rasterizer(renderer->cso, &raster); 950 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 951 util_draw_arrays(renderer->pipe, mode, start, count); 952 } 953} 954 955/** 956 * End polygon silhouette rendering. 957 */ 958void renderer_polygon_stencil_end(struct renderer *renderer) 959{ 960 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); 961 962 if (renderer->u.polygon_stencil.manual_two_sides) 963 cso_restore_rasterizer(renderer->cso); 964 965 /* restore color writes */ 966 cso_restore_blend(renderer->cso); 967 968 if (renderer->u.polygon_stencil.restore_dsa) 969 cso_restore_depth_stencil_alpha(renderer->cso); 970 971 renderer->state = RENDERER_STATE_INIT; 972} 973 974/** 975 * Prepare the renderer for polygon filling. 976 */ 977VGboolean renderer_polygon_fill_begin(struct renderer *renderer, 978 VGboolean save_dsa) 979{ 980 struct pipe_depth_stencil_alpha_state dsa; 981 struct pipe_stencil_ref sr; 982 983 assert(renderer->state == RENDERER_STATE_INIT); 984 985 if (save_dsa) 986 cso_save_depth_stencil_alpha(renderer->cso); 987 988 /* only need a fixed 0. Rely on default or move it out at least? */ 989 memset(&sr, 0, sizeof(sr)); 990 cso_set_stencil_ref(renderer->cso, &sr); 991 992 /* setup stencil ops */ 993 memset(&dsa, 0, sizeof(dsa)); 994 dsa.stencil[0].enabled = 1; 995 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; 996 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 997 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 998 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 999 dsa.stencil[0].valuemask = ~0; 1000 dsa.stencil[0].writemask = ~0; 1001 /* TODO do not access owner state */ 1002 dsa.depth = renderer->owner->state.g3d.dsa.depth; 1003 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 1004 1005 renderer->state = RENDERER_STATE_POLYGON_FILL; 1006 1007 return VG_TRUE; 1008} 1009 1010/** 1011 * Fill a polygon. 1012 */ 1013void renderer_polygon_fill(struct renderer *renderer, 1014 VGfloat min_x, VGfloat min_y, 1015 VGfloat max_x, VGfloat max_y) 1016{ 1017 assert(renderer->state == RENDERER_STATE_POLYGON_FILL); 1018 1019 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE); 1020 renderer_quad_draw(renderer); 1021} 1022 1023/** 1024 * End polygon filling. 1025 */ 1026void renderer_polygon_fill_end(struct renderer *renderer) 1027{ 1028 assert(renderer->state == RENDERER_STATE_POLYGON_FILL); 1029 1030 cso_restore_depth_stencil_alpha(renderer->cso); 1031 1032 renderer->state = RENDERER_STATE_INIT; 1033} 1034 1035static void setup_shaders(struct renderer *ctx) 1036{ 1037 struct pipe_context *pipe = ctx->pipe; 1038 /* fragment shader */ 1039 ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D, 1040 TGSI_INTERPOLATE_LINEAR); 1041} 1042 1043struct renderer * renderer_create(struct vg_context *owner) 1044{ 1045 VGint i; 1046 struct renderer *renderer = CALLOC_STRUCT(renderer); 1047 1048 if (!renderer) 1049 return NULL; 1050 1051 renderer->owner = owner; 1052 renderer->pipe = owner->pipe; 1053 renderer->cso = owner->cso_context; 1054 1055 setup_shaders(renderer); 1056 1057 /* init vertex data that doesn't change */ 1058 for (i = 0; i < 4; i++) 1059 renderer->vertices[i][0][3] = 1.0f; /* w */ 1060 1061 renderer->state = RENDERER_STATE_INIT; 1062 1063 return renderer; 1064} 1065 1066void renderer_destroy(struct renderer *ctx) 1067{ 1068 int i; 1069 1070 for (i = 0; i < NUM_RENDERER_VS; i++) { 1071 if (ctx->cached_vs[i]) 1072 cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]); 1073 } 1074 for (i = 0; i < NUM_RENDERER_FS; i++) { 1075 if (ctx->cached_fs[i]) 1076 cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]); 1077 } 1078 1079#if 0 1080 if (ctx->fs) { 1081 cso_delete_fragment_shader(ctx->cso, ctx->fs); 1082 ctx->fs = NULL; 1083 } 1084#endif 1085 FREE(ctx); 1086} 1087 1088void renderer_draw_quad(struct renderer *r, 1089 VGfloat x1, VGfloat y1, 1090 VGfloat x2, VGfloat y2, 1091 VGfloat depth) 1092{ 1093 assert(r->state == RENDERER_STATE_INIT); 1094 assert(floatsEqual(depth, 0.0f)); 1095 1096 renderer_quad_pos(r, x1, y1, x2, y2, VG_TRUE); 1097 renderer_quad_draw(r); 1098} 1099 1100void renderer_draw_texture(struct renderer *r, 1101 struct pipe_resource *tex, 1102 VGfloat x1offset, VGfloat y1offset, 1103 VGfloat x2offset, VGfloat y2offset, 1104 VGfloat x1, VGfloat y1, 1105 VGfloat x2, VGfloat y2) 1106{ 1107 assert(r->state == RENDERER_STATE_INIT); 1108 assert(tex->width0 != 0); 1109 assert(tex->height0 != 0); 1110 1111 cso_save_vertex_shader(r->cso); 1112 1113 renderer_set_vs(r, RENDERER_VS_TEXTURE); 1114 1115 renderer_quad_pos(r, x1, y1, x2, y2, VG_TRUE); 1116 renderer_quad_texcoord(r, x1offset, y1offset, 1117 x2offset, y2offset, tex->width0, tex->height0); 1118 renderer_quad_draw(r); 1119 1120 cso_restore_vertex_shader(r->cso); 1121} 1122 1123void renderer_copy_texture(struct renderer *ctx, 1124 struct pipe_sampler_view *src, 1125 VGfloat sx1, VGfloat sy1, 1126 VGfloat sx2, VGfloat sy2, 1127 struct pipe_resource *dst, 1128 VGfloat dx1, VGfloat dy1, 1129 VGfloat dx2, VGfloat dy2) 1130{ 1131 struct pipe_surface *surf; 1132 VGint x, y, w, h, sx, sy, sw, sh; 1133 1134 /* get the destination surface */ 1135 surf = ctx->pipe->screen->get_tex_surface(ctx->pipe->screen, 1136 dst, 0, 0, 0, PIPE_BIND_RENDER_TARGET); 1137 if (!surf) 1138 return; 1139 1140 assert(ctx->state == RENDERER_STATE_INIT); 1141 assert(src->texture->width0 != 0); 1142 assert(src->texture->height0 != 0); 1143 assert(dst->width0 != 0); 1144 assert(dst->height0 != 0); 1145 1146 x = (VGint) dx1; 1147 y = (VGint) dy1; 1148 w = (VGint) (dx2 - dx1); 1149 h = (VGint) (dy2 - dy1); 1150 assert(floatsEqual(x, dx1) && 1151 floatsEqual(y, dy1) && 1152 floatsEqual(w, (dx2 - dx1)) && 1153 floatsEqual(h, (dy2 - dy1))); 1154 1155 sx = (VGint) sx1; 1156 sy = (VGint) sy1; 1157 sw = (VGint) (sx2 - sx1); 1158 sh = (VGint) (sy2 - sy1); 1159 assert(floatsEqual(sx, sx1) && 1160 floatsEqual(sy, sy1) && 1161 floatsEqual(sw, (sx2 - sx1)) && 1162 floatsEqual(sh, (sy2 - sy1))); 1163 1164 if (renderer_copy_begin(ctx, surf, VG_TRUE, src)) { 1165 renderer_copy(ctx, x, y, w, h, sx, sy, sw, sh); 1166 renderer_copy_end(ctx); 1167 } 1168 1169 pipe_surface_reference(&surf, NULL); 1170} 1171 1172void renderer_copy_surface(struct renderer *ctx, 1173 struct pipe_surface *src, 1174 int srcX0, int srcY0, 1175 int srcX1, int srcY1, 1176 struct pipe_surface *dst, 1177 int dstX0, int dstY0, 1178 int dstX1, int dstY1, 1179 float z, unsigned filter) 1180{ 1181 struct pipe_context *pipe = ctx->pipe; 1182 struct pipe_screen *screen = pipe->screen; 1183 struct pipe_sampler_view view_templ; 1184 struct pipe_sampler_view *view; 1185 struct pipe_resource texTemp, *tex; 1186 struct pipe_subresource subsrc, subdst; 1187 struct st_framebuffer *stfb = ctx->owner->draw_buffer; 1188 const int srcW = abs(srcX1 - srcX0); 1189 const int srcH = abs(srcY1 - srcY0); 1190 const int srcLeft = MIN2(srcX0, srcX1); 1191 const int srcTop = MIN2(srcY0, srcY1); 1192 1193 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 1194 filter == PIPE_TEX_MIPFILTER_LINEAR); 1195 1196 if (srcLeft != srcX0) { 1197 /* left-right flip */ 1198 int tmp = dstX0; 1199 dstX0 = dstX1; 1200 dstX1 = tmp; 1201 } 1202 1203 if (srcTop != srcY0) { 1204 /* up-down flip */ 1205 int tmp = dstY0; 1206 dstY0 = dstY1; 1207 dstY1 = tmp; 1208 } 1209 1210 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 1211 0, PIPE_BIND_SAMPLER_VIEW, 0)); 1212 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 1213 0, PIPE_BIND_SAMPLER_VIEW, 0)); 1214 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 1215 0, PIPE_BIND_RENDER_TARGET, 0)); 1216 1217 /* 1218 * XXX for now we're always creating a temporary texture. 1219 * Strictly speaking that's not always needed. 1220 */ 1221 1222 /* create temp texture */ 1223 memset(&texTemp, 0, sizeof(texTemp)); 1224 texTemp.target = PIPE_TEXTURE_2D; 1225 texTemp.format = src->format; 1226 texTemp.last_level = 0; 1227 texTemp.width0 = srcW; 1228 texTemp.height0 = srcH; 1229 texTemp.depth0 = 1; 1230 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 1231 1232 tex = screen->resource_create(screen, &texTemp); 1233 if (!tex) 1234 return; 1235 1236 u_sampler_view_default_template(&view_templ, tex, tex->format); 1237 view = pipe->create_sampler_view(pipe, tex, &view_templ); 1238 1239 if (!view) 1240 return; 1241 1242 subdst.face = 0; 1243 subdst.level = 0; 1244 subsrc.face = src->face; 1245 subsrc.level = src->level; 1246 1247 pipe->resource_copy_region(pipe, 1248 tex, subdst, 0, 0, 0, /* dest */ 1249 src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */ 1250 srcW, srcH); /* size */ 1251 1252 assert(floatsEqual(z, 0.0f)); 1253 1254 /* draw */ 1255 if (stfb->strb->surface == dst) { 1256 /* transform back to surface coordinates */ 1257 dstY0 = dst->height - dstY0; 1258 dstY1 = dst->height - dstY1; 1259 1260 if (renderer_drawtex_begin(ctx, view)) { 1261 renderer_drawtex(ctx, 1262 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 1263 0, 0, view->texture->width0, view->texture->height0); 1264 renderer_drawtex_end(ctx); 1265 } 1266 } 1267 else { 1268 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) { 1269 renderer_copy(ctx, 1270 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 1271 0, 0, view->texture->width0, view->texture->height0); 1272 renderer_copy_end(ctx); 1273 } 1274 } 1275} 1276 1277void renderer_texture_quad(struct renderer *r, 1278 struct pipe_resource *tex, 1279 VGfloat x1offset, VGfloat y1offset, 1280 VGfloat x2offset, VGfloat y2offset, 1281 VGfloat x1, VGfloat y1, 1282 VGfloat x2, VGfloat y2, 1283 VGfloat x3, VGfloat y3, 1284 VGfloat x4, VGfloat y4) 1285{ 1286 const VGfloat z = 0.0f; 1287 1288 assert(r->state == RENDERER_STATE_INIT); 1289 assert(tex->width0 != 0); 1290 assert(tex->height0 != 0); 1291 1292 cso_save_vertex_shader(r->cso); 1293 1294 renderer_set_vs(r, RENDERER_VS_TEXTURE); 1295 1296 /* manually set up positions */ 1297 r->vertices[0][0][0] = x1; 1298 r->vertices[0][0][1] = y1; 1299 r->vertices[0][0][2] = z; 1300 1301 r->vertices[1][0][0] = x2; 1302 r->vertices[1][0][1] = y2; 1303 r->vertices[1][0][2] = z; 1304 1305 r->vertices[2][0][0] = x3; 1306 r->vertices[2][0][1] = y3; 1307 r->vertices[2][0][2] = z; 1308 1309 r->vertices[3][0][0] = x4; 1310 r->vertices[3][0][1] = y4; 1311 r->vertices[3][0][2] = z; 1312 1313 /* texcoords */ 1314 renderer_quad_texcoord(r, x1offset, y1offset, 1315 x2offset, y2offset, tex->width0, tex->height0); 1316 1317 renderer_quad_draw(r); 1318 1319 cso_restore_vertex_shader(r->cso); 1320} 1321