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