paint.c revision d509f84543d0979e9bb53c20c195f378dd61e728
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 "paint.h"
28
29#include "shaders_cache.h"
30#include "matrix.h"
31#include "image.h"
32#include "st_inlines.h"
33
34#include "pipe/p_compiler.h"
35#include "pipe/p_inlines.h"
36
37#include "util/u_memory.h"
38#include "util/u_math.h"
39
40#include "cso_cache/cso_context.h"
41
42struct vg_paint {
43   struct vg_object base;
44
45   VGPaintType type;
46
47   struct {
48      VGfloat color[4];
49      VGint colori[4];
50   } solid;
51
52   struct {
53      VGColorRampSpreadMode spread;
54      VGuint color_data[1024];
55      struct {
56         VGfloat  coords[4];
57         VGint  coordsi[4];
58      } linear;
59      struct {
60         VGfloat vals[5];
61         VGint valsi[5];
62      } radial;
63      struct pipe_texture *texture;
64      struct pipe_sampler_state sampler;
65
66      VGfloat *ramp_stops;
67      VGint *ramp_stopsi;
68      VGint    num_stops;
69
70      VGboolean color_ramps_premultiplied;
71   } gradient;
72
73   struct {
74      struct pipe_texture *texture;
75      VGTilingMode tiling_mode;
76      struct pipe_sampler_state sampler;
77   } pattern;
78
79   struct pipe_constant_buffer cbuf;
80   struct pipe_shader_state fs_state;
81   void *fs;
82};
83
84static INLINE VGuint mix_pixels(VGuint p1, VGuint a, VGuint p2, VGuint b)
85{
86   VGuint t = (p1 & 0xff00ff) * a + (p2 & 0xff00ff) * b;
87   t >>= 8; t &= 0xff00ff;
88
89   p1 = ((p1 >> 8) & 0xff00ff) * a + ((p2 >> 8) & 0xff00ff) * b;
90   p1 &= 0xff00ff00; p1 |= t;
91
92   return p1;
93}
94
95static INLINE VGuint float4_to_argb(const VGfloat *clr)
96{
97   return float_to_ubyte(clr[3]) << 24 |
98      float_to_ubyte(clr[0]) << 16 |
99      float_to_ubyte(clr[1]) << 8 |
100      float_to_ubyte(clr[2]) << 0;
101}
102
103static INLINE void create_gradient_data(const VGfloat *ramp_stops,
104                                        VGint num,
105                                        VGuint *data,
106                                        VGint size)
107{
108   VGint i;
109   VGint pos = 0;
110   VGfloat fpos = 0, incr = 1.f / size;
111   VGuint last_color;
112
113   while (fpos < ramp_stops[0]) {
114      data[pos] = float4_to_argb(ramp_stops + 1);
115      fpos += incr;
116      ++pos;
117   }
118
119   for (i = 0; i < num - 1; ++i) {
120      VGint rcur  = 5 * i;
121      VGint rnext = 5 * (i + 1);
122      VGfloat delta = 1.f/(ramp_stops[rnext] - ramp_stops[rcur]);
123      while (fpos < ramp_stops[rnext] && pos < size) {
124         VGint dist = 256 * ((fpos - ramp_stops[rcur]) * delta);
125         VGint idist = 256 - dist;
126         VGuint current_color = float4_to_argb(ramp_stops + rcur + 1);
127         VGuint next_color = float4_to_argb(ramp_stops + rnext + 1);
128         data[pos] = mix_pixels(current_color, idist,
129                                next_color, dist);
130         fpos += incr;
131         ++pos;
132      }
133   }
134
135   last_color = float4_to_argb(ramp_stops + ((num - 1) * 5 + 1));
136   while (pos < size) {
137      data[pos] = last_color;
138      ++pos;
139   }
140   data[size-1] = last_color;
141}
142
143static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p)
144{
145   struct pipe_context *pipe = p->base.ctx->pipe;
146   struct pipe_screen *screen = pipe->screen;
147   struct pipe_texture *tex = 0;
148   struct pipe_texture templ;
149
150   memset(&templ, 0, sizeof(templ));
151   templ.target = PIPE_TEXTURE_1D;
152   templ.format = PIPE_FORMAT_A8R8G8B8_UNORM;
153   templ.last_level = 0;
154   templ.width0 = 1024;
155   templ.height0 = 1;
156   templ.depth0 = 1;
157   pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block);
158   templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
159
160   tex = screen->texture_create(screen, &templ);
161
162   { /* upload color_data */
163      struct pipe_transfer *transfer =
164         st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0,
165                                      PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
166      void *map = screen->transfer_map(screen, transfer);
167      memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
168      screen->transfer_unmap(screen, transfer);
169      screen->tex_transfer_destroy(transfer);
170   }
171
172   return tex;
173}
174
175struct vg_paint * paint_create(struct vg_context *ctx)
176{
177   struct vg_paint *paint = CALLOC_STRUCT(vg_paint);
178   const VGfloat default_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
179   const VGfloat def_ling[] = {0.0f, 0.0f, 1.0f, 0.0f};
180   const VGfloat def_radg[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
181   vg_init_object(&paint->base, ctx, VG_OBJECT_PAINT);
182   vg_context_add_object(ctx, VG_OBJECT_PAINT, paint);
183
184   paint->type = VG_PAINT_TYPE_COLOR;
185   memcpy(paint->solid.color, default_color,
186          4 * sizeof(VGfloat));
187   paint->gradient.spread = VG_COLOR_RAMP_SPREAD_PAD;
188   memcpy(paint->gradient.linear.coords, def_ling,
189          4 * sizeof(VGfloat));
190   memcpy(paint->gradient.radial.vals, def_radg,
191          5 * sizeof(VGfloat));
192
193   paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
194   paint->gradient.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
195   paint->gradient.sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
196   paint->gradient.sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
197   paint->gradient.sampler.normalized_coords = 1;
198
199   memcpy(&paint->pattern.sampler,
200          &paint->gradient.sampler,
201          sizeof(struct pipe_sampler_state));
202
203   return paint;
204}
205
206void paint_destroy(struct vg_paint *paint)
207{
208   struct vg_context *ctx = paint->base.ctx;
209   if (paint->pattern.texture)
210      pipe_texture_reference(&paint->pattern.texture, NULL);
211   if (ctx)
212      vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint);
213
214   free(paint->gradient.ramp_stopsi);
215   free(paint->gradient.ramp_stops);
216   free(paint);
217}
218
219void paint_set_color(struct vg_paint *paint,
220                     const VGfloat *color)
221{
222   paint->solid.color[0] = color[0];
223   paint->solid.color[1] = color[1];
224   paint->solid.color[2] = color[2];
225   paint->solid.color[3] = color[3];
226
227   paint->solid.colori[0] = FLT_TO_INT(color[0]);
228   paint->solid.colori[1] = FLT_TO_INT(color[1]);
229   paint->solid.colori[2] = FLT_TO_INT(color[2]);
230   paint->solid.colori[3] = FLT_TO_INT(color[3]);
231}
232
233static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
234{
235   VGfloat *map = (VGfloat*)buffer;
236   memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat));
237   map[4] = 0.f;
238   map[5] = 1.f;
239   map[6] = 2.f;
240   map[7] = 4.f;
241}
242
243static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer)
244{
245   struct vg_context *ctx = paint->base.ctx;
246   VGfloat *map = (VGfloat*)buffer;
247
248   map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
249   map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1];
250   map[2] = 1.f / (map[0] * map[0] + map[1] * map[1]);
251   map[3] = 1.f;
252
253   map[4] = 0.f;
254   map[5] = 1.f;
255   map[6] = 2.f;
256   map[7] = 4.f;
257   {
258      struct matrix mat;
259      struct matrix inv;
260      matrix_load_identity(&mat);
261      matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
262      memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
263             sizeof(struct matrix));
264      matrix_invert(&inv);
265      matrix_mult(&inv, &mat);
266      memcpy(&mat, &inv,
267             sizeof(struct matrix));
268
269      map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
270      map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
271      map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
272   }
273#if 0
274   debug_printf("Coords  (%f, %f, %f, %f)\n",
275                map[0], map[1], map[2], map[3]);
276#endif
277}
278
279
280static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer)
281{
282   VGfloat *radialCoords = paint->gradient.radial.vals;
283   struct vg_context *ctx = paint->base.ctx;
284
285   VGfloat *map = (VGfloat*)buffer;
286
287   map[0] = radialCoords[0] - radialCoords[2];
288   map[1] = radialCoords[1] - radialCoords[3];
289   map[2] = -map[0] * map[0] - map[1] * map[1] +
290            radialCoords[4] * radialCoords[4];
291   map[3] = 1.f;
292
293   map[4] = 0.f;
294   map[5] = 1.f;
295   map[6] = 2.f;
296   map[7] = 4.f;
297
298   {
299      struct matrix mat;
300      struct matrix inv;
301      matrix_load_identity(&mat);
302      matrix_translate(&mat, -radialCoords[2], -radialCoords[3]);
303      memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
304             sizeof(struct matrix));
305      matrix_invert(&inv);
306      matrix_mult(&inv, &mat);
307      memcpy(&mat, &inv,
308             sizeof(struct matrix));
309
310      map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
311      map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
312      map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
313   }
314
315#if 0
316   debug_printf("Coords  (%f, %f, %f, %f)\n",
317                map[0], map[1], map[2], map[3]);
318#endif
319}
320
321
322static INLINE void  paint_pattern_buffer(struct vg_paint *paint, void *buffer)
323{
324   struct vg_context *ctx = paint->base.ctx;
325
326   VGfloat *map = (VGfloat *)buffer;
327   memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
328
329   map[4] = 0.f;
330   map[5] = 1.f;
331   map[6] = paint->pattern.texture->width0;
332   map[7] = paint->pattern.texture->height0;
333   {
334      struct matrix mat;
335      memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
336             sizeof(struct matrix));
337      matrix_invert(&mat);
338      {
339         struct matrix pm;
340         memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix,
341                sizeof(struct matrix));
342         matrix_invert(&pm);
343         matrix_mult(&pm, &mat);
344         memcpy(&mat, &pm, sizeof(struct matrix));
345      }
346
347      map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
348      map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
349      map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
350   }
351}
352
353void paint_set_type(struct vg_paint *paint, VGPaintType type)
354{
355   paint->type = type;
356}
357
358void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
359                          int num)
360{
361   const VGfloat default_stops[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
362                                    1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
363   VGint i;
364   const VGint num_stops = num / 5;
365   VGfloat last_coord;
366
367   paint->gradient.num_stops = num;
368   if (num) {
369      free(paint->gradient.ramp_stops);
370      paint->gradient.ramp_stops = malloc(sizeof(VGfloat)*num);
371      memcpy(paint->gradient.ramp_stops, stops, sizeof(VGfloat)*num);
372   } else
373      return;
374
375   /* stops must be in increasing order. the last stop is 1.0. if the
376    * first one is bigger than 1 then the whole sequence is invalid*/
377   if (stops[0] > 1) {
378      stops = default_stops;
379      num = 10;
380   }
381   last_coord = stops[0];
382   for (i = 1; i < num_stops; ++i) {
383      VGint idx = 5 * i;
384      VGfloat coord = stops[idx];
385      if (!floatsEqual(last_coord, coord) && coord < last_coord) {
386         stops = default_stops;
387         num = 10;
388         break;
389      }
390      last_coord = coord;
391   }
392
393   create_gradient_data(stops, num / 5, paint->gradient.color_data,
394                        1024);
395
396   if (paint->gradient.texture) {
397      pipe_texture_reference(&paint->gradient.texture, NULL);
398      paint->gradient.texture = 0;
399   }
400
401   paint->gradient.texture = create_gradient_texture(paint);
402}
403
404void paint_set_colori(struct vg_paint *p,
405                      VGuint rgba)
406{
407   p->solid.color[0] = ((rgba >> 24) & 0xff) / 255.f;
408   p->solid.color[1] = ((rgba >> 16) & 0xff) / 255.f;
409   p->solid.color[2] = ((rgba >>  8) & 0xff) / 255.f;
410   p->solid.color[3] = ((rgba >>  0) & 0xff) / 255.f;
411}
412
413VGuint paint_colori(struct vg_paint *p)
414{
415#define F2B(f) (float_to_ubyte(f))
416
417   return ((F2B(p->solid.color[0]) << 24) |
418           (F2B(p->solid.color[1]) << 16) |
419           (F2B(p->solid.color[2]) << 8)  |
420           (F2B(p->solid.color[3]) << 0));
421#undef F2B
422}
423
424void paint_set_linear_gradient(struct vg_paint *paint,
425                               const VGfloat *coords)
426{
427   memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4);
428}
429
430void paint_set_spread_mode(struct vg_paint *paint,
431                           VGint mode)
432{
433   paint->gradient.spread = mode;
434   switch(mode) {
435   case VG_COLOR_RAMP_SPREAD_PAD:
436      paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
437      break;
438   case VG_COLOR_RAMP_SPREAD_REPEAT:
439      paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
440      break;
441   case VG_COLOR_RAMP_SPREAD_REFLECT:
442      paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
443      break;
444   }
445}
446
447VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint)
448{
449   return paint->gradient.spread;
450}
451
452void paint_set_radial_gradient(struct vg_paint *paint,
453                               const VGfloat *values)
454{
455   memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5);
456}
457
458void paint_set_pattern(struct vg_paint *paint,
459                       struct vg_image *img)
460{
461   if (paint->pattern.texture)
462      pipe_texture_reference(&paint->pattern.texture, NULL);
463
464   paint->pattern.texture = 0;
465   pipe_texture_reference(&paint->pattern.texture,
466                          img->texture);
467}
468
469void paint_set_pattern_tiling(struct vg_paint *paint,
470                              VGTilingMode mode)
471{
472   paint->pattern.tiling_mode = mode;
473
474   switch(mode) {
475   case VG_TILE_FILL:
476      paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
477      paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
478      break;
479   case VG_TILE_PAD:
480      paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
481      paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
482      break;
483   case VG_TILE_REPEAT:
484      paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
485      paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
486      break;
487   case VG_TILE_REFLECT:
488      paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
489      paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
490      break;
491   default:
492      debug_assert("!Unknown tiling mode");
493   }
494}
495
496void paint_get_color(struct vg_paint *paint,
497                     VGfloat *color)
498{
499   color[0] = paint->solid.color[0];
500   color[1] = paint->solid.color[1];
501   color[2] = paint->solid.color[2];
502   color[3] = paint->solid.color[3];
503}
504
505void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
506                      int num)
507{
508   memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num);
509}
510
511void paint_linear_gradient(struct vg_paint *paint,
512                           VGfloat *coords)
513{
514   memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4);
515}
516
517void paint_radial_gradient(struct vg_paint *paint,
518                           VGfloat *coords)
519{
520   memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5);
521}
522
523int paint_num_ramp_stops(struct vg_paint *paint)
524{
525   return paint->gradient.num_stops;
526}
527
528VGPaintType paint_type(struct vg_paint *paint)
529{
530   return paint->type;
531}
532
533void paint_set_coloriv(struct vg_paint *paint,
534                      const VGint *color)
535{
536   paint->solid.color[0] = color[0];
537   paint->solid.color[1] = color[1];
538   paint->solid.color[2] = color[2];
539   paint->solid.color[3] = color[3];
540
541   paint->solid.colori[0] = color[0];
542   paint->solid.colori[1] = color[1];
543   paint->solid.colori[2] = color[2];
544   paint->solid.colori[3] = color[3];
545}
546
547void paint_get_coloriv(struct vg_paint *paint,
548                      VGint *color)
549{
550   color[0] = paint->solid.colori[0];
551   color[1] = paint->solid.colori[1];
552   color[2] = paint->solid.colori[2];
553   color[3] = paint->solid.colori[3];
554}
555
556void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
557                                        VGboolean set)
558{
559   paint->gradient.color_ramps_premultiplied = set;
560}
561
562VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint)
563{
564   return paint->gradient.color_ramps_premultiplied;
565}
566
567void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
568                           int num)
569{
570   if (num) {
571      free(paint->gradient.ramp_stopsi);
572      paint->gradient.ramp_stopsi = malloc(sizeof(VGint)*num);
573      memcpy(paint->gradient.ramp_stopsi, stops, sizeof(VGint)*num);
574   }
575}
576
577void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
578                       int num)
579{
580   memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num);
581}
582
583void paint_set_linear_gradienti(struct vg_paint *paint,
584                                const VGint *coords)
585{
586   memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4);
587}
588
589void paint_linear_gradienti(struct vg_paint *paint,
590                            VGint *coords)
591{
592   memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4);
593}
594
595void paint_set_radial_gradienti(struct vg_paint *paint,
596                                const VGint *values)
597{
598   memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5);
599}
600
601void paint_radial_gradienti(struct vg_paint *paint,
602                            VGint *coords)
603{
604   memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5);
605}
606
607VGTilingMode paint_pattern_tiling(struct vg_paint *paint)
608{
609   return paint->pattern.tiling_mode;
610}
611
612VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
613                          struct pipe_texture **textures)
614{
615   struct vg_context *ctx = vg_current_context();
616
617   switch(paint->type) {
618   case VG_PAINT_TYPE_LINEAR_GRADIENT:
619   case VG_PAINT_TYPE_RADIAL_GRADIENT: {
620      if (paint->gradient.texture) {
621         paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx);
622         paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx);
623         samplers[0] = &paint->gradient.sampler;
624         textures[0] = paint->gradient.texture;
625         return 1;
626      }
627   }
628      break;
629   case VG_PAINT_TYPE_PATTERN: {
630      memcpy(paint->pattern.sampler.border_color,
631             ctx->state.vg.tile_fill_color,
632             sizeof(VGfloat) * 4);
633      paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx);
634      paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx);
635      samplers[0] = &paint->pattern.sampler;
636      textures[0] = paint->pattern.texture;
637      return 1;
638   }
639      break;
640   default:
641      samplers[0] = &paint->pattern.sampler; /* dummy */
642      textures[0] = 0;
643      return 0;
644      break;
645   }
646   return 0;
647}
648
649void paint_resolve_type(struct vg_paint *paint)
650{
651   if (paint->type == VG_PAINT_TYPE_PATTERN &&
652       !paint->pattern.texture) {
653      paint->type = VG_PAINT_TYPE_COLOR;
654   }
655}
656
657VGint paint_constant_buffer_size(struct vg_paint *paint)
658{
659   switch(paint->type) {
660   case VG_PAINT_TYPE_COLOR:
661      return 8 * sizeof(VGfloat);/*4 color + 4 constants (0.f,1.f,2.f,4.f)*/
662      break;
663   case VG_PAINT_TYPE_LINEAR_GRADIENT:
664      return 20 * sizeof(VGfloat);
665      break;
666   case VG_PAINT_TYPE_RADIAL_GRADIENT:
667      return 20 * sizeof(VGfloat);
668      break;
669   case VG_PAINT_TYPE_PATTERN:
670      return 20 * sizeof(VGfloat);
671      break;
672   default:
673      debug_printf("Uknown paint type: %d\n", paint->type);
674   }
675
676   return 0;
677}
678
679void paint_fill_constant_buffer(struct vg_paint *paint,
680                                void *buffer)
681{
682   switch(paint->type) {
683   case VG_PAINT_TYPE_COLOR:
684      paint_color_buffer(paint, buffer);
685      break;
686   case VG_PAINT_TYPE_LINEAR_GRADIENT:
687      paint_linear_gradient_buffer(paint, buffer);
688      break;
689   case VG_PAINT_TYPE_RADIAL_GRADIENT:
690      paint_radial_gradient_buffer(paint, buffer);
691      break;
692   case VG_PAINT_TYPE_PATTERN:
693      paint_pattern_buffer(paint, buffer);
694      break;
695
696   default:
697      abort();
698   }
699}
700