316ea7a9c959cfaa0d8ec51f38d24a9472d810ef
[profile/ivi/mesa.git] / src / gallium / state_trackers / vega / mask.c
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
42 struct 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
51 static INLINE struct pipe_surface *
52 alpha_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
62 static INLINE VGboolean
63 intersect_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
106 static 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_BUFFER_USAGE_CPU_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
164 void 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
196 static 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 */
217 static void setup_mask_operation(VGMaskOperation operation)
218 {
219    struct vg_context *ctx = vg_current_context();
220    struct pipe_buffer **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_buffer_reference(cbuf, NULL);
229
230    *cbuf = pipe_buffer_create(ctx->pipe->screen, 1,
231                               PIPE_BUFFER_USAGE_CONSTANT,
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
287 static 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 */
318 static void setup_mask_fill(const VGfloat color[4])
319 {
320    struct vg_context *ctx = vg_current_context();
321    struct pipe_buffer **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_buffer_reference(cbuf, NULL);
328
329    *cbuf = pipe_buffer_create(ctx->pipe->screen, 1,
330                               PIPE_BUFFER_USAGE_CONSTANT,
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
342 static void setup_mask_viewport()
343 {
344    struct vg_context *ctx = vg_current_context();
345    vg_set_viewport(ctx, VEGA_Y0_TOP);
346 }
347
348 static 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
366 static 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
412 static 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_texture *texture = sampler_view->texture;
419    struct pipe_surface *surface =
420       alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE);
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
474 struct 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_texture 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_texture *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.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
500       pt.compressed = 0;
501
502       texture = screen->texture_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_texture_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
517 void 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_texture_release(&layer->texture);
523    free(layer);
524 }
525
526 void 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_BUFFER_USAGE_GPU_WRITE);
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
549 void 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
566 static 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_BUFFER_USAGE_GPU_WRITE);
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
608 void 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
630 void 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
639 VGint mask_layer_width(struct vg_mask_layer *layer)
640 {
641    return layer->width;
642 }
643
644 VGint mask_layer_height(struct vg_mask_layer *layer)
645 {
646    return layer->height;
647 }
648
649
650 #endif
651
652 void 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
661 void 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_BUFFER_USAGE_GPU_WRITE);
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
684 VGint 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 }