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