renderer.c revision dc4c821f0817a3db716f965692fb701079f66340
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); 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 PIPE_USAGE_STATIC, 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, PIPE_USAGE_STATIC, 478 const_buffer_len); 479 pipe_buffer_write(renderer->pipe, cbuf, 0, 480 const_buffer_len, const_buffer); 481 renderer->pipe->set_constant_buffer(renderer->pipe, 482 PIPE_SHADER_FRAGMENT, 0, cbuf); 483 484 renderer->fs_cbuf = cbuf; 485 if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) { 486 memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len); 487 renderer->fs_cbuf_len = const_buffer_len; 488 } 489 else { 490 renderer->fs_cbuf_len = 0; 491 } 492 } 493 } 494} 495 496/** 497 * Setup renderer quad position. 498 */ 499static void renderer_quad_pos(struct renderer *r, 500 VGfloat x0, VGfloat y0, 501 VGfloat x1, VGfloat y1, 502 VGboolean scissor) 503{ 504 VGfloat z; 505 506 /* the depth test is used for scissoring */ 507 z = (scissor) ? 0.0f : 1.0f; 508 509 /* positions */ 510 r->vertices[0][0][0] = x0; 511 r->vertices[0][0][1] = y0; 512 r->vertices[0][0][2] = z; 513 514 r->vertices[1][0][0] = x1; 515 r->vertices[1][0][1] = y0; 516 r->vertices[1][0][2] = z; 517 518 r->vertices[2][0][0] = x1; 519 r->vertices[2][0][1] = y1; 520 r->vertices[2][0][2] = z; 521 522 r->vertices[3][0][0] = x0; 523 r->vertices[3][0][1] = y1; 524 r->vertices[3][0][2] = z; 525} 526 527/** 528 * Setup renderer quad texture coordinates. 529 */ 530static void renderer_quad_texcoord(struct renderer *r, 531 VGfloat x0, VGfloat y0, 532 VGfloat x1, VGfloat y1, 533 VGint tex_width, VGint tex_height) 534{ 535 VGfloat s0, t0, s1, t1, r0, q0; 536 VGint i; 537 538 s0 = x0 / tex_width; 539 s1 = x1 / tex_width; 540 t0 = y0 / tex_height; 541 t1 = y1 / tex_height; 542 r0 = 0.0f; 543 q0 = 1.0f; 544 545 /* texcoords */ 546 r->vertices[0][1][0] = s0; 547 r->vertices[0][1][1] = t0; 548 549 r->vertices[1][1][0] = s1; 550 r->vertices[1][1][1] = t0; 551 552 r->vertices[2][1][0] = s1; 553 r->vertices[2][1][1] = t1; 554 555 r->vertices[3][1][0] = s0; 556 r->vertices[3][1][1] = t1; 557 558 for (i = 0; i < 4; i++) { 559 r->vertices[i][1][2] = r0; 560 r->vertices[i][1][3] = q0; 561 } 562} 563 564/** 565 * Draw renderer quad. 566 */ 567static void renderer_quad_draw(struct renderer *r) 568{ 569 struct pipe_resource *buf; 570 571 buf = pipe_user_buffer_create(r->pipe->screen, 572 r->vertices, 573 sizeof(r->vertices), 574 PIPE_BIND_VERTEX_BUFFER); 575 if (buf) { 576 util_draw_vertex_buffer(r->pipe, r->cso, buf, 0, 577 PIPE_PRIM_TRIANGLE_FAN, 578 Elements(r->vertices), /* verts */ 579 Elements(r->vertices[0])); /* attribs/vert */ 580 581 pipe_resource_reference(&buf, NULL); 582 } 583} 584 585/** 586 * Prepare the renderer for copying. 587 */ 588VGboolean renderer_copy_begin(struct renderer *renderer, 589 struct pipe_surface *dst, 590 VGboolean y0_top, 591 struct pipe_sampler_view *src) 592{ 593 assert(renderer->state == RENDERER_STATE_INIT); 594 595 /* sanity check */ 596 if (!renderer_can_support(renderer, 597 dst->texture, PIPE_BIND_RENDER_TARGET) || 598 !renderer_can_support(renderer, 599 src->texture, PIPE_BIND_SAMPLER_VIEW)) 600 return VG_FALSE; 601 602 cso_save_framebuffer(renderer->cso); 603 cso_save_viewport(renderer->cso); 604 cso_save_blend(renderer->cso); 605 cso_save_samplers(renderer->cso); 606 cso_save_fragment_sampler_views(renderer->cso); 607 cso_save_fragment_shader(renderer->cso); 608 cso_save_vertex_shader(renderer->cso); 609 610 renderer_set_target(renderer, dst, NULL, y0_top); 611 612 renderer_set_blend(renderer, ~0); 613 renderer_set_samplers(renderer, 1, &src); 614 615 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 616 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 617 618 renderer_set_mvp(renderer, NULL); 619 620 /* remember the texture size */ 621 renderer->u.copy.tex_width = src->texture->width0; 622 renderer->u.copy.tex_height = src->texture->height0; 623 renderer->state = RENDERER_STATE_COPY; 624 625 return VG_TRUE; 626} 627 628/** 629 * Draw into the destination rectangle given by (x, y, w, h). The texture is 630 * sampled from within the rectangle given by (sx, sy, sw, sh). 631 * 632 * The coordinates are in surface coordinates. 633 */ 634void renderer_copy(struct renderer *renderer, 635 VGint x, VGint y, VGint w, VGint h, 636 VGint sx, VGint sy, VGint sw, VGint sh) 637{ 638 assert(renderer->state == RENDERER_STATE_COPY); 639 640 /* there is no depth buffer for scissoring anyway */ 641 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); 642 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 643 renderer->u.copy.tex_width, 644 renderer->u.copy.tex_height); 645 646 renderer_quad_draw(renderer); 647} 648 649/** 650 * End copying and restore the states. 651 */ 652void renderer_copy_end(struct renderer *renderer) 653{ 654 assert(renderer->state == RENDERER_STATE_COPY); 655 656 cso_restore_framebuffer(renderer->cso); 657 cso_restore_viewport(renderer->cso); 658 cso_restore_blend(renderer->cso); 659 cso_restore_samplers(renderer->cso); 660 cso_restore_fragment_sampler_views(renderer->cso); 661 cso_restore_fragment_shader(renderer->cso); 662 cso_restore_vertex_shader(renderer->cso); 663 664 renderer->state = RENDERER_STATE_INIT; 665} 666 667/** 668 * Prepare the renderer for textured drawing. 669 */ 670VGboolean renderer_drawtex_begin(struct renderer *renderer, 671 struct pipe_sampler_view *src) 672{ 673 assert(renderer->state == RENDERER_STATE_INIT); 674 675 if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW)) 676 return VG_FALSE; 677 678 cso_save_blend(renderer->cso); 679 cso_save_samplers(renderer->cso); 680 cso_save_fragment_sampler_views(renderer->cso); 681 cso_save_fragment_shader(renderer->cso); 682 cso_save_vertex_shader(renderer->cso); 683 684 renderer_set_blend(renderer, ~0); 685 686 renderer_set_samplers(renderer, 1, &src); 687 688 renderer_set_fs(renderer, RENDERER_FS_TEXTURE); 689 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 690 691 renderer_set_mvp(renderer, NULL); 692 693 /* remember the texture size */ 694 renderer->u.drawtex.tex_width = src->texture->width0; 695 renderer->u.drawtex.tex_height = src->texture->height0; 696 renderer->state = RENDERER_STATE_DRAWTEX; 697 698 return VG_TRUE; 699} 700 701/** 702 * Draw into the destination rectangle given by (x, y, w, h). The texture is 703 * sampled from within the rectangle given by (sx, sy, sw, sh). 704 * 705 * The coordinates are in surface coordinates. 706 */ 707void renderer_drawtex(struct renderer *renderer, 708 VGint x, VGint y, VGint w, VGint h, 709 VGint sx, VGint sy, VGint sw, VGint sh) 710{ 711 assert(renderer->state == RENDERER_STATE_DRAWTEX); 712 713 /* with scissoring */ 714 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE); 715 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 716 renderer->u.drawtex.tex_width, 717 renderer->u.drawtex.tex_height); 718 719 renderer_quad_draw(renderer); 720} 721 722/** 723 * End textured drawing and restore the states. 724 */ 725void renderer_drawtex_end(struct renderer *renderer) 726{ 727 assert(renderer->state == RENDERER_STATE_DRAWTEX); 728 729 cso_restore_blend(renderer->cso); 730 cso_restore_samplers(renderer->cso); 731 cso_restore_fragment_sampler_views(renderer->cso); 732 cso_restore_fragment_shader(renderer->cso); 733 cso_restore_vertex_shader(renderer->cso); 734 735 renderer->state = RENDERER_STATE_INIT; 736} 737 738/** 739 * Prepare the renderer for scissor update. This will reset the depth buffer 740 * to 1.0f. 741 */ 742VGboolean renderer_scissor_begin(struct renderer *renderer, 743 VGboolean restore_dsa) 744{ 745 struct pipe_depth_stencil_alpha_state dsa; 746 747 assert(renderer->state == RENDERER_STATE_INIT); 748 749 if (restore_dsa) 750 cso_save_depth_stencil_alpha(renderer->cso); 751 cso_save_blend(renderer->cso); 752 cso_save_fragment_shader(renderer->cso); 753 754 /* enable depth writes */ 755 memset(&dsa, 0, sizeof(dsa)); 756 dsa.depth.enabled = 1; 757 dsa.depth.writemask = 1; 758 dsa.depth.func = PIPE_FUNC_ALWAYS; 759 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 760 761 /* disable color writes */ 762 renderer_set_blend(renderer, 0); 763 renderer_set_fs(renderer, RENDERER_FS_SCISSOR); 764 765 renderer_set_mvp(renderer, NULL); 766 767 renderer->u.scissor.restore_dsa = restore_dsa; 768 renderer->state = RENDERER_STATE_SCISSOR; 769 770 /* clear the depth buffer to 1.0f */ 771 renderer->pipe->clear(renderer->pipe, 772 PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0); 773 774 return VG_TRUE; 775} 776 777/** 778 * Add a scissor rectangle. Depth values inside the rectangle will be set to 779 * 0.0f. 780 */ 781void renderer_scissor(struct renderer *renderer, 782 VGint x, VGint y, VGint width, VGint height) 783{ 784 assert(renderer->state == RENDERER_STATE_SCISSOR); 785 786 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE); 787 renderer_quad_draw(renderer); 788} 789 790/** 791 * End scissor update and restore the states. 792 */ 793void renderer_scissor_end(struct renderer *renderer) 794{ 795 assert(renderer->state == RENDERER_STATE_SCISSOR); 796 797 if (renderer->u.scissor.restore_dsa) 798 cso_restore_depth_stencil_alpha(renderer->cso); 799 cso_restore_blend(renderer->cso); 800 cso_restore_fragment_shader(renderer->cso); 801 802 renderer->state = RENDERER_STATE_INIT; 803} 804 805/** 806 * Prepare the renderer for clearing. 807 */ 808VGboolean renderer_clear_begin(struct renderer *renderer) 809{ 810 assert(renderer->state == RENDERER_STATE_INIT); 811 812 cso_save_blend(renderer->cso); 813 cso_save_fragment_shader(renderer->cso); 814 cso_save_vertex_shader(renderer->cso); 815 816 renderer_set_blend(renderer, ~0); 817 renderer_set_fs(renderer, RENDERER_FS_COLOR); 818 renderer_set_vs(renderer, RENDERER_VS_COLOR); 819 820 renderer_set_mvp(renderer, NULL); 821 822 renderer->state = RENDERER_STATE_CLEAR; 823 824 return VG_TRUE; 825} 826 827/** 828 * Clear the framebuffer with the specified region and color. 829 * 830 * The coordinates are in surface coordinates. 831 */ 832void renderer_clear(struct renderer *renderer, 833 VGint x, VGint y, VGint width, VGint height, 834 const VGfloat color[4]) 835{ 836 VGuint i; 837 838 assert(renderer->state == RENDERER_STATE_CLEAR); 839 840 renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE); 841 for (i = 0; i < 4; i++) 842 memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4); 843 844 renderer_quad_draw(renderer); 845} 846 847/** 848 * End clearing and retore the states. 849 */ 850void renderer_clear_end(struct renderer *renderer) 851{ 852 assert(renderer->state == RENDERER_STATE_CLEAR); 853 854 cso_restore_blend(renderer->cso); 855 cso_restore_fragment_shader(renderer->cso); 856 cso_restore_vertex_shader(renderer->cso); 857 858 renderer->state = RENDERER_STATE_INIT; 859} 860 861/** 862 * Prepare the renderer for image filtering. 863 */ 864VGboolean renderer_filter_begin(struct renderer *renderer, 865 struct pipe_resource *dst, 866 VGboolean y0_top, 867 VGbitfield channel_mask, 868 const struct pipe_sampler_state **samplers, 869 struct pipe_sampler_view **views, 870 VGint num_samplers, 871 void *fs, 872 const void *const_buffer, 873 VGint const_buffer_len) 874{ 875 struct pipe_surface *surf, surf_tmpl; 876 877 assert(renderer->state == RENDERER_STATE_INIT); 878 879 if (!fs) 880 return VG_FALSE; 881 if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET)) 882 return VG_FALSE; 883 884 u_surface_default_template(&surf_tmpl, dst, 885 PIPE_BIND_RENDER_TARGET); 886 surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl); 887 if (!surf) 888 return VG_FALSE; 889 890 cso_save_framebuffer(renderer->cso); 891 cso_save_viewport(renderer->cso); 892 cso_save_blend(renderer->cso); 893 894 /* set the image as the target */ 895 renderer_set_target(renderer, surf, NULL, y0_top); 896 pipe_surface_reference(&surf, NULL); 897 898 renderer_set_blend(renderer, channel_mask); 899 900 if (num_samplers) { 901 struct pipe_resource *tex; 902 903 cso_save_samplers(renderer->cso); 904 cso_save_fragment_sampler_views(renderer->cso); 905 cso_save_fragment_shader(renderer->cso); 906 cso_save_vertex_shader(renderer->cso); 907 908 renderer_set_custom_fs(renderer, fs, 909 samplers, views, num_samplers, 910 const_buffer, const_buffer_len); 911 renderer_set_vs(renderer, RENDERER_VS_TEXTURE); 912 913 tex = views[0]->texture; 914 renderer->u.filter.tex_width = tex->width0; 915 renderer->u.filter.tex_height = tex->height0; 916 renderer->u.filter.use_sampler = VG_TRUE; 917 } 918 else { 919 cso_save_fragment_shader(renderer->cso); 920 921 renderer_set_custom_fs(renderer, fs, NULL, NULL, 0, 922 const_buffer, const_buffer_len); 923 924 renderer->u.filter.use_sampler = VG_FALSE; 925 } 926 927 renderer_set_mvp(renderer, NULL); 928 929 renderer->state = RENDERER_STATE_FILTER; 930 931 return VG_TRUE; 932} 933 934/** 935 * Draw into a rectangle of the destination with the specified region of the 936 * texture(s). 937 * 938 * The coordinates are in surface coordinates. 939 */ 940void renderer_filter(struct renderer *renderer, 941 VGint x, VGint y, VGint w, VGint h, 942 VGint sx, VGint sy, VGint sw, VGint sh) 943{ 944 assert(renderer->state == RENDERER_STATE_FILTER); 945 946 renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE); 947 if (renderer->u.filter.use_sampler) { 948 renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh, 949 renderer->u.filter.tex_width, 950 renderer->u.filter.tex_height); 951 } 952 953 renderer_quad_draw(renderer); 954} 955 956/** 957 * End image filtering and restore the states. 958 */ 959void renderer_filter_end(struct renderer *renderer) 960{ 961 assert(renderer->state == RENDERER_STATE_FILTER); 962 963 if (renderer->u.filter.use_sampler) { 964 cso_restore_samplers(renderer->cso); 965 cso_restore_fragment_sampler_views(renderer->cso); 966 cso_restore_vertex_shader(renderer->cso); 967 } 968 969 cso_restore_framebuffer(renderer->cso); 970 cso_restore_viewport(renderer->cso); 971 cso_restore_blend(renderer->cso); 972 cso_restore_fragment_shader(renderer->cso); 973 974 renderer->state = RENDERER_STATE_INIT; 975} 976 977/** 978 * Prepare the renderer for polygon silhouette rendering. 979 */ 980VGboolean renderer_polygon_stencil_begin(struct renderer *renderer, 981 struct pipe_vertex_element *velem, 982 VGFillRule rule, 983 VGboolean restore_dsa) 984{ 985 struct pipe_depth_stencil_alpha_state *dsa; 986 VGboolean manual_two_sides; 987 988 assert(renderer->state == RENDERER_STATE_INIT); 989 990 cso_save_vertex_elements(renderer->cso); 991 cso_save_blend(renderer->cso); 992 cso_save_depth_stencil_alpha(renderer->cso); 993 994 cso_set_vertex_elements(renderer->cso, 1, velem); 995 996 /* disable color writes */ 997 renderer_set_blend(renderer, 0); 998 999 manual_two_sides = VG_FALSE; 1000 dsa = &renderer->u.polygon_stencil.dsa; 1001 memset(dsa, 0, sizeof(*dsa)); 1002 if (rule == VG_EVEN_ODD) { 1003 dsa->stencil[0].enabled = 1; 1004 dsa->stencil[0].writemask = 1; 1005 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; 1006 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; 1007 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; 1008 dsa->stencil[0].func = PIPE_FUNC_ALWAYS; 1009 dsa->stencil[0].valuemask = ~0; 1010 } 1011 else { 1012 assert(rule == VG_NON_ZERO); 1013 1014 /* front face */ 1015 dsa->stencil[0].enabled = 1; 1016 dsa->stencil[0].writemask = ~0; 1017 dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; 1018 dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; 1019 dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; 1020 dsa->stencil[0].func = PIPE_FUNC_ALWAYS; 1021 dsa->stencil[0].valuemask = ~0; 1022 1023 if (renderer->pipe->screen->get_param(renderer->pipe->screen, 1024 PIPE_CAP_TWO_SIDED_STENCIL)) { 1025 /* back face */ 1026 dsa->stencil[1] = dsa->stencil[0]; 1027 dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; 1028 } 1029 else { 1030 manual_two_sides = VG_TRUE; 1031 } 1032 } 1033 cso_set_depth_stencil_alpha(renderer->cso, dsa); 1034 1035 if (manual_two_sides) 1036 cso_save_rasterizer(renderer->cso); 1037 1038 renderer->u.polygon_stencil.manual_two_sides = manual_two_sides; 1039 renderer->u.polygon_stencil.restore_dsa = restore_dsa; 1040 renderer->state = RENDERER_STATE_POLYGON_STENCIL; 1041 1042 return VG_TRUE; 1043} 1044 1045/** 1046 * Render a polygon silhouette to stencil buffer. 1047 */ 1048void renderer_polygon_stencil(struct renderer *renderer, 1049 struct pipe_vertex_buffer *vbuf, 1050 VGuint mode, VGuint start, VGuint count) 1051{ 1052 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); 1053 1054 cso_set_vertex_buffers(renderer->cso, 1, vbuf); 1055 1056 if (!renderer->u.polygon_stencil.manual_two_sides) { 1057 util_draw_arrays(renderer->pipe, mode, start, count); 1058 } 1059 else { 1060 struct pipe_rasterizer_state raster; 1061 struct pipe_depth_stencil_alpha_state dsa; 1062 1063 raster = renderer->g3d.rasterizer; 1064 dsa = renderer->u.polygon_stencil.dsa; 1065 1066 /* front */ 1067 raster.cull_face = PIPE_FACE_BACK; 1068 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; 1069 1070 cso_set_rasterizer(renderer->cso, &raster); 1071 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 1072 util_draw_arrays(renderer->pipe, mode, start, count); 1073 1074 /* back */ 1075 raster.cull_face = PIPE_FACE_FRONT; 1076 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; 1077 1078 cso_set_rasterizer(renderer->cso, &raster); 1079 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 1080 util_draw_arrays(renderer->pipe, mode, start, count); 1081 } 1082} 1083 1084/** 1085 * End polygon silhouette rendering. 1086 */ 1087void renderer_polygon_stencil_end(struct renderer *renderer) 1088{ 1089 assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL); 1090 1091 if (renderer->u.polygon_stencil.manual_two_sides) 1092 cso_restore_rasterizer(renderer->cso); 1093 1094 cso_restore_vertex_elements(renderer->cso); 1095 1096 /* restore color writes */ 1097 cso_restore_blend(renderer->cso); 1098 1099 if (renderer->u.polygon_stencil.restore_dsa) 1100 cso_restore_depth_stencil_alpha(renderer->cso); 1101 1102 renderer->state = RENDERER_STATE_INIT; 1103} 1104 1105/** 1106 * Prepare the renderer for polygon filling. 1107 */ 1108VGboolean renderer_polygon_fill_begin(struct renderer *renderer, 1109 VGboolean save_dsa) 1110{ 1111 struct pipe_depth_stencil_alpha_state dsa; 1112 1113 assert(renderer->state == RENDERER_STATE_INIT); 1114 1115 if (save_dsa) 1116 cso_save_depth_stencil_alpha(renderer->cso); 1117 1118 /* setup stencil ops */ 1119 memset(&dsa, 0, sizeof(dsa)); 1120 dsa.stencil[0].enabled = 1; 1121 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; 1122 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; 1123 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; 1124 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; 1125 dsa.stencil[0].valuemask = ~0; 1126 dsa.stencil[0].writemask = ~0; 1127 dsa.depth = renderer->g3d.dsa.depth; 1128 cso_set_depth_stencil_alpha(renderer->cso, &dsa); 1129 1130 renderer->state = RENDERER_STATE_POLYGON_FILL; 1131 1132 return VG_TRUE; 1133} 1134 1135/** 1136 * Fill a polygon. 1137 */ 1138void renderer_polygon_fill(struct renderer *renderer, 1139 VGfloat min_x, VGfloat min_y, 1140 VGfloat max_x, VGfloat max_y) 1141{ 1142 assert(renderer->state == RENDERER_STATE_POLYGON_FILL); 1143 1144 renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE); 1145 renderer_quad_draw(renderer); 1146} 1147 1148/** 1149 * End polygon filling. 1150 */ 1151void renderer_polygon_fill_end(struct renderer *renderer) 1152{ 1153 assert(renderer->state == RENDERER_STATE_POLYGON_FILL); 1154 1155 cso_restore_depth_stencil_alpha(renderer->cso); 1156 1157 renderer->state = RENDERER_STATE_INIT; 1158} 1159 1160struct renderer * renderer_create(struct vg_context *owner) 1161{ 1162 struct renderer *renderer; 1163 struct pipe_rasterizer_state *raster; 1164 struct pipe_stencil_ref sr; 1165 VGint i; 1166 1167 renderer = CALLOC_STRUCT(renderer); 1168 if (!renderer) 1169 return NULL; 1170 1171 renderer->pipe = owner->pipe; 1172 renderer->cso = owner->cso_context; 1173 1174 /* init vertex data that doesn't change */ 1175 for (i = 0; i < 4; i++) 1176 renderer->vertices[i][0][3] = 1.0f; /* w */ 1177 1178 for (i = 0; i < 2; i++) { 1179 renderer->velems[i].src_offset = i * 4 * sizeof(float); 1180 renderer->velems[i].instance_divisor = 0; 1181 renderer->velems[i].vertex_buffer_index = 0; 1182 renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 1183 } 1184 cso_set_vertex_elements(renderer->cso, 2, renderer->velems); 1185 1186 /* GL rasterization rules */ 1187 raster = &renderer->g3d.rasterizer; 1188 memset(raster, 0, sizeof(*raster)); 1189 raster->gl_rasterization_rules = 1; 1190 raster->depth_clip = 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 /* use the blend state only when there is no alpha channel */ 1296 if (!util_format_has_alpha(fb_format)) { 1297 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 1298 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 1299 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 1300 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 1301 blend.rt[0].blend_enable = 1; 1302 } 1303 break; 1304 case VG_BLEND_SRC_IN: 1305 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 1306 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 1307 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 1308 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 1309 blend.rt[0].blend_enable = 1; 1310 break; 1311 case VG_BLEND_DST_IN: 1312 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; 1313 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 1314 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 1315 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 1316 blend.rt[0].blend_enable = 1; 1317 break; 1318 case VG_BLEND_DST_OVER: 1319 case VG_BLEND_MULTIPLY: 1320 case VG_BLEND_SCREEN: 1321 case VG_BLEND_DARKEN: 1322 case VG_BLEND_LIGHTEN: 1323 case VG_BLEND_ADDITIVE: 1324 /* need a shader */ 1325 break; 1326 default: 1327 assert(!"not implemented blend mode"); 1328 break; 1329 } 1330 1331 cso_set_blend(renderer->cso, &blend); 1332} 1333 1334/** 1335 * Propogate OpenVG state changes to the renderer. Only framebuffer, blending 1336 * and scissoring states are relevant here. 1337 */ 1338void renderer_validate(struct renderer *renderer, 1339 VGbitfield dirty, 1340 const struct st_framebuffer *stfb, 1341 const struct vg_state *state) 1342{ 1343 assert(renderer->state == RENDERER_STATE_INIT); 1344 1345 dirty |= renderer->dirty; 1346 renderer->dirty = 0; 1347 1348 if (dirty & FRAMEBUFFER_DIRTY) { 1349 struct pipe_framebuffer_state *fb = &renderer->g3d.fb; 1350 struct matrix *proj = &renderer->projection; 1351 1352 memset(fb, 0, sizeof(struct pipe_framebuffer_state)); 1353 fb->width = stfb->width; 1354 fb->height = stfb->height; 1355 fb->nr_cbufs = 1; 1356 fb->cbufs[0] = stfb->strb->surface; 1357 fb->zsbuf = stfb->dsrb->surface; 1358 1359 cso_set_framebuffer(renderer->cso, fb); 1360 vg_set_viewport(renderer, VEGA_Y0_BOTTOM); 1361 1362 matrix_load_identity(proj); 1363 matrix_translate(proj, -1.0f, -1.0f); 1364 matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height); 1365 1366 /* we also got a new depth buffer */ 1367 if (dirty & DEPTH_STENCIL_DIRTY) { 1368 renderer->pipe->clear(renderer->pipe, 1369 PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); 1370 } 1371 } 1372 1373 /* must be last because it renders to the depth buffer*/ 1374 if (dirty & DEPTH_STENCIL_DIRTY) { 1375 update_clip_state(renderer, state); 1376 cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa); 1377 } 1378 1379 if (dirty & BLEND_DIRTY) 1380 renderer_validate_blend(renderer, state, stfb->strb->format); 1381} 1382 1383/** 1384 * Prepare the renderer for OpenVG pipeline. 1385 */ 1386void renderer_validate_for_shader(struct renderer *renderer, 1387 const struct pipe_sampler_state **samplers, 1388 struct pipe_sampler_view **views, 1389 VGint num_samplers, 1390 const struct matrix *modelview, 1391 void *fs, 1392 const void *const_buffer, 1393 VGint const_buffer_len) 1394{ 1395 struct matrix mvp = renderer->projection; 1396 1397 /* will be used in POLYGON_STENCIL and POLYGON_FILL */ 1398 matrix_mult(&mvp, modelview); 1399 renderer_set_mvp(renderer, &mvp); 1400 1401 renderer_set_custom_fs(renderer, fs, 1402 samplers, views, num_samplers, 1403 const_buffer, const_buffer_len); 1404} 1405 1406void renderer_validate_for_mask_rendering(struct renderer *renderer, 1407 struct pipe_surface *dst, 1408 const struct matrix *modelview) 1409{ 1410 struct matrix mvp = renderer->projection; 1411 1412 /* will be used in POLYGON_STENCIL and POLYGON_FILL */ 1413 matrix_mult(&mvp, modelview); 1414 renderer_set_mvp(renderer, &mvp); 1415 1416 renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE); 1417 renderer_set_blend(renderer, ~0); 1418 renderer_set_fs(renderer, RENDERER_FS_WHITE); 1419 1420 /* set internal dirty flags (hacky!) */ 1421 renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY; 1422} 1423 1424void renderer_copy_surface(struct renderer *ctx, 1425 struct pipe_surface *src, 1426 int srcX0, int srcY0, 1427 int srcX1, int srcY1, 1428 struct pipe_surface *dst, 1429 int dstX0, int dstY0, 1430 int dstX1, int dstY1, 1431 float z, unsigned filter) 1432{ 1433 struct pipe_context *pipe = ctx->pipe; 1434 struct pipe_screen *screen = pipe->screen; 1435 struct pipe_sampler_view view_templ; 1436 struct pipe_sampler_view *view; 1437 struct pipe_box src_box; 1438 struct pipe_resource texTemp, *tex; 1439 const struct pipe_framebuffer_state *fb = &ctx->g3d.fb; 1440 const int srcW = abs(srcX1 - srcX0); 1441 const int srcH = abs(srcY1 - srcY0); 1442 const int srcLeft = MIN2(srcX0, srcX1); 1443 const int srcTop = MIN2(srcY0, srcY1); 1444 1445 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 1446 filter == PIPE_TEX_MIPFILTER_LINEAR); 1447 1448 if (srcLeft != srcX0) { 1449 /* left-right flip */ 1450 int tmp = dstX0; 1451 dstX0 = dstX1; 1452 dstX1 = tmp; 1453 } 1454 1455 if (srcTop != srcY0) { 1456 /* up-down flip */ 1457 int tmp = dstY0; 1458 dstY0 = dstY1; 1459 dstY1 = tmp; 1460 } 1461 1462 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 1463 0, PIPE_BIND_SAMPLER_VIEW)); 1464 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 1465 0, PIPE_BIND_SAMPLER_VIEW)); 1466 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 1467 0, PIPE_BIND_RENDER_TARGET)); 1468 1469 /* 1470 * XXX for now we're always creating a temporary texture. 1471 * Strictly speaking that's not always needed. 1472 */ 1473 1474 /* create temp texture */ 1475 memset(&texTemp, 0, sizeof(texTemp)); 1476 texTemp.target = PIPE_TEXTURE_2D; 1477 texTemp.format = src->format; 1478 texTemp.last_level = 0; 1479 texTemp.width0 = srcW; 1480 texTemp.height0 = srcH; 1481 texTemp.depth0 = 1; 1482 texTemp.array_size = 1; 1483 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 1484 1485 tex = screen->resource_create(screen, &texTemp); 1486 if (!tex) 1487 return; 1488 1489 u_sampler_view_default_template(&view_templ, tex, tex->format); 1490 view = pipe->create_sampler_view(pipe, tex, &view_templ); 1491 1492 if (!view) 1493 return; 1494 1495 u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box); 1496 1497 pipe->resource_copy_region(pipe, 1498 tex, 0, 0, 0, 0, /* dest */ 1499 src->texture, 0, &src_box); 1500 1501 assert(floatsEqual(z, 0.0f)); 1502 1503 /* draw */ 1504 if (fb->cbufs[0] == dst) { 1505 /* transform back to surface coordinates */ 1506 dstY0 = dst->height - dstY0; 1507 dstY1 = dst->height - dstY1; 1508 1509 if (renderer_drawtex_begin(ctx, view)) { 1510 renderer_drawtex(ctx, 1511 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 1512 0, 0, view->texture->width0, view->texture->height0); 1513 renderer_drawtex_end(ctx); 1514 } 1515 } 1516 else { 1517 if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) { 1518 renderer_copy(ctx, 1519 dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0, 1520 0, 0, view->texture->width0, view->texture->height0); 1521 renderer_copy_end(ctx); 1522 } 1523 } 1524} 1525 1526void renderer_texture_quad(struct renderer *r, 1527 struct pipe_resource *tex, 1528 VGfloat x1offset, VGfloat y1offset, 1529 VGfloat x2offset, VGfloat y2offset, 1530 VGfloat x1, VGfloat y1, 1531 VGfloat x2, VGfloat y2, 1532 VGfloat x3, VGfloat y3, 1533 VGfloat x4, VGfloat y4) 1534{ 1535 const VGfloat z = 0.0f; 1536 1537 assert(r->state == RENDERER_STATE_INIT); 1538 assert(tex->width0 != 0); 1539 assert(tex->height0 != 0); 1540 1541 cso_save_vertex_shader(r->cso); 1542 1543 renderer_set_vs(r, RENDERER_VS_TEXTURE); 1544 1545 /* manually set up positions */ 1546 r->vertices[0][0][0] = x1; 1547 r->vertices[0][0][1] = y1; 1548 r->vertices[0][0][2] = z; 1549 1550 r->vertices[1][0][0] = x2; 1551 r->vertices[1][0][1] = y2; 1552 r->vertices[1][0][2] = z; 1553 1554 r->vertices[2][0][0] = x3; 1555 r->vertices[2][0][1] = y3; 1556 r->vertices[2][0][2] = z; 1557 1558 r->vertices[3][0][0] = x4; 1559 r->vertices[3][0][1] = y4; 1560 r->vertices[3][0][2] = z; 1561 1562 /* texcoords */ 1563 renderer_quad_texcoord(r, x1offset, y1offset, 1564 x2offset, y2offset, tex->width0, tex->height0); 1565 1566 renderer_quad_draw(r); 1567 1568 cso_restore_vertex_shader(r->cso); 1569} 1570