api_filters.c revision 75143ef05576ee9f25ee176bc28c3c4d03705bf5
19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/************************************************************************** 29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Copyright 2009 VMware, Inc. All Rights Reserved. 49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Permission is hereby granted, free of charge, to any person obtaining a 69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * copy of this software and associated documentation files (the 79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * "Software"), to deal in the Software without restriction, including 89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * without limitation the rights to use, copy, modify, merge, publish, 99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * distribute, sub license, and/or sell copies of the Software, and to 109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * permit persons to whom the Software is furnished to do so, subject to 119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * the following conditions: 129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * The above copyright notice and this permission notice (including the 149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * next paragraph) shall be included in all copies or substantial portions 159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * of the Software. 169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * 259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall **************************************************************************/ 269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "VG/openvg.h" 289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "vg_context.h" 309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "image.h" 319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "api.h" 329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "renderer.h" 339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "shaders_cache.h" 349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "st_inlines.h" 359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "pipe/p_context.h" 379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "pipe/p_state.h" 389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "util/u_inlines.h" 399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "pipe/p_screen.h" 409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "pipe/p_shader_tokens.h" 419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "util/u_format.h" 439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "util/u_memory.h" 449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "util/u_sampler.h" 459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "asm_filters.h" 489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct filter_info { 519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct vg_image *dst; 529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct vg_image *src; 539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct vg_shader * (*setup_shader)(struct vg_context *, void *); 549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall void *user_data; 559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall const void *const_buffer; 569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall VGint const_buffer_len; 579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall VGTilingMode tiling_mode; 589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_sampler_view *extra_texture_view; 599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}; 609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, 629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall const VGuint *color_data, 639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall const VGint color_data_len) 649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{ 659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_context *pipe = ctx->pipe; 669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_screen *screen = pipe->screen; 679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_resource *tex = 0; 689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_resource templ; 699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall memset(&templ, 0, sizeof(templ)); 719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.target = PIPE_TEXTURE_1D; 729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; 739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.last_level = 0; 749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.width0 = color_data_len; 759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.height0 = 1; 769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.depth0 = 1; 779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall templ.bind = PIPE_BIND_SAMPLER_VIEW; 789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall tex = screen->resource_create(screen, &templ); 809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall { /* upload color_data */ 829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall struct pipe_transfer *transfer = 839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall pipe_get_transfer(pipe, tex, 849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 0, 0, 0, 859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall PIPE_TRANSFER_READ_WRITE , 869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall 0, 0, tex->width0, tex->height0); 879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall void *map = pipe->transfer_map(pipe, transfer); 889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall memcpy(map, color_data, sizeof(VGint)*color_data_len); 899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall pipe->transfer_unmap(pipe, transfer); 909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall pipe->transfer_destroy(pipe, transfer); 919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall } 92 93 return tex; 94} 95 96static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx, 97 const VGuint *color_data, 98 const VGint color_data_len) 99{ 100 struct pipe_context *pipe = ctx->pipe; 101 struct pipe_resource *texture; 102 struct pipe_sampler_view view_templ; 103 struct pipe_sampler_view *view; 104 105 texture = create_texture_1d(ctx, color_data, color_data_len); 106 107 if (!texture) 108 return NULL; 109 110 u_sampler_view_default_template(&view_templ, texture, texture->format); 111 view = pipe->create_sampler_view(pipe, texture, &view_templ); 112 /* want the texture to go away if the view is freed */ 113 pipe_resource_reference(&texture, NULL); 114 115 return view; 116} 117 118static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst) 119{ 120 struct vg_context *ctx = vg_current_context(); 121 struct pipe_context *pipe = ctx->pipe; 122 struct pipe_framebuffer_state fb; 123 struct pipe_surface *dst_surf = pipe->screen->get_tex_surface( 124 pipe->screen, dst->sampler_view->texture, 0, 0, 0, 125 PIPE_BIND_RENDER_TARGET); 126 127 /* drawing dest */ 128 memset(&fb, 0, sizeof(fb)); 129 fb.width = dst->x + dst_surf->width; 130 fb.height = dst->y + dst_surf->height; 131 fb.nr_cbufs = 1; 132 fb.cbufs[0] = dst_surf; 133 { 134 VGint i; 135 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) 136 fb.cbufs[i] = 0; 137 } 138 cso_set_framebuffer(ctx->cso_context, &fb); 139 140 return dst_surf; 141} 142 143static void setup_viewport(struct vg_image *dst) 144{ 145 struct vg_context *ctx = vg_current_context(); 146 vg_set_viewport(ctx, VEGA_Y0_TOP); 147} 148 149static void setup_blend() 150{ 151 struct vg_context *ctx = vg_current_context(); 152 struct pipe_blend_state blend; 153 memset(&blend, 0, sizeof(blend)); 154 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 155 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 156 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 157 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 158 if (ctx->state.vg.filter_channel_mask & VG_RED) 159 blend.rt[0].colormask |= PIPE_MASK_R; 160 if (ctx->state.vg.filter_channel_mask & VG_GREEN) 161 blend.rt[0].colormask |= PIPE_MASK_G; 162 if (ctx->state.vg.filter_channel_mask & VG_BLUE) 163 blend.rt[0].colormask |= PIPE_MASK_B; 164 if (ctx->state.vg.filter_channel_mask & VG_ALPHA) 165 blend.rt[0].colormask |= PIPE_MASK_A; 166 blend.rt[0].blend_enable = 0; 167 cso_set_blend(ctx->cso_context, &blend); 168} 169 170static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, 171 VGint param_bytes) 172{ 173 struct pipe_context *pipe = ctx->pipe; 174 struct pipe_resource **cbuf = &ctx->filter.buffer; 175 176 /* We always need to get a new buffer, to keep the drivers simple and 177 * avoid gratuitous rendering synchronization. */ 178 pipe_resource_reference(cbuf, NULL); 179 180 *cbuf = pipe_buffer_create(pipe->screen, 181 PIPE_BIND_CONSTANT_BUFFER, 182 param_bytes); 183 184 if (*cbuf) { 185 st_no_flush_pipe_buffer_write(ctx, *cbuf, 186 0, param_bytes, buffer); 187 } 188 189 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf); 190} 191 192static void setup_samplers(struct vg_context *ctx, struct filter_info *info) 193{ 194 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; 195 struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 196 struct pipe_sampler_state sampler[3]; 197 int num_samplers = 0; 198 int num_textures = 0; 199 200 samplers[0] = NULL; 201 samplers[1] = NULL; 202 samplers[2] = NULL; 203 samplers[3] = NULL; 204 sampler_views[0] = NULL; 205 sampler_views[1] = NULL; 206 sampler_views[2] = NULL; 207 sampler_views[3] = NULL; 208 209 memset(&sampler[0], 0, sizeof(struct pipe_sampler_state)); 210 sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 211 sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 212 sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 213 sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR; 214 sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR; 215 sampler[0].normalized_coords = 1; 216 217 switch(info->tiling_mode) { 218 case VG_TILE_FILL: 219 sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 220 sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER; 221 memcpy(sampler[0].border_color, 222 ctx->state.vg.tile_fill_color, 223 sizeof(VGfloat) * 4); 224 break; 225 case VG_TILE_PAD: 226 sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 227 sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 228 break; 229 case VG_TILE_REPEAT: 230 sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT; 231 sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT; 232 break; 233 case VG_TILE_REFLECT: 234 sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT; 235 sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT; 236 break; 237 default: 238 debug_assert(!"Unknown tiling mode"); 239 } 240 241 samplers[0] = &sampler[0]; 242 sampler_views[0] = info->src->sampler_view; 243 ++num_samplers; 244 ++num_textures; 245 246 if (info->extra_texture_view) { 247 memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state)); 248 samplers[1] = &sampler[1]; 249 sampler_views[1] = info->extra_texture_view; 250 ++num_samplers; 251 ++num_textures; 252 } 253 254 255 cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers); 256 cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views); 257} 258 259static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data) 260{ 261 struct vg_shader *shader = 262 shader_create_from_text(ctx->pipe, color_matrix_asm, 200, 263 PIPE_SHADER_FRAGMENT); 264 cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); 265 return shader; 266} 267 268static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_data) 269{ 270 char buffer[1024]; 271 VGint num_consts = (VGint)(long)(user_data); 272 struct vg_shader *shader; 273 274 snprintf(buffer, 1023, convolution_asm, num_consts, num_consts / 2 + 1); 275 276 shader = shader_create_from_text(ctx->pipe, buffer, 200, 277 PIPE_SHADER_FRAGMENT); 278 279 cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); 280 return shader; 281} 282 283static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data) 284{ 285 struct vg_shader *shader = 286 shader_create_from_text(ctx->pipe, lookup_asm, 287 200, PIPE_SHADER_FRAGMENT); 288 289 cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); 290 return shader; 291} 292 293 294static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user_data) 295{ 296 char buffer[1024]; 297 VGImageChannel channel = (VGImageChannel)(user_data); 298 struct vg_shader *shader; 299 300 switch(channel) { 301 case VG_RED: 302 snprintf(buffer, 1023, lookup_single_asm, "xxxx"); 303 break; 304 case VG_GREEN: 305 snprintf(buffer, 1023, lookup_single_asm, "yyyy"); 306 break; 307 case VG_BLUE: 308 snprintf(buffer, 1023, lookup_single_asm, "zzzz"); 309 break; 310 case VG_ALPHA: 311 snprintf(buffer, 1023, lookup_single_asm, "wwww"); 312 break; 313 default: 314 debug_assert(!"Unknown color channel"); 315 } 316 317 shader = shader_create_from_text(ctx->pipe, buffer, 200, 318 PIPE_SHADER_FRAGMENT); 319 320 cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); 321 return shader; 322} 323 324static void execute_filter(struct vg_context *ctx, 325 struct filter_info *info) 326{ 327 struct pipe_surface *dst_surf; 328 struct vg_shader *shader; 329 330 cso_save_framebuffer(ctx->cso_context); 331 cso_save_fragment_shader(ctx->cso_context); 332 cso_save_viewport(ctx->cso_context); 333 cso_save_blend(ctx->cso_context); 334 cso_save_samplers(ctx->cso_context); 335 cso_save_fragment_sampler_views(ctx->cso_context); 336 337 dst_surf = setup_framebuffer(info->dst); 338 setup_viewport(info->dst); 339 setup_blend(); 340 setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len); 341 shader = info->setup_shader(ctx, info->user_data); 342 setup_samplers(ctx, info); 343 344 renderer_draw_texture(ctx->renderer, 345 info->src->sampler_view->texture, 346 info->dst->x, info->dst->y, 347 info->dst->x + info->dst->width, 348 info->dst->y + info->dst->height, 349 info->dst->x, info->dst->y, 350 info->dst->x + info->dst->width, 351 info->dst->y + info->dst->height); 352 353 cso_restore_framebuffer(ctx->cso_context); 354 cso_restore_fragment_shader(ctx->cso_context); 355 cso_restore_viewport(ctx->cso_context); 356 cso_restore_blend(ctx->cso_context); 357 cso_restore_samplers(ctx->cso_context); 358 cso_restore_fragment_sampler_views(ctx->cso_context); 359 360 vg_shader_destroy(ctx, shader); 361 362 pipe_surface_reference(&dst_surf, NULL); 363} 364 365void vegaColorMatrix(VGImage dst, VGImage src, 366 const VGfloat * matrix) 367{ 368 struct vg_context *ctx = vg_current_context(); 369 struct vg_image *d, *s; 370 struct filter_info info; 371 372 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 373 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 374 return; 375 } 376 if (!matrix || !is_aligned(matrix)) { 377 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 378 return; 379 } 380 381 d = (struct vg_image*)dst; 382 s = (struct vg_image*)src; 383 384 if (vg_image_overlaps(d, s)) { 385 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 386 return; 387 } 388 389 info.dst = d; 390 info.src = s; 391 info.setup_shader = &setup_color_matrix; 392 info.user_data = NULL; 393 info.const_buffer = matrix; 394 info.const_buffer_len = 20 * sizeof(VGfloat); 395 info.tiling_mode = VG_TILE_PAD; 396 info.extra_texture_view = NULL; 397 execute_filter(ctx, &info); 398} 399 400static VGfloat texture_offset(VGfloat width, VGint kernelSize, VGint current, VGint shift) 401{ 402 VGfloat diff = current - shift; 403 404 return diff / width; 405} 406 407void vegaConvolve(VGImage dst, VGImage src, 408 VGint kernelWidth, VGint kernelHeight, 409 VGint shiftX, VGint shiftY, 410 const VGshort * kernel, 411 VGfloat scale, 412 VGfloat bias, 413 VGTilingMode tilingMode) 414{ 415 struct vg_context *ctx = vg_current_context(); 416 VGfloat *buffer; 417 VGint buffer_len; 418 VGint i, j; 419 VGint idx = 0; 420 struct vg_image *d, *s; 421 VGint kernel_size = kernelWidth * kernelHeight; 422 struct filter_info info; 423 const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE); 424 425 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 426 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 427 return; 428 } 429 430 if (kernelWidth <= 0 || kernelHeight <= 0 || 431 kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) { 432 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 433 return; 434 } 435 436 if (!kernel || !is_aligned_to(kernel, 2)) { 437 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 438 return; 439 } 440 441 if (tilingMode < VG_TILE_FILL || 442 tilingMode > VG_TILE_REFLECT) { 443 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 444 return; 445 } 446 447 d = (struct vg_image*)dst; 448 s = (struct vg_image*)src; 449 450 if (vg_image_overlaps(d, s)) { 451 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 452 return; 453 } 454 455 vg_validate_state(ctx); 456 457 buffer_len = 8 + 2 * 4 * kernel_size; 458 buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat)); 459 460 buffer[0] = 0.f; 461 buffer[1] = 1.f; 462 buffer[2] = 2.f; /*unused*/ 463 buffer[3] = 4.f; /*unused*/ 464 465 buffer[4] = kernelWidth * kernelHeight; 466 buffer[5] = scale; 467 buffer[6] = bias; 468 buffer[7] = 0.f; 469 470 idx = 8; 471 for (j = 0; j < kernelHeight; ++j) { 472 for (i = 0; i < kernelWidth; ++i) { 473 VGint index = j * kernelWidth + i; 474 VGfloat x, y; 475 476 x = texture_offset(s->width, kernelWidth, i, shiftX); 477 y = texture_offset(s->height, kernelHeight, j, shiftY); 478 479 buffer[idx + index*4 + 0] = x; 480 buffer[idx + index*4 + 1] = y; 481 buffer[idx + index*4 + 2] = 0.f; 482 buffer[idx + index*4 + 3] = 0.f; 483 } 484 } 485 idx += kernel_size * 4; 486 487 for (j = 0; j < kernelHeight; ++j) { 488 for (i = 0; i < kernelWidth; ++i) { 489 /* transpose the kernel */ 490 VGint index = j * kernelWidth + i; 491 VGint kindex = (kernelWidth - i - 1) * kernelHeight + (kernelHeight - j - 1); 492 buffer[idx + index*4 + 0] = kernel[kindex]; 493 buffer[idx + index*4 + 1] = kernel[kindex]; 494 buffer[idx + index*4 + 2] = kernel[kindex]; 495 buffer[idx + index*4 + 3] = kernel[kindex]; 496 } 497 } 498 499 info.dst = d; 500 info.src = s; 501 info.setup_shader = &setup_convolution; 502 info.user_data = (void*)(long)(buffer_len/4); 503 info.const_buffer = buffer; 504 info.const_buffer_len = buffer_len * sizeof(VGfloat); 505 info.tiling_mode = tilingMode; 506 info.extra_texture_view = NULL; 507 execute_filter(ctx, &info); 508 509 free(buffer); 510} 511 512void vegaSeparableConvolve(VGImage dst, VGImage src, 513 VGint kernelWidth, 514 VGint kernelHeight, 515 VGint shiftX, VGint shiftY, 516 const VGshort * kernelX, 517 const VGshort * kernelY, 518 VGfloat scale, 519 VGfloat bias, 520 VGTilingMode tilingMode) 521{ 522 struct vg_context *ctx = vg_current_context(); 523 VGshort *kernel; 524 VGint i, j, idx = 0; 525 const VGint max_kernel_size = vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE); 526 527 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 528 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 529 return; 530 } 531 532 if (kernelWidth <= 0 || kernelHeight <= 0 || 533 kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) { 534 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 535 return; 536 } 537 538 if (!kernelX || !kernelY || 539 !is_aligned_to(kernelX, 2) || !is_aligned_to(kernelY, 2)) { 540 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 541 return; 542 } 543 if (tilingMode < VG_TILE_FILL || 544 tilingMode > VG_TILE_REFLECT) { 545 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 546 return; 547 } 548 kernel = malloc(sizeof(VGshort)*kernelWidth*kernelHeight); 549 for (i = 0; i < kernelWidth; ++i) { 550 for (j = 0; j < kernelHeight; ++j) { 551 kernel[idx] = kernelX[i] * kernelY[j]; 552 ++idx; 553 } 554 } 555 vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY, 556 kernel, scale, bias, tilingMode); 557 free(kernel); 558} 559 560static INLINE VGfloat compute_gaussian_componenet(VGfloat x, VGfloat y, 561 VGfloat stdDeviationX, 562 VGfloat stdDeviationY) 563{ 564 VGfloat mult = 1 / ( 2 * M_PI * stdDeviationX * stdDeviationY); 565 VGfloat e = exp( - ( pow(x, 2)/(2*pow(stdDeviationX, 2)) + 566 pow(y, 2)/(2*pow(stdDeviationY, 2)) ) ); 567 return mult * e; 568} 569 570static INLINE VGint compute_kernel_size(VGfloat deviation) 571{ 572 VGint size = ceil(2.146 * deviation); 573 if (size > 11) 574 return 11; 575 return size; 576} 577 578static void compute_gaussian_kernel(VGfloat *kernel, 579 VGint width, VGint height, 580 VGfloat stdDeviationX, 581 VGfloat stdDeviationY) 582{ 583 VGint i, j; 584 VGfloat scale = 0.0f; 585 586 for (j = 0; j < height; ++j) { 587 for (i = 0; i < width; ++i) { 588 VGint idx = (height - j -1) * width + (width - i -1); 589 kernel[idx] = compute_gaussian_componenet(i-(ceil(width/2))-1, 590 j-ceil(height/2)-1, 591 stdDeviationX, stdDeviationY); 592 scale += kernel[idx]; 593 } 594 } 595 596 for (j = 0; j < height; ++j) { 597 for (i = 0; i < width; ++i) { 598 VGint idx = j * width + i; 599 kernel[idx] /= scale; 600 } 601 } 602} 603 604void vegaGaussianBlur(VGImage dst, VGImage src, 605 VGfloat stdDeviationX, 606 VGfloat stdDeviationY, 607 VGTilingMode tilingMode) 608{ 609 struct vg_context *ctx = vg_current_context(); 610 struct vg_image *d, *s; 611 VGfloat *buffer, *kernel; 612 VGint kernel_width, kernel_height, kernel_size; 613 VGint buffer_len; 614 VGint idx, i, j; 615 struct filter_info info; 616 617 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 618 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 619 return; 620 } 621 if (stdDeviationX <= 0 || stdDeviationY <= 0) { 622 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 623 return; 624 } 625 626 if (tilingMode < VG_TILE_FILL || 627 tilingMode > VG_TILE_REFLECT) { 628 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 629 return; 630 } 631 632 d = (struct vg_image*)dst; 633 s = (struct vg_image*)src; 634 635 if (vg_image_overlaps(d, s)) { 636 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 637 return; 638 } 639 640 kernel_width = compute_kernel_size(stdDeviationX); 641 kernel_height = compute_kernel_size(stdDeviationY); 642 kernel_size = kernel_width * kernel_height; 643 kernel = malloc(sizeof(VGfloat)*kernel_size); 644 compute_gaussian_kernel(kernel, kernel_width, kernel_height, 645 stdDeviationX, stdDeviationY); 646 647 buffer_len = 8 + 2 * 4 * kernel_size; 648 buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat)); 649 650 buffer[0] = 0.f; 651 buffer[1] = 1.f; 652 buffer[2] = 2.f; /*unused*/ 653 buffer[3] = 4.f; /*unused*/ 654 655 buffer[4] = kernel_width * kernel_height; 656 buffer[5] = 1.f;/*scale*/ 657 buffer[6] = 0.f;/*bias*/ 658 buffer[7] = 0.f; 659 660 idx = 8; 661 for (j = 0; j < kernel_height; ++j) { 662 for (i = 0; i < kernel_width; ++i) { 663 VGint index = j * kernel_width + i; 664 VGfloat x, y; 665 666 x = texture_offset(s->width, kernel_width, i, kernel_width/2); 667 y = texture_offset(s->height, kernel_height, j, kernel_height/2); 668 669 buffer[idx + index*4 + 0] = x; 670 buffer[idx + index*4 + 1] = y; 671 buffer[idx + index*4 + 2] = 0.f; 672 buffer[idx + index*4 + 3] = 0.f; 673 } 674 } 675 idx += kernel_size * 4; 676 677 for (j = 0; j < kernel_height; ++j) { 678 for (i = 0; i < kernel_width; ++i) { 679 /* transpose the kernel */ 680 VGint index = j * kernel_width + i; 681 VGint kindex = (kernel_width - i - 1) * kernel_height + (kernel_height - j - 1); 682 buffer[idx + index*4 + 0] = kernel[kindex]; 683 buffer[idx + index*4 + 1] = kernel[kindex]; 684 buffer[idx + index*4 + 2] = kernel[kindex]; 685 buffer[idx + index*4 + 3] = kernel[kindex]; 686 } 687 } 688 689 info.dst = d; 690 info.src = s; 691 info.setup_shader = &setup_convolution; 692 info.user_data = (void*)(long)(buffer_len/4); 693 info.const_buffer = buffer; 694 info.const_buffer_len = buffer_len * sizeof(VGfloat); 695 info.tiling_mode = tilingMode; 696 info.extra_texture_view = NULL; 697 execute_filter(ctx, &info); 698 699 free(buffer); 700 free(kernel); 701} 702 703void vegaLookup(VGImage dst, VGImage src, 704 const VGubyte * redLUT, 705 const VGubyte * greenLUT, 706 const VGubyte * blueLUT, 707 const VGubyte * alphaLUT, 708 VGboolean outputLinear, 709 VGboolean outputPremultiplied) 710{ 711 struct vg_context *ctx = vg_current_context(); 712 struct vg_image *d, *s; 713 VGuint color_data[256]; 714 VGint i; 715 struct pipe_sampler_view *lut_texture_view; 716 VGfloat buffer[4]; 717 struct filter_info info; 718 719 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 720 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 721 return; 722 } 723 724 if (!redLUT || !greenLUT || !blueLUT || !alphaLUT) { 725 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 726 return; 727 } 728 729 d = (struct vg_image*)dst; 730 s = (struct vg_image*)src; 731 732 if (vg_image_overlaps(d, s)) { 733 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 734 return; 735 } 736 737 for (i = 0; i < 256; ++i) { 738 color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 | 739 redLUT[i] << 8 | alphaLUT[i]; 740 } 741 lut_texture_view = create_texture_1d_view(ctx, color_data, 255); 742 743 buffer[0] = 0.f; 744 buffer[1] = 0.f; 745 buffer[2] = 1.f; 746 buffer[3] = 1.f; 747 748 info.dst = d; 749 info.src = s; 750 info.setup_shader = &setup_lookup; 751 info.user_data = NULL; 752 info.const_buffer = buffer; 753 info.const_buffer_len = 4 * sizeof(VGfloat); 754 info.tiling_mode = VG_TILE_PAD; 755 info.extra_texture_view = lut_texture_view; 756 757 execute_filter(ctx, &info); 758 759 pipe_sampler_view_reference(&lut_texture_view, NULL); 760} 761 762void vegaLookupSingle(VGImage dst, VGImage src, 763 const VGuint * lookupTable, 764 VGImageChannel sourceChannel, 765 VGboolean outputLinear, 766 VGboolean outputPremultiplied) 767{ 768 struct vg_context *ctx = vg_current_context(); 769 struct vg_image *d, *s; 770 struct pipe_sampler_view *lut_texture_view; 771 VGfloat buffer[4]; 772 struct filter_info info; 773 VGuint color_data[256]; 774 VGint i; 775 776 if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { 777 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 778 return; 779 } 780 781 if (!lookupTable || !is_aligned(lookupTable)) { 782 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 783 return; 784 } 785 786 if (sourceChannel != VG_RED && sourceChannel != VG_GREEN && 787 sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA) { 788 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 789 return; 790 } 791 792 d = (struct vg_image*)dst; 793 s = (struct vg_image*)src; 794 795 if (vg_image_overlaps(d, s)) { 796 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 797 return; 798 } 799 800 for (i = 0; i < 256; ++i) { 801 VGuint rgba = lookupTable[i]; 802 VGubyte blue, green, red, alpha; 803 red = (rgba & 0xff000000)>>24; 804 green = (rgba & 0x00ff0000)>>16; 805 blue = (rgba & 0x0000ff00)>> 8; 806 alpha = (rgba & 0x000000ff)>> 0; 807 color_data[i] = blue << 24 | green << 16 | 808 red << 8 | alpha; 809 } 810 lut_texture_view = create_texture_1d_view(ctx, color_data, 256); 811 812 buffer[0] = 0.f; 813 buffer[1] = 0.f; 814 buffer[2] = 1.f; 815 buffer[3] = 1.f; 816 817 info.dst = d; 818 info.src = s; 819 info.setup_shader = &setup_lookup_single; 820 info.user_data = (void*)sourceChannel; 821 info.const_buffer = buffer; 822 info.const_buffer_len = 4 * sizeof(VGfloat); 823 info.tiling_mode = VG_TILE_PAD; 824 info.extra_texture_view = lut_texture_view; 825 826 execute_filter(ctx, &info); 827 828 pipe_sampler_view_reference(&lut_texture_view, NULL); 829} 830