1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
29 #include "shaders_cache.h"
32 #include "st_inlines.h"
34 #include "pipe/p_compiler.h"
35 #include "util/u_inlines.h"
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_math.h"
41 #include "cso_cache/cso_context.h"
44 struct vg_object base
;
54 VGColorRampSpreadMode spread
;
55 VGuint color_data
[1024];
64 struct pipe_texture
*texture
;
65 struct pipe_sampler_state sampler
;
71 VGboolean color_ramps_premultiplied
;
75 struct pipe_texture
*texture
;
76 VGTilingMode tiling_mode
;
77 struct pipe_sampler_state sampler
;
80 /* XXX next 3 all unneded? */
81 struct pipe_buffer
*cbuf
;
82 struct pipe_shader_state fs_state
;
86 static INLINE VGuint
mix_pixels(VGuint p1
, VGuint a
, VGuint p2
, VGuint b
)
88 VGuint t
= (p1
& 0xff00ff) * a
+ (p2
& 0xff00ff) * b
;
89 t
>>= 8; t
&= 0xff00ff;
91 p1
= ((p1
>> 8) & 0xff00ff) * a
+ ((p2
>> 8) & 0xff00ff) * b
;
92 p1
&= 0xff00ff00; p1
|= t
;
97 static INLINE VGuint
float4_to_argb(const VGfloat
*clr
)
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;
105 static INLINE
void create_gradient_data(const VGfloat
*ramp_stops
,
112 VGfloat fpos
= 0, incr
= 1.f
/ size
;
115 while (fpos
< ramp_stops
[0]) {
116 data
[pos
] = float4_to_argb(ramp_stops
+ 1);
121 for (i
= 0; i
< num
- 1; ++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
,
137 last_color
= float4_to_argb(ramp_stops
+ ((num
- 1) * 5 + 1));
139 data
[pos
] = last_color
;
142 data
[size
-1] = last_color
;
145 static INLINE
struct pipe_texture
*create_gradient_texture(struct vg_paint
*p
)
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
;
152 memset(&templ
, 0, sizeof(templ
));
153 templ
.target
= PIPE_TEXTURE_1D
;
154 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
155 templ
.last_level
= 0;
159 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
161 tex
= screen
->texture_create(screen
, &templ
);
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
);
176 struct vg_paint
* paint_create(struct vg_context
*ctx
)
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
);
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
));
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;
200 memcpy(&paint
->pattern
.sampler
,
201 &paint
->gradient
.sampler
,
202 sizeof(struct pipe_sampler_state
));
207 void paint_destroy(struct vg_paint
*paint
)
209 struct vg_context
*ctx
= paint
->base
.ctx
;
210 if (paint
->pattern
.texture
)
211 pipe_texture_reference(&paint
->pattern
.texture
, NULL
);
213 vg_context_remove_object(ctx
, VG_OBJECT_PAINT
, paint
);
215 free(paint
->gradient
.ramp_stopsi
);
216 free(paint
->gradient
.ramp_stops
);
220 void paint_set_color(struct vg_paint
*paint
,
221 const VGfloat
*color
)
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];
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]);
234 static INLINE
void paint_color_buffer(struct vg_paint
*paint
, void *buffer
)
236 VGfloat
*map
= (VGfloat
*)buffer
;
237 memcpy(buffer
, paint
->solid
.color
, 4 * sizeof(VGfloat
));
244 static INLINE
void paint_linear_gradient_buffer(struct vg_paint
*paint
, void *buffer
)
246 struct vg_context
*ctx
= paint
->base
.ctx
;
247 VGfloat
*map
= (VGfloat
*)buffer
;
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]);
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
));
266 matrix_mult(&inv
, &mat
);
268 sizeof(struct matrix
));
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
;
275 debug_printf("Coords (%f, %f, %f, %f)\n",
276 map
[0], map
[1], map
[2], map
[3]);
281 static INLINE
void paint_radial_gradient_buffer(struct vg_paint
*paint
, void *buffer
)
283 VGfloat
*radialCoords
= paint
->gradient
.radial
.vals
;
284 struct vg_context
*ctx
= paint
->base
.ctx
;
286 VGfloat
*map
= (VGfloat
*)buffer
;
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];
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
));
307 matrix_mult(&inv
, &mat
);
309 sizeof(struct matrix
));
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
;
317 debug_printf("Coords (%f, %f, %f, %f)\n",
318 map
[0], map
[1], map
[2], map
[3]);
323 static INLINE
void paint_pattern_buffer(struct vg_paint
*paint
, void *buffer
)
325 struct vg_context
*ctx
= paint
->base
.ctx
;
327 VGfloat
*map
= (VGfloat
*)buffer
;
328 memcpy(map
, paint
->solid
.color
, 4 * sizeof(VGfloat
));
332 map
[6] = paint
->pattern
.texture
->width0
;
333 map
[7] = paint
->pattern
.texture
->height0
;
336 memcpy(&mat
, &ctx
->state
.vg
.fill_paint_to_user_matrix
,
337 sizeof(struct matrix
));
341 memcpy(&pm
, &ctx
->state
.vg
.path_user_to_surface_matrix
,
342 sizeof(struct matrix
));
344 matrix_mult(&pm
, &mat
);
345 memcpy(&mat
, &pm
, sizeof(struct matrix
));
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
;
354 void paint_set_type(struct vg_paint
*paint
, VGPaintType type
)
359 void paint_set_ramp_stops(struct vg_paint
*paint
, const VGfloat
*stops
,
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
};
365 const VGint num_stops
= num
/ 5;
368 paint
->gradient
.num_stops
= 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
);
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*/
379 stops
= default_stops
;
382 last_coord
= stops
[0];
383 for (i
= 1; i
< num_stops
; ++i
) {
385 VGfloat coord
= stops
[idx
];
386 if (!floatsEqual(last_coord
, coord
) && coord
< last_coord
) {
387 stops
= default_stops
;
394 create_gradient_data(stops
, num
/ 5, paint
->gradient
.color_data
,
397 if (paint
->gradient
.texture
) {
398 pipe_texture_reference(&paint
->gradient
.texture
, NULL
);
399 paint
->gradient
.texture
= 0;
402 paint
->gradient
.texture
= create_gradient_texture(paint
);
405 void paint_set_colori(struct vg_paint
*p
,
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
;
414 VGuint
paint_colori(struct vg_paint
*p
)
416 #define F2B(f) (float_to_ubyte(f))
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));
425 void paint_set_linear_gradient(struct vg_paint
*paint
,
426 const VGfloat
*coords
)
428 memcpy(paint
->gradient
.linear
.coords
, coords
, sizeof(VGfloat
) * 4);
431 void paint_set_spread_mode(struct vg_paint
*paint
,
434 paint
->gradient
.spread
= mode
;
436 case VG_COLOR_RAMP_SPREAD_PAD
:
437 paint
->gradient
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
439 case VG_COLOR_RAMP_SPREAD_REPEAT
:
440 paint
->gradient
.sampler
.wrap_s
= PIPE_TEX_WRAP_REPEAT
;
442 case VG_COLOR_RAMP_SPREAD_REFLECT
:
443 paint
->gradient
.sampler
.wrap_s
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
448 VGColorRampSpreadMode
paint_spread_mode(struct vg_paint
*paint
)
450 return paint
->gradient
.spread
;
453 void paint_set_radial_gradient(struct vg_paint
*paint
,
454 const VGfloat
*values
)
456 memcpy(paint
->gradient
.radial
.vals
, values
, sizeof(VGfloat
) * 5);
459 void paint_set_pattern(struct vg_paint
*paint
,
460 struct vg_image
*img
)
462 if (paint
->pattern
.texture
)
463 pipe_texture_reference(&paint
->pattern
.texture
, NULL
);
465 paint
->pattern
.texture
= 0;
466 pipe_texture_reference(&paint
->pattern
.texture
,
470 void paint_set_pattern_tiling(struct vg_paint
*paint
,
473 paint
->pattern
.tiling_mode
= mode
;
477 paint
->pattern
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
478 paint
->pattern
.sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
481 paint
->pattern
.sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
482 paint
->pattern
.sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
485 paint
->pattern
.sampler
.wrap_s
= PIPE_TEX_WRAP_REPEAT
;
486 paint
->pattern
.sampler
.wrap_t
= PIPE_TEX_WRAP_REPEAT
;
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
;
493 debug_assert("!Unknown tiling mode");
497 void paint_get_color(struct vg_paint
*paint
,
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];
506 void paint_ramp_stops(struct vg_paint
*paint
, VGfloat
*stops
,
509 memcpy(stops
, paint
->gradient
.ramp_stops
, sizeof(VGfloat
)*num
);
512 void paint_linear_gradient(struct vg_paint
*paint
,
515 memcpy(coords
, paint
->gradient
.linear
.coords
, sizeof(VGfloat
)*4);
518 void paint_radial_gradient(struct vg_paint
*paint
,
521 memcpy(coords
, paint
->gradient
.radial
.vals
, sizeof(VGfloat
)*5);
524 int paint_num_ramp_stops(struct vg_paint
*paint
)
526 return paint
->gradient
.num_stops
;
529 VGPaintType
paint_type(struct vg_paint
*paint
)
534 void paint_set_coloriv(struct vg_paint
*paint
,
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];
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];
548 void paint_get_coloriv(struct vg_paint
*paint
,
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];
557 void paint_set_color_ramp_premultiplied(struct vg_paint
*paint
,
560 paint
->gradient
.color_ramps_premultiplied
= set
;
563 VGboolean
paint_color_ramp_premultiplied(struct vg_paint
*paint
)
565 return paint
->gradient
.color_ramps_premultiplied
;
568 void paint_set_ramp_stopsi(struct vg_paint
*paint
, const VGint
*stops
,
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
);
578 void paint_ramp_stopsi(struct vg_paint
*paint
, VGint
*stops
,
581 memcpy(stops
, paint
->gradient
.ramp_stopsi
, sizeof(VGint
)*num
);
584 void paint_set_linear_gradienti(struct vg_paint
*paint
,
587 memcpy(paint
->gradient
.linear
.coordsi
, coords
, sizeof(VGint
) * 4);
590 void paint_linear_gradienti(struct vg_paint
*paint
,
593 memcpy(coords
, paint
->gradient
.linear
.coordsi
, sizeof(VGint
)*4);
596 void paint_set_radial_gradienti(struct vg_paint
*paint
,
599 memcpy(paint
->gradient
.radial
.valsi
, values
, sizeof(VGint
) * 5);
602 void paint_radial_gradienti(struct vg_paint
*paint
,
605 memcpy(coords
, paint
->gradient
.radial
.valsi
, sizeof(VGint
)*5);
608 VGTilingMode
paint_pattern_tiling(struct vg_paint
*paint
)
610 return paint
->pattern
.tiling_mode
;
613 VGint
paint_bind_samplers(struct vg_paint
*paint
, struct pipe_sampler_state
**samplers
,
614 struct pipe_texture
**textures
)
616 struct vg_context
*ctx
= vg_current_context();
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
;
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
;
647 void paint_resolve_type(struct vg_paint
*paint
)
649 if (paint
->type
== VG_PAINT_TYPE_PATTERN
&&
650 !paint
->pattern
.texture
) {
651 paint
->type
= VG_PAINT_TYPE_COLOR
;
655 VGint
paint_constant_buffer_size(struct vg_paint
*paint
)
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)*/
661 case VG_PAINT_TYPE_LINEAR_GRADIENT
:
662 return 20 * sizeof(VGfloat
);
664 case VG_PAINT_TYPE_RADIAL_GRADIENT
:
665 return 20 * sizeof(VGfloat
);
667 case VG_PAINT_TYPE_PATTERN
:
668 return 20 * sizeof(VGfloat
);
671 debug_printf("Uknown paint type: %d\n", paint
->type
);
677 void paint_fill_constant_buffer(struct vg_paint
*paint
,
680 switch(paint
->type
) {
681 case VG_PAINT_TYPE_COLOR
:
682 paint_color_buffer(paint
, buffer
);
684 case VG_PAINT_TYPE_LINEAR_GRADIENT
:
685 paint_linear_gradient_buffer(paint
, buffer
);
687 case VG_PAINT_TYPE_RADIAL_GRADIENT
:
688 paint_radial_gradient_buffer(paint
, buffer
);
690 case VG_PAINT_TYPE_PATTERN
:
691 paint_pattern_buffer(paint
, buffer
);