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 **************************************************************************/
27 #include "VG/openvg.h"
29 #include "vg_context.h"
33 #include "shaders_cache.h"
34 #include "st_inlines.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_state.h"
38 #include "util/u_inlines.h"
39 #include "pipe/p_screen.h"
40 #include "pipe/p_shader_tokens.h"
42 #include "util/u_format.h"
43 #include "util/u_memory.h"
44 #include "util/u_sampler.h"
45 #include "util/u_string.h"
48 #include "asm_filters.h"
54 struct vg_shader
* (*setup_shader
)(struct vg_context
*, void *);
56 const void *const_buffer
;
57 VGint const_buffer_len
;
58 VGTilingMode tiling_mode
;
59 struct pipe_sampler_view
*extra_texture_view
;
62 static INLINE
struct pipe_resource
*create_texture_1d(struct vg_context
*ctx
,
63 const VGuint
*color_data
,
64 const VGint color_data_len
)
66 struct pipe_context
*pipe
= ctx
->pipe
;
67 struct pipe_screen
*screen
= pipe
->screen
;
68 struct pipe_resource
*tex
= 0;
69 struct pipe_resource templ
;
71 memset(&templ
, 0, sizeof(templ
));
72 templ
.target
= PIPE_TEXTURE_1D
;
73 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
75 templ
.width0
= color_data_len
;
78 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
80 tex
= screen
->resource_create(screen
, &templ
);
82 { /* upload color_data */
83 struct pipe_transfer
*transfer
=
84 pipe_get_transfer(pipe
, tex
,
86 PIPE_TRANSFER_READ_WRITE
,
87 0, 0, tex
->width0
, tex
->height0
);
88 void *map
= pipe
->transfer_map(pipe
, transfer
);
89 memcpy(map
, color_data
, sizeof(VGint
)*color_data_len
);
90 pipe
->transfer_unmap(pipe
, transfer
);
91 pipe
->transfer_destroy(pipe
, transfer
);
97 static INLINE
struct pipe_sampler_view
*create_texture_1d_view(struct vg_context
*ctx
,
98 const VGuint
*color_data
,
99 const VGint color_data_len
)
101 struct pipe_context
*pipe
= ctx
->pipe
;
102 struct pipe_resource
*texture
;
103 struct pipe_sampler_view view_templ
;
104 struct pipe_sampler_view
*view
;
106 texture
= create_texture_1d(ctx
, color_data
, color_data_len
);
111 u_sampler_view_default_template(&view_templ
, texture
, texture
->format
);
112 view
= pipe
->create_sampler_view(pipe
, texture
, &view_templ
);
113 /* want the texture to go away if the view is freed */
114 pipe_resource_reference(&texture
, NULL
);
119 static INLINE
struct pipe_surface
* setup_framebuffer(struct vg_image
*dst
)
121 struct vg_context
*ctx
= vg_current_context();
122 struct pipe_context
*pipe
= ctx
->pipe
;
123 struct pipe_framebuffer_state fb
;
124 struct pipe_surface
*dst_surf
= pipe
->screen
->get_tex_surface(
125 pipe
->screen
, dst
->sampler_view
->texture
, 0, 0, 0,
126 PIPE_BIND_RENDER_TARGET
);
129 memset(&fb
, 0, sizeof(fb
));
130 fb
.width
= dst
->x
+ dst_surf
->width
;
131 fb
.height
= dst
->y
+ dst_surf
->height
;
133 fb
.cbufs
[0] = dst_surf
;
136 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
139 cso_set_framebuffer(ctx
->cso_context
, &fb
);
144 static void setup_viewport(struct vg_image
*dst
)
146 struct vg_context
*ctx
= vg_current_context();
147 vg_set_viewport(ctx
, VEGA_Y0_TOP
);
150 static void setup_blend()
152 struct vg_context
*ctx
= vg_current_context();
153 struct pipe_blend_state blend
;
154 memset(&blend
, 0, sizeof(blend
));
155 blend
.rt
[0].rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
156 blend
.rt
[0].alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
157 blend
.rt
[0].rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
158 blend
.rt
[0].alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
159 if (ctx
->state
.vg
.filter_channel_mask
& VG_RED
)
160 blend
.rt
[0].colormask
|= PIPE_MASK_R
;
161 if (ctx
->state
.vg
.filter_channel_mask
& VG_GREEN
)
162 blend
.rt
[0].colormask
|= PIPE_MASK_G
;
163 if (ctx
->state
.vg
.filter_channel_mask
& VG_BLUE
)
164 blend
.rt
[0].colormask
|= PIPE_MASK_B
;
165 if (ctx
->state
.vg
.filter_channel_mask
& VG_ALPHA
)
166 blend
.rt
[0].colormask
|= PIPE_MASK_A
;
167 blend
.rt
[0].blend_enable
= 0;
168 cso_set_blend(ctx
->cso_context
, &blend
);
171 static void setup_constant_buffer(struct vg_context
*ctx
, const void *buffer
,
174 struct pipe_context
*pipe
= ctx
->pipe
;
175 struct pipe_resource
**cbuf
= &ctx
->filter
.buffer
;
177 /* We always need to get a new buffer, to keep the drivers simple and
178 * avoid gratuitous rendering synchronization. */
179 pipe_resource_reference(cbuf
, NULL
);
181 *cbuf
= pipe_buffer_create(pipe
->screen
,
182 PIPE_BIND_CONSTANT_BUFFER
,
186 st_no_flush_pipe_buffer_write(ctx
, *cbuf
,
187 0, param_bytes
, buffer
);
190 ctx
->pipe
->set_constant_buffer(ctx
->pipe
, PIPE_SHADER_FRAGMENT
, 0, *cbuf
);
193 static void setup_samplers(struct vg_context
*ctx
, struct filter_info
*info
)
195 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
196 struct pipe_sampler_view
*sampler_views
[PIPE_MAX_SAMPLERS
];
197 struct pipe_sampler_state sampler
[3];
198 int num_samplers
= 0;
199 int num_textures
= 0;
205 sampler_views
[0] = NULL
;
206 sampler_views
[1] = NULL
;
207 sampler_views
[2] = NULL
;
208 sampler_views
[3] = NULL
;
210 memset(&sampler
[0], 0, sizeof(struct pipe_sampler_state
));
211 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
212 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
213 sampler
[0].wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
214 sampler
[0].min_img_filter
= PIPE_TEX_MIPFILTER_LINEAR
;
215 sampler
[0].mag_img_filter
= PIPE_TEX_MIPFILTER_LINEAR
;
216 sampler
[0].normalized_coords
= 1;
218 switch(info
->tiling_mode
) {
220 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
221 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
222 memcpy(sampler
[0].border_color
,
223 ctx
->state
.vg
.tile_fill_color
,
224 sizeof(VGfloat
) * 4);
227 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
228 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
231 sampler
[0].wrap_s
= PIPE_TEX_WRAP_REPEAT
;
232 sampler
[0].wrap_t
= PIPE_TEX_WRAP_REPEAT
;
234 case VG_TILE_REFLECT
:
235 sampler
[0].wrap_s
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
236 sampler
[0].wrap_t
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
239 debug_assert(!"Unknown tiling mode");
242 samplers
[0] = &sampler
[0];
243 sampler_views
[0] = info
->src
->sampler_view
;
247 if (info
->extra_texture_view
) {
248 memcpy(&sampler
[1], &sampler
[0], sizeof(struct pipe_sampler_state
));
249 samplers
[1] = &sampler
[1];
250 sampler_views
[1] = info
->extra_texture_view
;
256 cso_set_samplers(ctx
->cso_context
, num_samplers
, (const struct pipe_sampler_state
**)samplers
);
257 cso_set_fragment_sampler_views(ctx
->cso_context
, num_textures
, sampler_views
);
260 static struct vg_shader
* setup_color_matrix(struct vg_context
*ctx
, void *user_data
)
262 struct vg_shader
*shader
=
263 shader_create_from_text(ctx
->pipe
, color_matrix_asm
, 200,
264 PIPE_SHADER_FRAGMENT
);
265 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
269 static struct vg_shader
* setup_convolution(struct vg_context
*ctx
, void *user_data
)
272 VGint num_consts
= (VGint
)(long)(user_data
);
273 struct vg_shader
*shader
;
275 util_snprintf(buffer
, 1023, convolution_asm
, num_consts
, num_consts
/ 2 + 1);
277 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
278 PIPE_SHADER_FRAGMENT
);
280 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
284 static struct vg_shader
* setup_lookup(struct vg_context
*ctx
, void *user_data
)
286 struct vg_shader
*shader
=
287 shader_create_from_text(ctx
->pipe
, lookup_asm
,
288 200, PIPE_SHADER_FRAGMENT
);
290 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
295 static struct vg_shader
* setup_lookup_single(struct vg_context
*ctx
, void *user_data
)
298 VGImageChannel channel
= (VGImageChannel
)(user_data
);
299 struct vg_shader
*shader
;
303 util_snprintf(buffer
, 1023, lookup_single_asm
, "xxxx");
306 util_snprintf(buffer
, 1023, lookup_single_asm
, "yyyy");
309 util_snprintf(buffer
, 1023, lookup_single_asm
, "zzzz");
312 util_snprintf(buffer
, 1023, lookup_single_asm
, "wwww");
315 debug_assert(!"Unknown color channel");
318 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
319 PIPE_SHADER_FRAGMENT
);
321 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
325 static void execute_filter(struct vg_context
*ctx
,
326 struct filter_info
*info
)
328 struct pipe_surface
*dst_surf
;
329 struct vg_shader
*shader
;
331 cso_save_framebuffer(ctx
->cso_context
);
332 cso_save_fragment_shader(ctx
->cso_context
);
333 cso_save_viewport(ctx
->cso_context
);
334 cso_save_blend(ctx
->cso_context
);
335 cso_save_samplers(ctx
->cso_context
);
336 cso_save_fragment_sampler_views(ctx
->cso_context
);
338 dst_surf
= setup_framebuffer(info
->dst
);
339 setup_viewport(info
->dst
);
341 setup_constant_buffer(ctx
, info
->const_buffer
, info
->const_buffer_len
);
342 shader
= info
->setup_shader(ctx
, info
->user_data
);
343 setup_samplers(ctx
, info
);
345 renderer_draw_texture(ctx
->renderer
,
346 info
->src
->sampler_view
->texture
,
347 info
->dst
->x
, info
->dst
->y
,
348 info
->dst
->x
+ info
->dst
->width
,
349 info
->dst
->y
+ info
->dst
->height
,
350 info
->dst
->x
, info
->dst
->y
,
351 info
->dst
->x
+ info
->dst
->width
,
352 info
->dst
->y
+ info
->dst
->height
);
354 cso_restore_framebuffer(ctx
->cso_context
);
355 cso_restore_fragment_shader(ctx
->cso_context
);
356 cso_restore_viewport(ctx
->cso_context
);
357 cso_restore_blend(ctx
->cso_context
);
358 cso_restore_samplers(ctx
->cso_context
);
359 cso_restore_fragment_sampler_views(ctx
->cso_context
);
361 vg_shader_destroy(ctx
, shader
);
363 pipe_surface_reference(&dst_surf
, NULL
);
366 void vegaColorMatrix(VGImage dst
, VGImage src
,
367 const VGfloat
* matrix
)
369 struct vg_context
*ctx
= vg_current_context();
370 struct vg_image
*d
, *s
;
371 struct filter_info info
;
373 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
374 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
377 if (!matrix
|| !is_aligned(matrix
)) {
378 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
382 d
= (struct vg_image
*)dst
;
383 s
= (struct vg_image
*)src
;
385 if (vg_image_overlaps(d
, s
)) {
386 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
392 info
.setup_shader
= &setup_color_matrix
;
393 info
.user_data
= NULL
;
394 info
.const_buffer
= matrix
;
395 info
.const_buffer_len
= 20 * sizeof(VGfloat
);
396 info
.tiling_mode
= VG_TILE_PAD
;
397 info
.extra_texture_view
= NULL
;
398 execute_filter(ctx
, &info
);
401 static VGfloat
texture_offset(VGfloat width
, VGint kernelSize
, VGint current
, VGint shift
)
403 VGfloat diff
= current
- shift
;
408 void vegaConvolve(VGImage dst
, VGImage src
,
409 VGint kernelWidth
, VGint kernelHeight
,
410 VGint shiftX
, VGint shiftY
,
411 const VGshort
* kernel
,
414 VGTilingMode tilingMode
)
416 struct vg_context
*ctx
= vg_current_context();
421 struct vg_image
*d
, *s
;
422 VGint kernel_size
= kernelWidth
* kernelHeight
;
423 struct filter_info info
;
424 const VGint max_kernel_size
= vgGeti(VG_MAX_KERNEL_SIZE
);
426 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
427 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
431 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
432 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
433 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
437 if (!kernel
|| !is_aligned_to(kernel
, 2)) {
438 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
442 if (tilingMode
< VG_TILE_FILL
||
443 tilingMode
> VG_TILE_REFLECT
) {
444 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
448 d
= (struct vg_image
*)dst
;
449 s
= (struct vg_image
*)src
;
451 if (vg_image_overlaps(d
, s
)) {
452 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
456 vg_validate_state(ctx
);
458 buffer_len
= 8 + 2 * 4 * kernel_size
;
459 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
463 buffer
[2] = 2.f
; /*unused*/
464 buffer
[3] = 4.f
; /*unused*/
466 buffer
[4] = kernelWidth
* kernelHeight
;
472 for (j
= 0; j
< kernelHeight
; ++j
) {
473 for (i
= 0; i
< kernelWidth
; ++i
) {
474 VGint index
= j
* kernelWidth
+ i
;
477 x
= texture_offset(s
->width
, kernelWidth
, i
, shiftX
);
478 y
= texture_offset(s
->height
, kernelHeight
, j
, shiftY
);
480 buffer
[idx
+ index
*4 + 0] = x
;
481 buffer
[idx
+ index
*4 + 1] = y
;
482 buffer
[idx
+ index
*4 + 2] = 0.f
;
483 buffer
[idx
+ index
*4 + 3] = 0.f
;
486 idx
+= kernel_size
* 4;
488 for (j
= 0; j
< kernelHeight
; ++j
) {
489 for (i
= 0; i
< kernelWidth
; ++i
) {
490 /* transpose the kernel */
491 VGint index
= j
* kernelWidth
+ i
;
492 VGint kindex
= (kernelWidth
- i
- 1) * kernelHeight
+ (kernelHeight
- j
- 1);
493 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
494 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
495 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
496 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
502 info
.setup_shader
= &setup_convolution
;
503 info
.user_data
= (void*)(long)(buffer_len
/4);
504 info
.const_buffer
= buffer
;
505 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
506 info
.tiling_mode
= tilingMode
;
507 info
.extra_texture_view
= NULL
;
508 execute_filter(ctx
, &info
);
513 void vegaSeparableConvolve(VGImage dst
, VGImage src
,
516 VGint shiftX
, VGint shiftY
,
517 const VGshort
* kernelX
,
518 const VGshort
* kernelY
,
521 VGTilingMode tilingMode
)
523 struct vg_context
*ctx
= vg_current_context();
526 const VGint max_kernel_size
= vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE
);
528 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
529 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
533 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
534 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
535 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
539 if (!kernelX
|| !kernelY
||
540 !is_aligned_to(kernelX
, 2) || !is_aligned_to(kernelY
, 2)) {
541 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
544 if (tilingMode
< VG_TILE_FILL
||
545 tilingMode
> VG_TILE_REFLECT
) {
546 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
549 kernel
= malloc(sizeof(VGshort
)*kernelWidth
*kernelHeight
);
550 for (i
= 0; i
< kernelWidth
; ++i
) {
551 for (j
= 0; j
< kernelHeight
; ++j
) {
552 kernel
[idx
] = kernelX
[i
] * kernelY
[j
];
556 vgConvolve(dst
, src
, kernelWidth
, kernelHeight
, shiftX
, shiftY
,
557 kernel
, scale
, bias
, tilingMode
);
561 static INLINE VGfloat
compute_gaussian_componenet(VGfloat x
, VGfloat y
,
562 VGfloat stdDeviationX
,
563 VGfloat stdDeviationY
)
565 VGfloat mult
= 1 / ( 2 * M_PI
* stdDeviationX
* stdDeviationY
);
566 VGfloat e
= exp( - ( pow(x
, 2)/(2*pow(stdDeviationX
, 2)) +
567 pow(y
, 2)/(2*pow(stdDeviationY
, 2)) ) );
571 static INLINE VGint
compute_kernel_size(VGfloat deviation
)
573 VGint size
= ceil(2.146 * deviation
);
579 static void compute_gaussian_kernel(VGfloat
*kernel
,
580 VGint width
, VGint height
,
581 VGfloat stdDeviationX
,
582 VGfloat stdDeviationY
)
585 VGfloat scale
= 0.0f
;
587 for (j
= 0; j
< height
; ++j
) {
588 for (i
= 0; i
< width
; ++i
) {
589 VGint idx
= (height
- j
-1) * width
+ (width
- i
-1);
590 kernel
[idx
] = compute_gaussian_componenet(i
-(ceil(width
/2))-1,
592 stdDeviationX
, stdDeviationY
);
593 scale
+= kernel
[idx
];
597 for (j
= 0; j
< height
; ++j
) {
598 for (i
= 0; i
< width
; ++i
) {
599 VGint idx
= j
* width
+ i
;
600 kernel
[idx
] /= scale
;
605 void vegaGaussianBlur(VGImage dst
, VGImage src
,
606 VGfloat stdDeviationX
,
607 VGfloat stdDeviationY
,
608 VGTilingMode tilingMode
)
610 struct vg_context
*ctx
= vg_current_context();
611 struct vg_image
*d
, *s
;
612 VGfloat
*buffer
, *kernel
;
613 VGint kernel_width
, kernel_height
, kernel_size
;
616 struct filter_info info
;
618 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
619 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
622 if (stdDeviationX
<= 0 || stdDeviationY
<= 0) {
623 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
627 if (tilingMode
< VG_TILE_FILL
||
628 tilingMode
> VG_TILE_REFLECT
) {
629 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
633 d
= (struct vg_image
*)dst
;
634 s
= (struct vg_image
*)src
;
636 if (vg_image_overlaps(d
, s
)) {
637 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
641 kernel_width
= compute_kernel_size(stdDeviationX
);
642 kernel_height
= compute_kernel_size(stdDeviationY
);
643 kernel_size
= kernel_width
* kernel_height
;
644 kernel
= malloc(sizeof(VGfloat
)*kernel_size
);
645 compute_gaussian_kernel(kernel
, kernel_width
, kernel_height
,
646 stdDeviationX
, stdDeviationY
);
648 buffer_len
= 8 + 2 * 4 * kernel_size
;
649 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
653 buffer
[2] = 2.f
; /*unused*/
654 buffer
[3] = 4.f
; /*unused*/
656 buffer
[4] = kernel_width
* kernel_height
;
657 buffer
[5] = 1.f
;/*scale*/
658 buffer
[6] = 0.f
;/*bias*/
662 for (j
= 0; j
< kernel_height
; ++j
) {
663 for (i
= 0; i
< kernel_width
; ++i
) {
664 VGint index
= j
* kernel_width
+ i
;
667 x
= texture_offset(s
->width
, kernel_width
, i
, kernel_width
/2);
668 y
= texture_offset(s
->height
, kernel_height
, j
, kernel_height
/2);
670 buffer
[idx
+ index
*4 + 0] = x
;
671 buffer
[idx
+ index
*4 + 1] = y
;
672 buffer
[idx
+ index
*4 + 2] = 0.f
;
673 buffer
[idx
+ index
*4 + 3] = 0.f
;
676 idx
+= kernel_size
* 4;
678 for (j
= 0; j
< kernel_height
; ++j
) {
679 for (i
= 0; i
< kernel_width
; ++i
) {
680 /* transpose the kernel */
681 VGint index
= j
* kernel_width
+ i
;
682 VGint kindex
= (kernel_width
- i
- 1) * kernel_height
+ (kernel_height
- j
- 1);
683 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
684 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
685 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
686 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
692 info
.setup_shader
= &setup_convolution
;
693 info
.user_data
= (void*)(long)(buffer_len
/4);
694 info
.const_buffer
= buffer
;
695 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
696 info
.tiling_mode
= tilingMode
;
697 info
.extra_texture_view
= NULL
;
698 execute_filter(ctx
, &info
);
704 void vegaLookup(VGImage dst
, VGImage src
,
705 const VGubyte
* redLUT
,
706 const VGubyte
* greenLUT
,
707 const VGubyte
* blueLUT
,
708 const VGubyte
* alphaLUT
,
709 VGboolean outputLinear
,
710 VGboolean outputPremultiplied
)
712 struct vg_context
*ctx
= vg_current_context();
713 struct vg_image
*d
, *s
;
714 VGuint color_data
[256];
716 struct pipe_sampler_view
*lut_texture_view
;
718 struct filter_info info
;
720 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
721 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
725 if (!redLUT
|| !greenLUT
|| !blueLUT
|| !alphaLUT
) {
726 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
730 d
= (struct vg_image
*)dst
;
731 s
= (struct vg_image
*)src
;
733 if (vg_image_overlaps(d
, s
)) {
734 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
738 for (i
= 0; i
< 256; ++i
) {
739 color_data
[i
] = blueLUT
[i
] << 24 | greenLUT
[i
] << 16 |
740 redLUT
[i
] << 8 | alphaLUT
[i
];
742 lut_texture_view
= create_texture_1d_view(ctx
, color_data
, 255);
751 info
.setup_shader
= &setup_lookup
;
752 info
.user_data
= NULL
;
753 info
.const_buffer
= buffer
;
754 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
755 info
.tiling_mode
= VG_TILE_PAD
;
756 info
.extra_texture_view
= lut_texture_view
;
758 execute_filter(ctx
, &info
);
760 pipe_sampler_view_reference(&lut_texture_view
, NULL
);
763 void vegaLookupSingle(VGImage dst
, VGImage src
,
764 const VGuint
* lookupTable
,
765 VGImageChannel sourceChannel
,
766 VGboolean outputLinear
,
767 VGboolean outputPremultiplied
)
769 struct vg_context
*ctx
= vg_current_context();
770 struct vg_image
*d
, *s
;
771 struct pipe_sampler_view
*lut_texture_view
;
773 struct filter_info info
;
774 VGuint color_data
[256];
777 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
778 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
782 if (!lookupTable
|| !is_aligned(lookupTable
)) {
783 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
787 if (sourceChannel
!= VG_RED
&& sourceChannel
!= VG_GREEN
&&
788 sourceChannel
!= VG_BLUE
&& sourceChannel
!= VG_ALPHA
) {
789 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
793 d
= (struct vg_image
*)dst
;
794 s
= (struct vg_image
*)src
;
796 if (vg_image_overlaps(d
, s
)) {
797 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
801 for (i
= 0; i
< 256; ++i
) {
802 VGuint rgba
= lookupTable
[i
];
803 VGubyte blue
, green
, red
, alpha
;
804 red
= (rgba
& 0xff000000)>>24;
805 green
= (rgba
& 0x00ff0000)>>16;
806 blue
= (rgba
& 0x0000ff00)>> 8;
807 alpha
= (rgba
& 0x000000ff)>> 0;
808 color_data
[i
] = blue
<< 24 | green
<< 16 |
811 lut_texture_view
= create_texture_1d_view(ctx
, color_data
, 256);
820 info
.setup_shader
= &setup_lookup_single
;
821 info
.user_data
= (void*)sourceChannel
;
822 info
.const_buffer
= buffer
;
823 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
824 info
.tiling_mode
= VG_TILE_PAD
;
825 info
.extra_texture_view
= lut_texture_view
;
827 execute_filter(ctx
, &info
);
829 pipe_sampler_view_reference(&lut_texture_view
, NULL
);