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