Merge branch 'mesa_7_5_branch' into mesa_7_6_branch
[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 "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
42 struct 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
84 static 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
95 static 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
103 static 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
143 static 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.width[0] = 1024;
155 templ.height[0] = 1;
156 templ.depth[0] = 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
175 struct 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
206 void 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
219 void 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
233 static 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
243 static 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
280 static 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
322 static 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->width[0];
332 map[7] = paint->pattern.texture->height[0];
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
353 void paint_set_type(struct vg_paint *paint, VGPaintType type)
354 {
355 paint->type = type;
356 }
357
358 void 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
404 void 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
413 VGuint 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
424 void 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
430 void 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
447 VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint)
448 {
449 return paint->gradient.spread;
450 }
451
452 void 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
458 void 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
469 void 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
496 void 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
505 void 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
511 void paint_linear_gradient(struct vg_paint *paint,
512 VGfloat *coords)
513 {
514 memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4);
515 }
516
517 void paint_radial_gradient(struct vg_paint *paint,
518 VGfloat *coords)
519 {
520 memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5);
521 }
522
523 int paint_num_ramp_stops(struct vg_paint *paint)
524 {
525 return paint->gradient.num_stops;
526 }
527
528 VGPaintType paint_type(struct vg_paint *paint)
529 {
530 return paint->type;
531 }
532
533 void 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
547 void 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
556 void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
557 VGboolean set)
558 {
559 paint->gradient.color_ramps_premultiplied = set;
560 }
561
562 VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint)
563 {
564 return paint->gradient.color_ramps_premultiplied;
565 }
566
567 void 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
577 void 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
583 void 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
589 void paint_linear_gradienti(struct vg_paint *paint,
590 VGint *coords)
591 {
592 memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4);
593 }
594
595 void 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
601 void paint_radial_gradienti(struct vg_paint *paint,
602 VGint *coords)
603 {
604 memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5);
605 }
606
607 VGTilingMode paint_pattern_tiling(struct vg_paint *paint)
608 {
609 return paint->pattern.tiling_mode;
610 }
611
612 VGint 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
649 void 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
657 VGint 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
679 void 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 }