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