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