st/egl: Remove.
[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 "matrix.h"
30 #include "image.h"
31
32 #include "pipe/p_compiler.h"
33 #include "util/u_inlines.h"
34
35 #include "util/u_memory.h"
36 #include "util/u_math.h"
37 #include "util/u_sampler.h"
38
39 #include "cso_cache/cso_context.h"
40
41 struct vg_paint {
42 struct vg_object base;
43
44 VGPaintType type;
45
46 struct {
47 VGfloat color[4];
48 VGint colori[4];
49 } solid;
50
51 struct {
52 VGColorRampSpreadMode spread;
53 VGuint color_data[1024];
54 struct {
55 VGfloat coords[4];
56 VGint coordsi[4];
57 } linear;
58 struct {
59 VGfloat vals[5];
60 VGint valsi[5];
61 } radial;
62 struct pipe_sampler_view *sampler_view;
63 struct pipe_sampler_state sampler;
64
65 VGfloat *ramp_stops;
66 VGint *ramp_stopsi;
67 VGint num_stops;
68
69 VGboolean color_ramps_premultiplied;
70 } gradient;
71
72 struct {
73 struct pipe_sampler_view *sampler_view;
74 VGTilingMode tiling_mode;
75 struct pipe_sampler_state sampler;
76 } pattern;
77
78 /* XXX next 3 all unneded? */
79 struct pipe_resource *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_resource *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_resource *tex = 0;
148 struct pipe_resource templ;
149
150 memset(&templ, 0, sizeof(templ));
151 templ.target = PIPE_TEXTURE_1D;
152 templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
153 templ.last_level = 0;
154 templ.width0 = 1024;
155 templ.height0 = 1;
156 templ.depth0 = 1;
157 templ.array_size = 1;
158 templ.bind = PIPE_BIND_SAMPLER_VIEW;
159
160 tex = screen->resource_create(screen, &templ);
161
162 { /* upload color_data */
163 struct pipe_transfer *transfer;
164 void *map =
165 pipe_transfer_map(p->base.ctx->pipe, tex, 0, 0,
166 PIPE_TRANSFER_WRITE, 0, 0, 1024, 1,
167 &transfer);
168 memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
169 pipe->transfer_unmap(pipe, transfer);
170 }
171
172 return tex;
173 }
174
175 static INLINE struct pipe_sampler_view *create_gradient_sampler_view(struct vg_paint *p)
176 {
177 struct pipe_context *pipe = p->base.ctx->pipe;
178 struct pipe_resource *texture;
179 struct pipe_sampler_view view_templ;
180 struct pipe_sampler_view *view;
181
182 texture = create_gradient_texture(p);
183
184 if (!texture)
185 return NULL;
186
187 u_sampler_view_default_template(&view_templ, texture, texture->format);
188 view = pipe->create_sampler_view(pipe, texture, &view_templ);
189 /* want the texture to go away if the view is freed */
190 pipe_resource_reference(&texture, NULL);
191
192 return view;
193 }
194
195 struct vg_paint * paint_create(struct vg_context *ctx)
196 {
197 struct vg_paint *paint = CALLOC_STRUCT(vg_paint);
198 const VGfloat default_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
199 const VGfloat def_ling[] = {0.0f, 0.0f, 1.0f, 0.0f};
200 const VGfloat def_radg[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
201 vg_init_object(&paint->base, ctx, VG_OBJECT_PAINT);
202 vg_context_add_object(ctx, &paint->base);
203
204 paint->type = VG_PAINT_TYPE_COLOR;
205 memcpy(paint->solid.color, default_color,
206 4 * sizeof(VGfloat));
207 paint->gradient.spread = VG_COLOR_RAMP_SPREAD_PAD;
208 memcpy(paint->gradient.linear.coords, def_ling,
209 4 * sizeof(VGfloat));
210 memcpy(paint->gradient.radial.vals, def_radg,
211 5 * sizeof(VGfloat));
212
213 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
214 paint->gradient.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
215 paint->gradient.sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
216 paint->gradient.sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
217 paint->gradient.sampler.normalized_coords = 1;
218
219 memcpy(&paint->pattern.sampler,
220 &paint->gradient.sampler,
221 sizeof(struct pipe_sampler_state));
222
223 return paint;
224 }
225
226 void paint_destroy(struct vg_paint *paint)
227 {
228 struct vg_context *ctx = paint->base.ctx;
229 pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL);
230 if (paint->pattern.sampler_view)
231 pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL);
232 if (ctx) {
233 vg_context_remove_object(ctx, &paint->base);
234 vg_free_object(&paint->base);
235 }
236
237 free(paint->gradient.ramp_stopsi);
238 free(paint->gradient.ramp_stops);
239 FREE(paint);
240 }
241
242 void paint_set_color(struct vg_paint *paint,
243 const VGfloat *color)
244 {
245 paint->solid.color[0] = color[0];
246 paint->solid.color[1] = color[1];
247 paint->solid.color[2] = color[2];
248 paint->solid.color[3] = color[3];
249
250 paint->solid.colori[0] = FLT_TO_INT(color[0]);
251 paint->solid.colori[1] = FLT_TO_INT(color[1]);
252 paint->solid.colori[2] = FLT_TO_INT(color[2]);
253 paint->solid.colori[3] = FLT_TO_INT(color[3]);
254 }
255
256 static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
257 {
258 VGfloat *map = (VGfloat*)buffer;
259 memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat));
260 map[4] = 0.f;
261 map[5] = 1.f;
262 map[6] = 2.f;
263 map[7] = 4.f;
264 }
265
266 static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint,
267 const struct matrix *inv,
268 void *buffer)
269 {
270 VGfloat *map = (VGfloat*)buffer;
271 VGfloat dd;
272
273 map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
274 map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1];
275 dd = (map[0] * map[0] + map[1] * map[1]);
276
277 map[2] = (dd > 0.0f) ? 1.f / dd : 0.f;
278 map[3] = 1.f;
279
280 map[4] = 0.f;
281 map[5] = 1.f;
282 map[6] = 2.f;
283 map[7] = 4.f;
284 {
285 struct matrix mat;
286 matrix_load_identity(&mat);
287 /* VEGA_LINEAR_GRADIENT_SHADER expects the first point to be at (0, 0) */
288 matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
289 matrix_mult(&mat, inv);
290
291 map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
292 map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
293 map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
294 }
295 #if 0
296 debug_printf("Coords (%f, %f, %f, %f)\n",
297 map[0], map[1], map[2], map[3]);
298 #endif
299 }
300
301
302 static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint,
303 const struct matrix *inv,
304 void *buffer)
305 {
306 const VGfloat *center = &paint->gradient.radial.vals[0];
307 const VGfloat *focal = &paint->gradient.radial.vals[2];
308 VGfloat rr = paint->gradient.radial.vals[4];
309 VGfloat *map = (VGfloat*)buffer;
310 VGfloat dd, new_focal[2];
311
312 rr *= rr;
313
314 map[0] = center[0] - focal[0];
315 map[1] = center[1] - focal[1];
316 dd = map[0] * map[0] + map[1] * map[1];
317
318 /* focal point must lie inside the circle */
319 if (0.998f * rr < dd) {
320 VGfloat scale;
321
322 scale = (dd > 0.0f) ? sqrt(0.998f * rr / dd) : 0.0f;
323 map[0] *= scale;
324 map[1] *= scale;
325
326 new_focal[0] = center[0] - map[0];
327 new_focal[1] = center[1] - map[1];
328 dd = map[0] * map[0] + map[1] * map[1];
329 focal = new_focal;
330 }
331
332 map[2] = (rr > dd) ? rr - dd : 1.0f;
333 map[3] = 1.f;
334
335 map[4] = 0.f;
336 map[5] = 1.f;
337 map[6] = 2.f;
338 map[7] = 4.f;
339
340 {
341 struct matrix mat;
342 matrix_load_identity(&mat);
343 matrix_translate(&mat, -focal[0], -focal[1]);
344 matrix_mult(&mat, inv);
345
346 map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
347 map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
348 map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
349 }
350
351 #if 0
352 debug_printf("Coords (%f, %f, %f, %f)\n",
353 map[0], map[1], map[2], map[3]);
354 #endif
355 }
356
357
358 static INLINE void paint_pattern_buffer(struct vg_paint *paint,
359 const struct matrix *inv,
360 void *buffer)
361 {
362 VGfloat *map = (VGfloat *)buffer;
363 memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
364
365 map[4] = 0.f;
366 map[5] = 1.f;
367 map[6] = paint->pattern.sampler_view->texture->width0;
368 map[7] = paint->pattern.sampler_view->texture->height0;
369 {
370 struct matrix mat;
371
372 memcpy(&mat, inv, sizeof(*inv));
373
374 map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
375 map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
376 map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f;
377 }
378 }
379
380 void paint_set_type(struct vg_paint *paint, VGPaintType type)
381 {
382 paint->type = type;
383 }
384
385 void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops,
386 int num)
387 {
388 const VGfloat default_stops[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
389 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
390 VGint i;
391 const VGint num_stops = num / 5;
392 VGfloat last_coord;
393
394 paint->gradient.num_stops = num;
395 if (num) {
396 free(paint->gradient.ramp_stops);
397 paint->gradient.ramp_stops = malloc(sizeof(VGfloat)*num);
398 memcpy(paint->gradient.ramp_stops, stops, sizeof(VGfloat)*num);
399 } else
400 return;
401
402 /* stops must be in increasing order. the last stop is 1.0. if the
403 * first one is bigger than 1 then the whole sequence is invalid*/
404 if (stops[0] > 1) {
405 stops = default_stops;
406 num = 10;
407 }
408 last_coord = stops[0];
409 for (i = 1; i < num_stops; ++i) {
410 VGint idx = 5 * i;
411 VGfloat coord = stops[idx];
412 if (!floatsEqual(last_coord, coord) && coord < last_coord) {
413 stops = default_stops;
414 num = 10;
415 break;
416 }
417 last_coord = coord;
418 }
419
420 create_gradient_data(stops, num / 5, paint->gradient.color_data,
421 1024);
422
423 if (paint->gradient.sampler_view) {
424 pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL);
425 paint->gradient.sampler_view = NULL;
426 }
427
428 paint->gradient.sampler_view = create_gradient_sampler_view(paint);
429 }
430
431 void paint_set_colori(struct vg_paint *p,
432 VGuint rgba)
433 {
434 p->solid.color[0] = ((rgba >> 24) & 0xff) / 255.f;
435 p->solid.color[1] = ((rgba >> 16) & 0xff) / 255.f;
436 p->solid.color[2] = ((rgba >> 8) & 0xff) / 255.f;
437 p->solid.color[3] = ((rgba >> 0) & 0xff) / 255.f;
438 }
439
440 VGuint paint_colori(struct vg_paint *p)
441 {
442 #define F2B(f) (float_to_ubyte(f))
443
444 return ((F2B(p->solid.color[0]) << 24) |
445 (F2B(p->solid.color[1]) << 16) |
446 (F2B(p->solid.color[2]) << 8) |
447 (F2B(p->solid.color[3]) << 0));
448 #undef F2B
449 }
450
451 void paint_set_linear_gradient(struct vg_paint *paint,
452 const VGfloat *coords)
453 {
454 memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4);
455 }
456
457 void paint_set_spread_mode(struct vg_paint *paint,
458 VGint mode)
459 {
460 paint->gradient.spread = mode;
461 switch(mode) {
462 case VG_COLOR_RAMP_SPREAD_PAD:
463 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
464 break;
465 case VG_COLOR_RAMP_SPREAD_REPEAT:
466 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
467 break;
468 case VG_COLOR_RAMP_SPREAD_REFLECT:
469 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
470 break;
471 }
472 }
473
474 VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint)
475 {
476 return paint->gradient.spread;
477 }
478
479 void paint_set_radial_gradient(struct vg_paint *paint,
480 const VGfloat *values)
481 {
482 memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5);
483 }
484
485 void paint_set_pattern(struct vg_paint *paint,
486 struct vg_image *img)
487 {
488 if (paint->pattern.sampler_view)
489 pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL);
490
491 paint->pattern.sampler_view = NULL;
492 pipe_sampler_view_reference(&paint->pattern.sampler_view,
493 img->sampler_view);
494 }
495
496 void paint_set_pattern_tiling(struct vg_paint *paint,
497 VGTilingMode mode)
498 {
499 paint->pattern.tiling_mode = mode;
500
501 switch(mode) {
502 case VG_TILE_FILL:
503 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
504 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
505 break;
506 case VG_TILE_PAD:
507 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
508 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
509 break;
510 case VG_TILE_REPEAT:
511 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
512 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
513 break;
514 case VG_TILE_REFLECT:
515 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
516 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
517 break;
518 default:
519 debug_assert(!"Unknown tiling mode");
520 }
521 }
522
523 void paint_get_color(struct vg_paint *paint,
524 VGfloat *color)
525 {
526 color[0] = paint->solid.color[0];
527 color[1] = paint->solid.color[1];
528 color[2] = paint->solid.color[2];
529 color[3] = paint->solid.color[3];
530 }
531
532 void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops,
533 int num)
534 {
535 memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num);
536 }
537
538 void paint_linear_gradient(struct vg_paint *paint,
539 VGfloat *coords)
540 {
541 memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4);
542 }
543
544 void paint_radial_gradient(struct vg_paint *paint,
545 VGfloat *coords)
546 {
547 memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5);
548 }
549
550 int paint_num_ramp_stops(struct vg_paint *paint)
551 {
552 return paint->gradient.num_stops;
553 }
554
555 VGPaintType paint_type(struct vg_paint *paint)
556 {
557 return paint->type;
558 }
559
560 void paint_set_coloriv(struct vg_paint *paint,
561 const VGint *color)
562 {
563 paint->solid.color[0] = color[0];
564 paint->solid.color[1] = color[1];
565 paint->solid.color[2] = color[2];
566 paint->solid.color[3] = color[3];
567
568 paint->solid.colori[0] = color[0];
569 paint->solid.colori[1] = color[1];
570 paint->solid.colori[2] = color[2];
571 paint->solid.colori[3] = color[3];
572 }
573
574 void paint_get_coloriv(struct vg_paint *paint,
575 VGint *color)
576 {
577 color[0] = paint->solid.colori[0];
578 color[1] = paint->solid.colori[1];
579 color[2] = paint->solid.colori[2];
580 color[3] = paint->solid.colori[3];
581 }
582
583 void paint_set_color_ramp_premultiplied(struct vg_paint *paint,
584 VGboolean set)
585 {
586 paint->gradient.color_ramps_premultiplied = set;
587 }
588
589 VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint)
590 {
591 return paint->gradient.color_ramps_premultiplied;
592 }
593
594 void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops,
595 int num)
596 {
597 if (num) {
598 free(paint->gradient.ramp_stopsi);
599 paint->gradient.ramp_stopsi = malloc(sizeof(VGint)*num);
600 memcpy(paint->gradient.ramp_stopsi, stops, sizeof(VGint)*num);
601 }
602 }
603
604 void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops,
605 int num)
606 {
607 memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num);
608 }
609
610 void paint_set_linear_gradienti(struct vg_paint *paint,
611 const VGint *coords)
612 {
613 memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4);
614 }
615
616 void paint_linear_gradienti(struct vg_paint *paint,
617 VGint *coords)
618 {
619 memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4);
620 }
621
622 void paint_set_radial_gradienti(struct vg_paint *paint,
623 const VGint *values)
624 {
625 memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5);
626 }
627
628 void paint_radial_gradienti(struct vg_paint *paint,
629 VGint *coords)
630 {
631 memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5);
632 }
633
634 VGTilingMode paint_pattern_tiling(struct vg_paint *paint)
635 {
636 return paint->pattern.tiling_mode;
637 }
638
639 VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
640 struct pipe_sampler_view **sampler_views)
641 {
642 struct vg_context *ctx = vg_current_context();
643
644 switch(paint->type) {
645 case VG_PAINT_TYPE_LINEAR_GRADIENT:
646 case VG_PAINT_TYPE_RADIAL_GRADIENT: {
647 if (paint->gradient.sampler_view) {
648 paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx);
649 paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx);
650 samplers[0] = &paint->gradient.sampler;
651 sampler_views[0] = paint->gradient.sampler_view;
652 return 1;
653 }
654 }
655 break;
656 case VG_PAINT_TYPE_PATTERN: {
657 memcpy(paint->pattern.sampler.border_color.f,
658 ctx->state.vg.tile_fill_color,
659 sizeof(VGfloat) * 4);
660 paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx);
661 paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx);
662 samplers[0] = &paint->pattern.sampler;
663 sampler_views[0] = paint->pattern.sampler_view;
664 return 1;
665 }
666 break;
667 default:
668 break;
669 }
670 return 0;
671 }
672
673 void paint_resolve_type(struct vg_paint *paint)
674 {
675 if (paint->type == VG_PAINT_TYPE_PATTERN &&
676 !paint->pattern.sampler_view) {
677 paint->type = VG_PAINT_TYPE_COLOR;
678 }
679 }
680
681 VGboolean paint_is_degenerate(struct vg_paint *paint)
682 {
683 VGboolean degen;
684 VGfloat *vals;
685
686
687 switch (paint->type) {
688 case VG_PAINT_TYPE_LINEAR_GRADIENT:
689 vals = paint->gradient.linear.coords;
690 /* two points are coincident */
691 degen = (floatsEqual(vals[0], vals[2]) &&
692 floatsEqual(vals[1], vals[3]));
693 break;
694 case VG_PAINT_TYPE_RADIAL_GRADIENT:
695 vals = paint->gradient.radial.vals;
696 /* radius <= 0 */
697 degen = (vals[4] <= 0.0f);
698 break;
699 case VG_PAINT_TYPE_COLOR:
700 case VG_PAINT_TYPE_PATTERN:
701 default:
702 degen = VG_FALSE;
703 break;
704 }
705
706 return degen;
707 }
708
709 VGint paint_constant_buffer_size(struct vg_paint *paint)
710 {
711 switch(paint->type) {
712 case VG_PAINT_TYPE_COLOR:
713 return 8 * sizeof(VGfloat);/*4 color + 4 constants (0.f,1.f,2.f,4.f)*/
714 break;
715 case VG_PAINT_TYPE_LINEAR_GRADIENT:
716 return 20 * sizeof(VGfloat);
717 break;
718 case VG_PAINT_TYPE_RADIAL_GRADIENT:
719 return 20 * sizeof(VGfloat);
720 break;
721 case VG_PAINT_TYPE_PATTERN:
722 return 20 * sizeof(VGfloat);
723 break;
724 default:
725 debug_printf("Uknown paint type: %d\n", paint->type);
726 }
727
728 return 0;
729 }
730
731 void paint_fill_constant_buffer(struct vg_paint *paint,
732 const struct matrix *mat,
733 void *buffer)
734 {
735 switch(paint->type) {
736 case VG_PAINT_TYPE_COLOR:
737 paint_color_buffer(paint, buffer);
738 break;
739 case VG_PAINT_TYPE_LINEAR_GRADIENT:
740 paint_linear_gradient_buffer(paint, mat, buffer);
741 break;
742 case VG_PAINT_TYPE_RADIAL_GRADIENT:
743 paint_radial_gradient_buffer(paint, mat, buffer);
744 break;
745 case VG_PAINT_TYPE_PATTERN:
746 paint_pattern_buffer(paint, mat, buffer);
747 break;
748
749 default:
750 abort();
751 }
752 }
753
754 VGboolean paint_is_opaque(struct vg_paint *paint)
755 {
756 /* TODO add other paint types and make sure PAINT_DIRTY gets set */
757 return (paint->type == VG_PAINT_TYPE_COLOR &&
758 floatsEqual(paint->solid.color[3], 1.0f));
759 }