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