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