paint.c revision b43c182f19c6291c88420fa12714f952c2b461fb
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 "util/u_inlines.h" 36 37#include "util/u_format.h" 38#include "util/u_memory.h" 39#include "util/u_math.h" 40 41#include "cso_cache/cso_context.h" 42 43struct vg_paint { 44 struct vg_object base; 45 46 VGPaintType type; 47 48 struct { 49 VGfloat color[4]; 50 VGint colori[4]; 51 } solid; 52 53 struct { 54 VGColorRampSpreadMode spread; 55 VGuint color_data[1024]; 56 struct { 57 VGfloat coords[4]; 58 VGint coordsi[4]; 59 } linear; 60 struct { 61 VGfloat vals[5]; 62 VGint valsi[5]; 63 } radial; 64 struct pipe_texture *texture; 65 struct pipe_sampler_state sampler; 66 67 VGfloat *ramp_stops; 68 VGint *ramp_stopsi; 69 VGint num_stops; 70 71 VGboolean color_ramps_premultiplied; 72 } gradient; 73 74 struct { 75 struct pipe_texture *texture; 76 VGTilingMode tiling_mode; 77 struct pipe_sampler_state sampler; 78 } pattern; 79 80 /* XXX next 3 all unneded? */ 81 struct pipe_buffer *cbuf; 82 struct pipe_shader_state fs_state; 83 void *fs; 84}; 85 86static INLINE VGuint mix_pixels(VGuint p1, VGuint a, VGuint p2, VGuint b) 87{ 88 VGuint t = (p1 & 0xff00ff) * a + (p2 & 0xff00ff) * b; 89 t >>= 8; t &= 0xff00ff; 90 91 p1 = ((p1 >> 8) & 0xff00ff) * a + ((p2 >> 8) & 0xff00ff) * b; 92 p1 &= 0xff00ff00; p1 |= t; 93 94 return p1; 95} 96 97static INLINE VGuint float4_to_argb(const VGfloat *clr) 98{ 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; 103} 104 105static INLINE void create_gradient_data(const VGfloat *ramp_stops, 106 VGint num, 107 VGuint *data, 108 VGint size) 109{ 110 VGint i; 111 VGint pos = 0; 112 VGfloat fpos = 0, incr = 1.f / size; 113 VGuint last_color; 114 115 while (fpos < ramp_stops[0]) { 116 data[pos] = float4_to_argb(ramp_stops + 1); 117 fpos += incr; 118 ++pos; 119 } 120 121 for (i = 0; i < num - 1; ++i) { 122 VGint rcur = 5 * 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, 131 next_color, dist); 132 fpos += incr; 133 ++pos; 134 } 135 } 136 137 last_color = float4_to_argb(ramp_stops + ((num - 1) * 5 + 1)); 138 while (pos < size) { 139 data[pos] = last_color; 140 ++pos; 141 } 142 data[size-1] = last_color; 143} 144 145static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) 146{ 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; 151 152 memset(&templ, 0, sizeof(templ)); 153 templ.target = PIPE_TEXTURE_1D; 154 templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; 155 templ.last_level = 0; 156 templ.width0 = 1024; 157 templ.height0 = 1; 158 templ.depth0 = 1; 159 templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; 160 161 tex = screen->texture_create(screen, &templ); 162 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(transfer); 171 } 172 173 return tex; 174} 175 176struct vg_paint * paint_create(struct vg_context *ctx) 177{ 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); 184 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)); 193 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; 199 200 memcpy(&paint->pattern.sampler, 201 &paint->gradient.sampler, 202 sizeof(struct pipe_sampler_state)); 203 204 return paint; 205} 206 207void paint_destroy(struct vg_paint *paint) 208{ 209 struct vg_context *ctx = paint->base.ctx; 210 if (paint->pattern.texture) 211 pipe_texture_reference(&paint->pattern.texture, NULL); 212 if (ctx) 213 vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint); 214 215 free(paint->gradient.ramp_stopsi); 216 free(paint->gradient.ramp_stops); 217 free(paint); 218} 219 220void paint_set_color(struct vg_paint *paint, 221 const VGfloat *color) 222{ 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]; 227 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]); 232} 233 234static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer) 235{ 236 VGfloat *map = (VGfloat*)buffer; 237 memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat)); 238 map[4] = 0.f; 239 map[5] = 1.f; 240 map[6] = 2.f; 241 map[7] = 4.f; 242} 243 244static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer) 245{ 246 struct vg_context *ctx = paint->base.ctx; 247 VGfloat *map = (VGfloat*)buffer; 248 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]); 252 map[3] = 1.f; 253 254 map[4] = 0.f; 255 map[5] = 1.f; 256 map[6] = 2.f; 257 map[7] = 4.f; 258 { 259 struct matrix mat; 260 struct matrix inv; 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)); 265 matrix_invert(&inv); 266 matrix_mult(&inv, &mat); 267 memcpy(&mat, &inv, 268 sizeof(struct matrix)); 269 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; 273 } 274#if 0 275 debug_printf("Coords (%f, %f, %f, %f)\n", 276 map[0], map[1], map[2], map[3]); 277#endif 278} 279 280 281static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer) 282{ 283 VGfloat *radialCoords = paint->gradient.radial.vals; 284 struct vg_context *ctx = paint->base.ctx; 285 286 VGfloat *map = (VGfloat*)buffer; 287 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]; 292 map[3] = 1.f; 293 294 map[4] = 0.f; 295 map[5] = 1.f; 296 map[6] = 2.f; 297 map[7] = 4.f; 298 299 { 300 struct matrix mat; 301 struct matrix inv; 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)); 306 matrix_invert(&inv); 307 matrix_mult(&inv, &mat); 308 memcpy(&mat, &inv, 309 sizeof(struct matrix)); 310 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; 314 } 315 316#if 0 317 debug_printf("Coords (%f, %f, %f, %f)\n", 318 map[0], map[1], map[2], map[3]); 319#endif 320} 321 322 323static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer) 324{ 325 struct vg_context *ctx = paint->base.ctx; 326 327 VGfloat *map = (VGfloat *)buffer; 328 memcpy(map, paint->solid.color, 4 * sizeof(VGfloat)); 329 330 map[4] = 0.f; 331 map[5] = 1.f; 332 map[6] = paint->pattern.texture->width0; 333 map[7] = paint->pattern.texture->height0; 334 { 335 struct matrix mat; 336 memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix, 337 sizeof(struct matrix)); 338 matrix_invert(&mat); 339 { 340 struct matrix pm; 341 memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix, 342 sizeof(struct matrix)); 343 matrix_invert(&pm); 344 matrix_mult(&pm, &mat); 345 memcpy(&mat, &pm, sizeof(struct matrix)); 346 } 347 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; 351 } 352} 353 354void paint_set_type(struct vg_paint *paint, VGPaintType type) 355{ 356 paint->type = type; 357} 358 359void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, 360 int num) 361{ 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}; 364 VGint i; 365 const VGint num_stops = num / 5; 366 VGfloat last_coord; 367 368 paint->gradient.num_stops = num; 369 if (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); 373 } else 374 return; 375 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*/ 378 if (stops[0] > 1) { 379 stops = default_stops; 380 num = 10; 381 } 382 last_coord = stops[0]; 383 for (i = 1; i < num_stops; ++i) { 384 VGint idx = 5 * i; 385 VGfloat coord = stops[idx]; 386 if (!floatsEqual(last_coord, coord) && coord < last_coord) { 387 stops = default_stops; 388 num = 10; 389 break; 390 } 391 last_coord = coord; 392 } 393 394 create_gradient_data(stops, num / 5, paint->gradient.color_data, 395 1024); 396 397 if (paint->gradient.texture) { 398 pipe_texture_reference(&paint->gradient.texture, NULL); 399 paint->gradient.texture = 0; 400 } 401 402 paint->gradient.texture = create_gradient_texture(paint); 403} 404 405void paint_set_colori(struct vg_paint *p, 406 VGuint rgba) 407{ 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; 412} 413 414VGuint paint_colori(struct vg_paint *p) 415{ 416#define F2B(f) (float_to_ubyte(f)) 417 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)); 422#undef F2B 423} 424 425void paint_set_linear_gradient(struct vg_paint *paint, 426 const VGfloat *coords) 427{ 428 memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4); 429} 430 431void paint_set_spread_mode(struct vg_paint *paint, 432 VGint mode) 433{ 434 paint->gradient.spread = mode; 435 switch(mode) { 436 case VG_COLOR_RAMP_SPREAD_PAD: 437 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 438 break; 439 case VG_COLOR_RAMP_SPREAD_REPEAT: 440 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; 441 break; 442 case VG_COLOR_RAMP_SPREAD_REFLECT: 443 paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT; 444 break; 445 } 446} 447 448VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint) 449{ 450 return paint->gradient.spread; 451} 452 453void paint_set_radial_gradient(struct vg_paint *paint, 454 const VGfloat *values) 455{ 456 memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5); 457} 458 459void paint_set_pattern(struct vg_paint *paint, 460 struct vg_image *img) 461{ 462 if (paint->pattern.texture) 463 pipe_texture_reference(&paint->pattern.texture, NULL); 464 465 paint->pattern.texture = 0; 466 pipe_texture_reference(&paint->pattern.texture, 467 img->texture); 468} 469 470void paint_set_pattern_tiling(struct vg_paint *paint, 471 VGTilingMode mode) 472{ 473 paint->pattern.tiling_mode = mode; 474 475 switch(mode) { 476 case VG_TILE_FILL: 477 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 478 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 479 break; 480 case VG_TILE_PAD: 481 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 482 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 483 break; 484 case VG_TILE_REPEAT: 485 paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; 486 paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; 487 break; 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; 491 break; 492 default: 493 debug_assert("!Unknown tiling mode"); 494 } 495} 496 497void paint_get_color(struct vg_paint *paint, 498 VGfloat *color) 499{ 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]; 504} 505 506void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops, 507 int num) 508{ 509 memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num); 510} 511 512void paint_linear_gradient(struct vg_paint *paint, 513 VGfloat *coords) 514{ 515 memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4); 516} 517 518void paint_radial_gradient(struct vg_paint *paint, 519 VGfloat *coords) 520{ 521 memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5); 522} 523 524int paint_num_ramp_stops(struct vg_paint *paint) 525{ 526 return paint->gradient.num_stops; 527} 528 529VGPaintType paint_type(struct vg_paint *paint) 530{ 531 return paint->type; 532} 533 534void paint_set_coloriv(struct vg_paint *paint, 535 const VGint *color) 536{ 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]; 541 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]; 546} 547 548void paint_get_coloriv(struct vg_paint *paint, 549 VGint *color) 550{ 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]; 555} 556 557void paint_set_color_ramp_premultiplied(struct vg_paint *paint, 558 VGboolean set) 559{ 560 paint->gradient.color_ramps_premultiplied = set; 561} 562 563VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint) 564{ 565 return paint->gradient.color_ramps_premultiplied; 566} 567 568void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops, 569 int num) 570{ 571 if (num) { 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); 575 } 576} 577 578void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops, 579 int num) 580{ 581 memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num); 582} 583 584void paint_set_linear_gradienti(struct vg_paint *paint, 585 const VGint *coords) 586{ 587 memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4); 588} 589 590void paint_linear_gradienti(struct vg_paint *paint, 591 VGint *coords) 592{ 593 memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4); 594} 595 596void paint_set_radial_gradienti(struct vg_paint *paint, 597 const VGint *values) 598{ 599 memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5); 600} 601 602void paint_radial_gradienti(struct vg_paint *paint, 603 VGint *coords) 604{ 605 memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5); 606} 607 608VGTilingMode paint_pattern_tiling(struct vg_paint *paint) 609{ 610 return paint->pattern.tiling_mode; 611} 612 613VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, 614 struct pipe_texture **textures) 615{ 616 struct vg_context *ctx = vg_current_context(); 617 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; 626 return 1; 627 } 628 } 629 break; 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; 638 return 1; 639 } 640 break; 641 default: 642 break; 643 } 644 return 0; 645} 646 647void paint_resolve_type(struct vg_paint *paint) 648{ 649 if (paint->type == VG_PAINT_TYPE_PATTERN && 650 !paint->pattern.texture) { 651 paint->type = VG_PAINT_TYPE_COLOR; 652 } 653} 654 655VGint paint_constant_buffer_size(struct vg_paint *paint) 656{ 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)*/ 660 break; 661 case VG_PAINT_TYPE_LINEAR_GRADIENT: 662 return 20 * sizeof(VGfloat); 663 break; 664 case VG_PAINT_TYPE_RADIAL_GRADIENT: 665 return 20 * sizeof(VGfloat); 666 break; 667 case VG_PAINT_TYPE_PATTERN: 668 return 20 * sizeof(VGfloat); 669 break; 670 default: 671 debug_printf("Uknown paint type: %d\n", paint->type); 672 } 673 674 return 0; 675} 676 677void paint_fill_constant_buffer(struct vg_paint *paint, 678 void *buffer) 679{ 680 switch(paint->type) { 681 case VG_PAINT_TYPE_COLOR: 682 paint_color_buffer(paint, buffer); 683 break; 684 case VG_PAINT_TYPE_LINEAR_GRADIENT: 685 paint_linear_gradient_buffer(paint, buffer); 686 break; 687 case VG_PAINT_TYPE_RADIAL_GRADIENT: 688 paint_radial_gradient_buffer(paint, buffer); 689 break; 690 case VG_PAINT_TYPE_PATTERN: 691 paint_pattern_buffer(paint, buffer); 692 break; 693 694 default: 695 abort(); 696 } 697} 698