mask.c revision f914cd1796845164109c837a111c39ba64852ad4
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "mask.h" 28 29#include "path.h" 30#include "image.h" 31#include "shaders_cache.h" 32#include "renderer.h" 33#include "asm_util.h" 34#include "st_inlines.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_screen.h" 38#include "util/u_inlines.h" 39#include "util/u_format.h" 40#include "util/u_memory.h" 41 42struct vg_mask_layer { 43 struct vg_object base; 44 45 VGint width; 46 VGint height; 47 48 struct pipe_sampler_view *sampler_view; 49}; 50 51static INLINE struct pipe_surface * 52alpha_mask_surface(struct vg_context *ctx, int usage) 53{ 54 struct pipe_screen *screen = ctx->pipe->screen; 55 struct st_framebuffer *stfb = ctx->draw_buffer; 56 return screen->get_tex_surface(screen, 57 stfb->alpha_mask_view->texture, 58 0, 0, 0, 59 usage); 60} 61 62static INLINE VGboolean 63intersect_rectangles(VGint dwidth, VGint dheight, 64 VGint swidth, VGint sheight, 65 VGint tx, VGint ty, 66 VGint twidth, VGint theight, 67 VGint *offsets, 68 VGint *location) 69{ 70 if (tx + twidth <= 0 || tx >= dwidth) 71 return VG_FALSE; 72 if (ty + theight <= 0 || ty >= dheight) 73 return VG_FALSE; 74 75 offsets[0] = 0; 76 offsets[1] = 0; 77 location[0] = tx; 78 location[1] = ty; 79 80 if (tx < 0) { 81 offsets[0] -= tx; 82 location[0] = 0; 83 84 location[2] = MIN2(tx + swidth, MIN2(dwidth, tx + twidth)); 85 offsets[2] = location[2]; 86 } else { 87 offsets[2] = MIN2(twidth, MIN2(dwidth - tx, swidth )); 88 location[2] = offsets[2]; 89 } 90 91 if (ty < 0) { 92 offsets[1] -= ty; 93 location[1] = 0; 94 95 location[3] = MIN2(ty + sheight, MIN2(dheight, ty + theight)); 96 offsets[3] = location[3]; 97 } else { 98 offsets[3] = MIN2(theight, MIN2(dheight - ty, sheight)); 99 location[3] = offsets[3]; 100 } 101 102 return VG_TRUE; 103} 104 105#if DEBUG_MASKS 106static void read_alpha_mask(void * data, VGint dataStride, 107 VGImageFormat dataFormat, 108 VGint sx, VGint sy, 109 VGint width, VGint height) 110{ 111 struct vg_context *ctx = vg_current_context(); 112 struct pipe_context *pipe = ctx->pipe; 113 struct pipe_screen *screen = pipe->screen; 114 115 struct st_framebuffer *stfb = ctx->draw_buffer; 116 struct st_renderbuffer *strb = stfb->alpha_mask; 117 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 118 119 VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; 120 VGfloat *df = (VGfloat*)temp; 121 VGint y = (fb->height - sy) - 1, yStep = -1; 122 VGint i; 123 VGubyte *dst = (VGubyte *)data; 124 VGint xoffset = 0, yoffset = 0; 125 126 /* make sure rendering has completed */ 127 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 128 if (sx < 0) { 129 xoffset = -sx; 130 xoffset *= _vega_size_for_format(dataFormat); 131 width += sx; 132 sx = 0; 133 } 134 if (sy < 0) { 135 yoffset = -sy; 136 height += sy; 137 sy = 0; 138 y = (fb->height - sy) - 1; 139 yoffset *= dataStride; 140 } 141 142 { 143 struct pipe_surface *surf; 144 145 surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, 146 PIPE_BIND_TRANSFER_READ); 147 148 /* Do a row at a time to flip image data vertically */ 149 for (i = 0; i < height; i++) { 150#if 0 151 debug_printf("%d-%d == %d\n", sy, height, y); 152#endif 153 pipe_get_tile_rgba(surf, sx, y, width, 1, df); 154 y += yStep; 155 _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, 156 dst + yoffset + xoffset); 157 dst += dataStride; 158 } 159 160 pipe_surface_reference(&surf, NULL); 161 } 162} 163 164void save_alpha_to_file(const char *filename) 165{ 166 struct vg_context *ctx = vg_current_context(); 167 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 168 VGint *data; 169 int i, j; 170 171 data = malloc(sizeof(int) * fb->width * fb->height); 172 read_alpha_mask(data, fb->width * sizeof(int), 173 VG_sRGBA_8888, 174 0, 0, fb->width, fb->height); 175 fprintf(stderr, "/*---------- start */\n"); 176 fprintf(stderr, "const int image_width = %d;\n", 177 fb->width); 178 fprintf(stderr, "const int image_height = %d;\n", 179 fb->height); 180 fprintf(stderr, "const int image_data = {\n"); 181 for (i = 0; i < fb->height; ++i) { 182 for (j = 0; j < fb->width; ++j) { 183 int rgba = data[i * fb->height + j]; 184 int argb = 0; 185 argb = (rgba >> 8); 186 argb |= ((rgba & 0xff) << 24); 187 fprintf(stderr, "0x%x, ", argb); 188 } 189 fprintf(stderr, "\n"); 190 } 191 fprintf(stderr, "};\n"); 192 fprintf(stderr, "/*---------- end */\n"); 193} 194#endif 195 196static void setup_mask_framebuffer(struct pipe_surface *surf, 197 VGint surf_width, VGint surf_height) 198{ 199 struct vg_context *ctx = vg_current_context(); 200 struct pipe_framebuffer_state fb; 201 202 memset(&fb, 0, sizeof(fb)); 203 fb.width = surf_width; 204 fb.height = surf_height; 205 fb.nr_cbufs = 1; 206 fb.cbufs[0] = surf; 207 { 208 VGint i; 209 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) 210 fb.cbufs[i] = 0; 211 } 212 cso_set_framebuffer(ctx->cso_context, &fb); 213} 214 215 216/* setup shader constants */ 217static void setup_mask_operation(VGMaskOperation operation) 218{ 219 struct vg_context *ctx = vg_current_context(); 220 struct pipe_resource **cbuf = &ctx->mask.cbuf; 221 const VGint param_bytes = 4 * sizeof(VGfloat); 222 const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f}; 223 void *shader = 0; 224 225 /* We always need to get a new buffer, to keep the drivers simple and 226 * avoid gratuitous rendering synchronization. 227 */ 228 pipe_resource_reference(cbuf, NULL); 229 230 *cbuf = pipe_buffer_create(ctx->pipe->screen, 231 PIPE_BIND_CONSTANT_BUFFER, 232 param_bytes); 233 if (*cbuf) { 234 st_no_flush_pipe_buffer_write(ctx, *cbuf, 235 0, param_bytes, ones); 236 } 237 238 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf); 239 switch (operation) { 240 case VG_UNION_MASK: { 241 if (!ctx->mask.union_fs) { 242 ctx->mask.union_fs = shader_create_from_text(ctx->pipe, 243 union_mask_asm, 244 200, 245 PIPE_SHADER_FRAGMENT); 246 } 247 shader = ctx->mask.union_fs->driver; 248 } 249 break; 250 case VG_INTERSECT_MASK: { 251 if (!ctx->mask.intersect_fs) { 252 ctx->mask.intersect_fs = shader_create_from_text(ctx->pipe, 253 intersect_mask_asm, 254 200, 255 PIPE_SHADER_FRAGMENT); 256 } 257 shader = ctx->mask.intersect_fs->driver; 258 } 259 break; 260 case VG_SUBTRACT_MASK: { 261 if (!ctx->mask.subtract_fs) { 262 ctx->mask.subtract_fs = shader_create_from_text(ctx->pipe, 263 subtract_mask_asm, 264 200, 265 PIPE_SHADER_FRAGMENT); 266 } 267 shader = ctx->mask.subtract_fs->driver; 268 } 269 break; 270 case VG_SET_MASK: { 271 if (!ctx->mask.set_fs) { 272 ctx->mask.set_fs = shader_create_from_text(ctx->pipe, 273 set_mask_asm, 274 200, 275 PIPE_SHADER_FRAGMENT); 276 } 277 shader = ctx->mask.set_fs->driver; 278 } 279 break; 280 default: 281 assert(0); 282 break; 283 } 284 cso_set_fragment_shader_handle(ctx->cso_context, shader); 285} 286 287static void setup_mask_samplers(struct pipe_sampler_view *umask) 288{ 289 struct vg_context *ctx = vg_current_context(); 290 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 291 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 292 struct st_framebuffer *fb_buffers = ctx->draw_buffer; 293 struct pipe_sampler_view *uprev = NULL; 294 struct pipe_sampler_state sampler; 295 296 uprev = fb_buffers->blend_texture_view; 297 sampler = ctx->mask.sampler; 298 sampler.normalized_coords = 1; 299 300 samplers[0] = NULL; 301 samplers[1] = NULL; 302 sampler_views[0] = NULL; 303 sampler_views[1] = NULL; 304 305 samplers[0] = &sampler; 306 samplers[1] = &ctx->mask.sampler; 307 308 sampler_views[0] = umask; 309 sampler_views[1] = uprev; 310 311 cso_set_samplers(ctx->cso_context, 2, 312 (const struct pipe_sampler_state **)samplers); 313 cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views); 314} 315 316 317/* setup shader constants */ 318static void setup_mask_fill(const VGfloat color[4]) 319{ 320 struct vg_context *ctx = vg_current_context(); 321 struct pipe_resource **cbuf = &ctx->mask.cbuf; 322 const VGint param_bytes = 4 * sizeof(VGfloat); 323 324 /* We always need to get a new buffer, to keep the drivers simple and 325 * avoid gratuitous rendering synchronization. 326 */ 327 pipe_resource_reference(cbuf, NULL); 328 329 *cbuf = pipe_buffer_create(ctx->pipe->screen, 330 PIPE_BIND_CONSTANT_BUFFER, 331 param_bytes); 332 if (*cbuf) { 333 st_no_flush_pipe_buffer_write(ctx, *cbuf, 0, param_bytes, color); 334 } 335 336 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf); 337 cso_set_fragment_shader_handle(ctx->cso_context, 338 shaders_cache_fill(ctx->sc, 339 VEGA_SOLID_FILL_SHADER)); 340} 341 342static void setup_mask_viewport() 343{ 344 struct vg_context *ctx = vg_current_context(); 345 vg_set_viewport(ctx, VEGA_Y0_TOP); 346} 347 348static void setup_mask_blend() 349{ 350 struct vg_context *ctx = vg_current_context(); 351 352 struct pipe_blend_state blend; 353 354 memset(&blend, 0, sizeof(struct pipe_blend_state)); 355 blend.rt[0].blend_enable = 0; 356 blend.rt[0].colormask = PIPE_MASK_RGBA; 357 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 358 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 359 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 360 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 361 362 cso_set_blend(ctx->cso_context, &blend); 363} 364 365 366static void surface_fill(struct pipe_surface *surf, 367 int surf_width, int surf_height, 368 int x, int y, int width, int height, 369 const VGfloat color[4]) 370{ 371 struct vg_context *ctx = vg_current_context(); 372 373 if (x < 0) { 374 width += x; 375 x = 0; 376 } 377 if (y < 0) { 378 height += y; 379 y = 0; 380 } 381 382 cso_save_framebuffer(ctx->cso_context); 383 cso_save_blend(ctx->cso_context); 384 cso_save_fragment_shader(ctx->cso_context); 385 cso_save_viewport(ctx->cso_context); 386 387 setup_mask_blend(); 388 setup_mask_fill(color); 389 setup_mask_framebuffer(surf, surf_width, surf_height); 390 setup_mask_viewport(); 391 392 renderer_draw_quad(ctx->renderer, x, y, 393 x + width, y + height, 0.0f/*depth should be disabled*/); 394 395 396 /* make sure rendering has completed */ 397 ctx->pipe->flush(ctx->pipe, 398 PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, 399 NULL); 400 401#if DEBUG_MASKS 402 save_alpha_to_file(0); 403#endif 404 405 cso_restore_blend(ctx->cso_context); 406 cso_restore_framebuffer(ctx->cso_context); 407 cso_restore_fragment_shader(ctx->cso_context); 408 cso_restore_viewport(ctx->cso_context); 409} 410 411 412static void mask_using_texture(struct pipe_sampler_view *sampler_view, 413 VGMaskOperation operation, 414 VGint x, VGint y, 415 VGint width, VGint height) 416{ 417 struct vg_context *ctx = vg_current_context(); 418 struct pipe_resource *texture = sampler_view->texture; 419 struct pipe_surface *surface = 420 alpha_mask_surface(ctx, PIPE_BIND_RENDER_TARGET); 421 VGint offsets[4], loc[4]; 422 423 if (!surface) 424 return; 425 if (!intersect_rectangles(surface->width, surface->height, 426 texture->width0, texture->height0, 427 x, y, width, height, 428 offsets, loc)) 429 return; 430#if 0 431 debug_printf("Offset = [%d, %d, %d, %d]\n", offsets[0], 432 offsets[1], offsets[2], offsets[3]); 433 debug_printf("Locati = [%d, %d, %d, %d]\n", loc[0], 434 loc[1], loc[2], loc[3]); 435#endif 436 437 /* prepare our blend surface */ 438 vg_prepare_blend_surface_from_mask(ctx); 439 440 cso_save_samplers(ctx->cso_context); 441 cso_save_fragment_sampler_views(ctx->cso_context); 442 cso_save_framebuffer(ctx->cso_context); 443 cso_save_blend(ctx->cso_context); 444 cso_save_fragment_shader(ctx->cso_context); 445 cso_save_viewport(ctx->cso_context); 446 447 setup_mask_samplers(sampler_view); 448 setup_mask_blend(); 449 setup_mask_operation(operation); 450 setup_mask_framebuffer(surface, surface->width, surface->height); 451 setup_mask_viewport(); 452 453 /* render the quad to propagate the rendering from stencil */ 454 renderer_draw_texture(ctx->renderer, texture, 455 offsets[0], offsets[1], 456 offsets[0] + offsets[2], offsets[1] + offsets[3], 457 loc[0], loc[1], loc[0] + loc[2], loc[1] + loc[3]); 458 459 /* make sure rendering has completed */ 460 ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 461 cso_restore_blend(ctx->cso_context); 462 cso_restore_framebuffer(ctx->cso_context); 463 cso_restore_fragment_shader(ctx->cso_context); 464 cso_restore_samplers(ctx->cso_context); 465 cso_restore_fragment_sampler_views(ctx->cso_context); 466 cso_restore_viewport(ctx->cso_context); 467 468 pipe_surface_reference(&surface, NULL); 469} 470 471 472#ifdef OPENVG_VERSION_1_1 473 474struct vg_mask_layer * mask_layer_create(VGint width, VGint height) 475{ 476 struct vg_context *ctx = vg_current_context(); 477 struct vg_mask_layer *mask = 0; 478 479 mask = CALLOC_STRUCT(vg_mask_layer); 480 vg_init_object(&mask->base, ctx, VG_OBJECT_MASK); 481 mask->width = width; 482 mask->height = height; 483 484 { 485 struct pipe_resource pt; 486 struct pipe_context *pipe = ctx->pipe; 487 struct pipe_screen *screen = ctx->pipe->screen; 488 struct pipe_sampler_view view_templ; 489 struct pipe_sampler_view *view = NULL; 490 struct pipe_resource *texture; 491 492 memset(&pt, 0, sizeof(pt)); 493 pt.target = PIPE_TEXTURE_2D; 494 pt.format = PIPE_FORMAT_B8G8R8A8_UNORM; 495 pt.last_level = 0; 496 pt.width0 = width; 497 pt.height0 = height; 498 pt.depth0 = 1; 499 pt.bind = PIPE_BIND_SAMPLER_VIEW; 500 pt.compressed = 0; 501 502 texture = screen->resource_create(screen, &pt); 503 504 if (texture) { 505 u_sampler_view_default_template(&view_templ, texture, texture->format); 506 view = pipe->create_sampler_view(pipe, texture, &view_templ); 507 } 508 pipe_resource_reference(&texture, NULL); 509 mask->sampler_view = view; 510 } 511 512 vg_context_add_object(ctx, VG_OBJECT_MASK, mask); 513 514 return mask; 515} 516 517void mask_layer_destroy(struct vg_mask_layer *layer) 518{ 519 struct vg_context *ctx = vg_current_context(); 520 521 vg_context_remove_object(ctx, VG_OBJECT_MASK, layer); 522 pipe_resource_release(&layer->texture); 523 FREE(layer); 524} 525 526void mask_layer_fill(struct vg_mask_layer *layer, 527 VGint x, VGint y, 528 VGint width, VGint height, 529 VGfloat value) 530{ 531 struct vg_context *ctx = vg_current_context(); 532 VGfloat alpha_color[4] = {0, 0, 0, 0}; 533 struct pipe_surface *surface; 534 535 alpha_color[3] = value; 536 537 surface = ctx->pipe->screen->get_tex_surface( 538 ctx->pipe->screen, layer->sampler_view->texture, 539 0, 0, 0, 540 PIPE_BIND_RENDER_TARGET); 541 542 surface_fill(surface, 543 layer->width, layer->height, 544 x, y, width, height, alpha_color); 545 546 ctx->pipe->screen->tex_surface_release(ctx->pipe->screen, &surface); 547} 548 549void mask_copy(struct vg_mask_layer *layer, 550 VGint sx, VGint sy, 551 VGint dx, VGint dy, 552 VGint width, VGint height) 553{ 554 struct vg_context *ctx = vg_current_context(); 555 struct st_framebuffer *fb_buffers = ctx->draw_buffer; 556 557 renderer_copy_texture(ctx->renderer, 558 layer->sampler_view, 559 sx, sy, 560 sx + width, sy + height, 561 fb_buffers->alpha_mask_view->texture, 562 dx, dy, 563 dx + width, dy + height); 564} 565 566static void mask_layer_render_to(struct vg_mask_layer *layer, 567 struct path *path, 568 VGbitfield paint_modes) 569{ 570 struct vg_context *ctx = vg_current_context(); 571 const VGfloat fill_color[4] = {1.f, 1.f, 1.f, 1.f}; 572 struct pipe_screen *screen = ctx->pipe->screen; 573 struct pipe_surface *surface; 574 575 surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0, 576 PIPE_BIND_RENDER_TARGET); 577 578 cso_save_framebuffer(ctx->cso_context); 579 cso_save_fragment_shader(ctx->cso_context); 580 cso_save_viewport(ctx->cso_context); 581 582 setup_mask_blend(); 583 setup_mask_fill(fill_color); 584 setup_mask_framebuffer(surface, layer->width, layer->height); 585 setup_mask_viewport(); 586 587 if (paint_modes & VG_FILL_PATH) { 588 struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix; 589 path_fill(path, mat); 590 } 591 592 if (paint_modes & VG_STROKE_PATH){ 593 path_stroke(path); 594 } 595 596 597 /* make sure rendering has completed */ 598 ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); 599 600 cso_restore_framebuffer(ctx->cso_context); 601 cso_restore_fragment_shader(ctx->cso_context); 602 cso_restore_viewport(ctx->cso_context); 603 ctx->state.dirty |= BLEND_DIRTY; 604 605 screen->tex_surface_release(ctx->pipe->screen, &surface); 606} 607 608void mask_render_to(struct path *path, 609 VGbitfield paint_modes, 610 VGMaskOperation operation) 611{ 612 struct vg_context *ctx = vg_current_context(); 613 struct st_framebuffer *fb_buffers = ctx->draw_buffer; 614 struct vg_mask_layer *temp_layer; 615 VGint width, height; 616 617 width = fb_buffers->alpha_mask_view->texture->width0; 618 height = fb_buffers->alpha_mask_view->texture->width0; 619 620 temp_layer = mask_layer_create(width, height); 621 622 mask_layer_render_to(temp_layer, path, paint_modes); 623 624 mask_using_layer(temp_layer, 0, 0, width, height, 625 operation); 626 627 mask_layer_destroy(temp_layer); 628} 629 630void mask_using_layer(struct vg_mask_layer *layer, 631 VGMaskOperation operation, 632 VGint x, VGint y, 633 VGint width, VGint height) 634{ 635 mask_using_texture(layer->sampler_view, operation, 636 x, y, width, height); 637} 638 639VGint mask_layer_width(struct vg_mask_layer *layer) 640{ 641 return layer->width; 642} 643 644VGint mask_layer_height(struct vg_mask_layer *layer) 645{ 646 return layer->height; 647} 648 649 650#endif 651 652void mask_using_image(struct vg_image *image, 653 VGMaskOperation operation, 654 VGint x, VGint y, 655 VGint width, VGint height) 656{ 657 mask_using_texture(image->sampler_view, operation, 658 x, y, width, height); 659} 660 661void mask_fill(VGint x, VGint y, VGint width, VGint height, 662 VGfloat value) 663{ 664 struct vg_context *ctx = vg_current_context(); 665 VGfloat alpha_color[4] = {.0f, .0f, .0f, value}; 666 struct pipe_surface *surf = alpha_mask_surface( 667 ctx, PIPE_BIND_RENDER_TARGET); 668 669#if DEBUG_MASKS 670 debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n", 671 x, y, width, height, 672 alpha_color[0], alpha_color[1], 673 alpha_color[2], alpha_color[3]); 674 debug_printf("XXX %f === %f \n", 675 alpha_color[3], value); 676#endif 677 678 surface_fill(surf, surf->width, surf->height, 679 x, y, width, height, alpha_color); 680 681 pipe_surface_reference(&surf, NULL); 682} 683 684VGint mask_bind_samplers(struct pipe_sampler_state **samplers, 685 struct pipe_sampler_view **sampler_views) 686{ 687 struct vg_context *ctx = vg_current_context(); 688 689 if (ctx->state.vg.masking) { 690 struct st_framebuffer *fb_buffers = ctx->draw_buffer; 691 692 samplers[1] = &ctx->mask.sampler; 693 sampler_views[1] = fb_buffers->alpha_mask_view; 694 return 1; 695 } else 696 return 0; 697} 698