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