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