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