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