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"
32 #include "shaders_cache.h"
33 #include "st_inlines.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_state.h"
37 #include "pipe/p_inlines.h"
38 #include "pipe/p_screen.h"
39 #include "pipe/p_shader_tokens.h"
41 #include "util/u_format.h"
42 #include "util/u_memory.h"
45 #include "asm_filters.h"
51 struct vg_shader
* (*setup_shader
)(struct vg_context
*, void *);
53 const void *const_buffer
;
54 VGint const_buffer_len
;
55 VGTilingMode tiling_mode
;
56 struct pipe_texture
*extra_texture
;
59 static INLINE
struct pipe_texture
*create_texture_1d(struct vg_context
*ctx
,
60 const VGuint
*color_data
,
61 const VGint color_data_len
)
63 struct pipe_context
*pipe
= ctx
->pipe
;
64 struct pipe_screen
*screen
= pipe
->screen
;
65 struct pipe_texture
*tex
= 0;
66 struct pipe_texture templ
;
68 memset(&templ
, 0, sizeof(templ
));
69 templ
.target
= PIPE_TEXTURE_1D
;
70 templ
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
72 templ
.width0
= color_data_len
;
75 util_format_get_block(PIPE_FORMAT_A8R8G8B8_UNORM
, &templ
.block
);
76 templ
.tex_usage
= PIPE_TEXTURE_USAGE_SAMPLER
;
78 tex
= screen
->texture_create(screen
, &templ
);
80 { /* upload color_data */
81 struct pipe_transfer
*transfer
=
82 screen
->get_tex_transfer(screen
, tex
,
84 PIPE_TRANSFER_READ_WRITE
,
85 0, 0, tex
->width0
, tex
->height0
);
86 void *map
= screen
->transfer_map(screen
, transfer
);
87 memcpy(map
, color_data
, sizeof(VGint
)*color_data_len
);
88 screen
->transfer_unmap(screen
, transfer
);
89 screen
->tex_transfer_destroy(transfer
);
95 static INLINE
struct pipe_surface
* setup_framebuffer(struct vg_image
*dst
)
97 struct vg_context
*ctx
= vg_current_context();
98 struct pipe_context
*pipe
= ctx
->pipe
;
99 struct pipe_framebuffer_state fb
;
100 struct pipe_surface
*dst_surf
= pipe
->screen
->get_tex_surface(
101 pipe
->screen
, dst
->texture
, 0, 0, 0,
102 PIPE_BUFFER_USAGE_GPU_WRITE
);
105 memset(&fb
, 0, sizeof(fb
));
106 fb
.width
= dst
->x
+ dst_surf
->width
;
107 fb
.height
= dst
->y
+ dst_surf
->height
;
109 fb
.cbufs
[0] = dst_surf
;
112 for (i
= 1; i
< PIPE_MAX_COLOR_BUFS
; ++i
)
115 cso_set_framebuffer(ctx
->cso_context
, &fb
);
120 static void setup_viewport(struct vg_image
*dst
)
122 struct vg_context
*ctx
= vg_current_context();
123 vg_set_viewport(ctx
, VEGA_Y0_TOP
);
126 static void setup_blend()
128 struct vg_context
*ctx
= vg_current_context();
129 struct pipe_blend_state blend
;
130 memset(&blend
, 0, sizeof(blend
));
131 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
132 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
133 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
134 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
135 if (ctx
->state
.vg
.filter_channel_mask
& VG_RED
)
136 blend
.colormask
|= PIPE_MASK_R
;
137 if (ctx
->state
.vg
.filter_channel_mask
& VG_GREEN
)
138 blend
.colormask
|= PIPE_MASK_G
;
139 if (ctx
->state
.vg
.filter_channel_mask
& VG_BLUE
)
140 blend
.colormask
|= PIPE_MASK_B
;
141 if (ctx
->state
.vg
.filter_channel_mask
& VG_ALPHA
)
142 blend
.colormask
|= PIPE_MASK_A
;
143 blend
.blend_enable
= 1;
144 cso_set_blend(ctx
->cso_context
, &blend
);
147 static void setup_constant_buffer(struct vg_context
*ctx
, const void *buffer
,
150 struct pipe_context
*pipe
= ctx
->pipe
;
151 struct pipe_constant_buffer
*cbuf
= &ctx
->filter
.buffer
;
153 /* We always need to get a new buffer, to keep the drivers simple and
154 * avoid gratuitous rendering synchronization. */
155 pipe_buffer_reference(&cbuf
->buffer
, NULL
);
157 cbuf
->buffer
= pipe_buffer_create(pipe
->screen
, 16,
158 PIPE_BUFFER_USAGE_CONSTANT
,
162 st_no_flush_pipe_buffer_write(ctx
, cbuf
->buffer
,
163 0, param_bytes
, buffer
);
166 ctx
->pipe
->set_constant_buffer(ctx
->pipe
, PIPE_SHADER_FRAGMENT
, 0, cbuf
);
169 static void setup_samplers(struct vg_context
*ctx
, struct filter_info
*info
)
171 struct pipe_sampler_state
*samplers
[PIPE_MAX_SAMPLERS
];
172 struct pipe_texture
*textures
[PIPE_MAX_SAMPLERS
];
173 struct pipe_sampler_state sampler
[3];
174 int num_samplers
= 0;
175 int num_textures
= 0;
186 memset(&sampler
[0], 0, sizeof(struct pipe_sampler_state
));
187 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
188 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
189 sampler
[0].wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
190 sampler
[0].min_img_filter
= PIPE_TEX_MIPFILTER_LINEAR
;
191 sampler
[0].mag_img_filter
= PIPE_TEX_MIPFILTER_LINEAR
;
192 sampler
[0].normalized_coords
= 1;
194 switch(info
->tiling_mode
) {
196 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
197 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
198 memcpy(sampler
[0].border_color
,
199 ctx
->state
.vg
.tile_fill_color
,
200 sizeof(VGfloat
) * 4);
203 sampler
[0].wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
204 sampler
[0].wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
207 sampler
[0].wrap_s
= PIPE_TEX_WRAP_REPEAT
;
208 sampler
[0].wrap_t
= PIPE_TEX_WRAP_REPEAT
;
210 case VG_TILE_REFLECT
:
211 sampler
[0].wrap_s
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
212 sampler
[0].wrap_t
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
215 debug_assert(!"Unknown tiling mode");
218 samplers
[0] = &sampler
[0];
219 textures
[0] = info
->src
->texture
;
223 if (info
->extra_texture
) {
224 memcpy(&sampler
[1], &sampler
[0], sizeof(struct pipe_sampler_state
));
225 samplers
[1] = &sampler
[1];
226 textures
[1] = info
->extra_texture
;
232 cso_set_samplers(ctx
->cso_context
, num_samplers
, (const struct pipe_sampler_state
**)samplers
);
233 cso_set_sampler_textures(ctx
->cso_context
, num_textures
, textures
);
236 static struct vg_shader
* setup_color_matrix(struct vg_context
*ctx
, void *user_data
)
238 struct vg_shader
*shader
=
239 shader_create_from_text(ctx
->pipe
, color_matrix_asm
, 200,
240 PIPE_SHADER_FRAGMENT
);
241 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
245 static struct vg_shader
* setup_convolution(struct vg_context
*ctx
, void *user_data
)
248 VGint num_consts
= (VGint
)(long)(user_data
);
249 struct vg_shader
*shader
;
251 snprintf(buffer
, 1023, convolution_asm
, num_consts
, num_consts
/ 2 + 1);
253 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
254 PIPE_SHADER_FRAGMENT
);
256 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
260 static struct vg_shader
* setup_lookup(struct vg_context
*ctx
, void *user_data
)
262 struct vg_shader
*shader
=
263 shader_create_from_text(ctx
->pipe
, lookup_asm
,
264 200, PIPE_SHADER_FRAGMENT
);
266 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
271 static struct vg_shader
* setup_lookup_single(struct vg_context
*ctx
, void *user_data
)
274 VGImageChannel channel
= (VGImageChannel
)(user_data
);
275 struct vg_shader
*shader
;
279 snprintf(buffer
, 1023, lookup_single_asm
, "xxxx");
282 snprintf(buffer
, 1023, lookup_single_asm
, "yyyy");
285 snprintf(buffer
, 1023, lookup_single_asm
, "zzzz");
288 snprintf(buffer
, 1023, lookup_single_asm
, "wwww");
291 debug_assert(!"Unknown color channel");
294 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
295 PIPE_SHADER_FRAGMENT
);
297 cso_set_fragment_shader_handle(ctx
->cso_context
, shader
->driver
);
301 static void execute_filter(struct vg_context
*ctx
,
302 struct filter_info
*info
)
304 struct pipe_surface
*dst_surf
;
305 struct vg_shader
*shader
;
307 cso_save_framebuffer(ctx
->cso_context
);
308 cso_save_fragment_shader(ctx
->cso_context
);
309 cso_save_viewport(ctx
->cso_context
);
310 cso_save_blend(ctx
->cso_context
);
311 cso_save_samplers(ctx
->cso_context
);
312 cso_save_sampler_textures(ctx
->cso_context
);
314 dst_surf
= setup_framebuffer(info
->dst
);
315 setup_viewport(info
->dst
);
317 setup_constant_buffer(ctx
, info
->const_buffer
, info
->const_buffer_len
);
318 shader
= info
->setup_shader(ctx
, info
->user_data
);
319 setup_samplers(ctx
, info
);
321 renderer_draw_texture(ctx
->renderer
,
323 info
->dst
->x
, info
->dst
->y
,
324 info
->dst
->x
+ info
->dst
->width
,
325 info
->dst
->y
+ info
->dst
->height
,
326 info
->dst
->x
, info
->dst
->y
,
327 info
->dst
->x
+ info
->dst
->width
,
328 info
->dst
->y
+ info
->dst
->height
);
330 cso_restore_framebuffer(ctx
->cso_context
);
331 cso_restore_fragment_shader(ctx
->cso_context
);
332 cso_restore_viewport(ctx
->cso_context
);
333 cso_restore_blend(ctx
->cso_context
);
334 cso_restore_samplers(ctx
->cso_context
);
335 cso_restore_sampler_textures(ctx
->cso_context
);
337 vg_shader_destroy(ctx
, shader
);
339 pipe_surface_reference(&dst_surf
, NULL
);
342 void vgColorMatrix(VGImage dst
, VGImage src
,
343 const VGfloat
* matrix
)
345 struct vg_context
*ctx
= vg_current_context();
346 struct vg_image
*d
, *s
;
347 struct filter_info info
;
349 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
350 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
353 if (!matrix
|| !is_aligned(matrix
)) {
354 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
358 d
= (struct vg_image
*)dst
;
359 s
= (struct vg_image
*)src
;
361 if (vg_image_overlaps(d
, s
)) {
362 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
368 info
.setup_shader
= &setup_color_matrix
;
369 info
.user_data
= NULL
;
370 info
.const_buffer
= matrix
;
371 info
.const_buffer_len
= 20 * sizeof(VGfloat
);
372 info
.tiling_mode
= VG_TILE_PAD
;
373 info
.extra_texture
= 0;
374 execute_filter(ctx
, &info
);
377 static VGfloat
texture_offset(VGfloat width
, VGint kernelSize
, VGint current
, VGint shift
)
379 VGfloat diff
= current
- shift
;
384 void vgConvolve(VGImage dst
, VGImage src
,
385 VGint kernelWidth
, VGint kernelHeight
,
386 VGint shiftX
, VGint shiftY
,
387 const VGshort
* kernel
,
390 VGTilingMode tilingMode
)
392 struct vg_context
*ctx
= vg_current_context();
397 struct vg_image
*d
, *s
;
398 VGint kernel_size
= kernelWidth
* kernelHeight
;
399 struct filter_info info
;
400 const VGint max_kernel_size
= vgGeti(VG_MAX_KERNEL_SIZE
);
402 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
403 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
407 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
408 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
409 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
413 if (!kernel
|| !is_aligned_to(kernel
, 2)) {
414 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
418 if (tilingMode
< VG_TILE_FILL
||
419 tilingMode
> VG_TILE_REFLECT
) {
420 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
424 d
= (struct vg_image
*)dst
;
425 s
= (struct vg_image
*)src
;
427 if (vg_image_overlaps(d
, s
)) {
428 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
432 vg_validate_state(ctx
);
434 buffer_len
= 8 + 2 * 4 * kernel_size
;
435 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
439 buffer
[2] = 2.f
; /*unused*/
440 buffer
[3] = 4.f
; /*unused*/
442 buffer
[4] = kernelWidth
* kernelHeight
;
448 for (j
= 0; j
< kernelHeight
; ++j
) {
449 for (i
= 0; i
< kernelWidth
; ++i
) {
450 VGint index
= j
* kernelWidth
+ i
;
453 x
= texture_offset(s
->width
, kernelWidth
, i
, shiftX
);
454 y
= texture_offset(s
->height
, kernelHeight
, j
, shiftY
);
456 buffer
[idx
+ index
*4 + 0] = x
;
457 buffer
[idx
+ index
*4 + 1] = y
;
458 buffer
[idx
+ index
*4 + 2] = 0.f
;
459 buffer
[idx
+ index
*4 + 3] = 0.f
;
462 idx
+= kernel_size
* 4;
464 for (j
= 0; j
< kernelHeight
; ++j
) {
465 for (i
= 0; i
< kernelWidth
; ++i
) {
466 /* transpose the kernel */
467 VGint index
= j
* kernelWidth
+ i
;
468 VGint kindex
= (kernelWidth
- i
- 1) * kernelHeight
+ (kernelHeight
- j
- 1);
469 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
470 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
471 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
472 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
478 info
.setup_shader
= &setup_convolution
;
479 info
.user_data
= (void*)(long)(buffer_len
/4);
480 info
.const_buffer
= buffer
;
481 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
482 info
.tiling_mode
= tilingMode
;
483 info
.extra_texture
= 0;
484 execute_filter(ctx
, &info
);
489 void vgSeparableConvolve(VGImage dst
, VGImage src
,
492 VGint shiftX
, VGint shiftY
,
493 const VGshort
* kernelX
,
494 const VGshort
* kernelY
,
497 VGTilingMode tilingMode
)
499 struct vg_context
*ctx
= vg_current_context();
502 const VGint max_kernel_size
= vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE
);
504 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
505 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
509 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
510 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
511 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
515 if (!kernelX
|| !kernelY
||
516 !is_aligned_to(kernelX
, 2) || !is_aligned_to(kernelY
, 2)) {
517 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
520 if (tilingMode
< VG_TILE_FILL
||
521 tilingMode
> VG_TILE_REFLECT
) {
522 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
525 kernel
= malloc(sizeof(VGshort
)*kernelWidth
*kernelHeight
);
526 for (i
= 0; i
< kernelWidth
; ++i
) {
527 for (j
= 0; j
< kernelHeight
; ++j
) {
528 kernel
[idx
] = kernelX
[i
] * kernelY
[j
];
532 vgConvolve(dst
, src
, kernelWidth
, kernelHeight
, shiftX
, shiftY
,
533 kernel
, scale
, bias
, tilingMode
);
537 static INLINE VGfloat
compute_gaussian_componenet(VGfloat x
, VGfloat y
,
538 VGfloat stdDeviationX
,
539 VGfloat stdDeviationY
)
541 VGfloat mult
= 1 / ( 2 * M_PI
* stdDeviationX
* stdDeviationY
);
542 VGfloat e
= exp( - ( pow(x
, 2)/(2*pow(stdDeviationX
, 2)) +
543 pow(y
, 2)/(2*pow(stdDeviationY
, 2)) ) );
547 static INLINE VGint
compute_kernel_size(VGfloat deviation
)
549 VGint size
= ceil(2.146 * deviation
);
555 static void compute_gaussian_kernel(VGfloat
*kernel
,
556 VGint width
, VGint height
,
557 VGfloat stdDeviationX
,
558 VGfloat stdDeviationY
)
561 VGfloat scale
= 0.0f
;
563 for (j
= 0; j
< height
; ++j
) {
564 for (i
= 0; i
< width
; ++i
) {
565 VGint idx
= (height
- j
-1) * width
+ (width
- i
-1);
566 kernel
[idx
] = compute_gaussian_componenet(i
-(ceil(width
/2))-1,
568 stdDeviationX
, stdDeviationY
);
569 scale
+= kernel
[idx
];
573 for (j
= 0; j
< height
; ++j
) {
574 for (i
= 0; i
< width
; ++i
) {
575 VGint idx
= j
* width
+ i
;
576 kernel
[idx
] /= scale
;
581 void vgGaussianBlur(VGImage dst
, VGImage src
,
582 VGfloat stdDeviationX
,
583 VGfloat stdDeviationY
,
584 VGTilingMode tilingMode
)
586 struct vg_context
*ctx
= vg_current_context();
587 struct vg_image
*d
, *s
;
588 VGfloat
*buffer
, *kernel
;
589 VGint kernel_width
, kernel_height
, kernel_size
;
592 struct filter_info info
;
594 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
595 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
598 if (stdDeviationX
<= 0 || stdDeviationY
<= 0) {
599 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
603 if (tilingMode
< VG_TILE_FILL
||
604 tilingMode
> VG_TILE_REFLECT
) {
605 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
609 d
= (struct vg_image
*)dst
;
610 s
= (struct vg_image
*)src
;
612 if (vg_image_overlaps(d
, s
)) {
613 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
617 kernel_width
= compute_kernel_size(stdDeviationX
);
618 kernel_height
= compute_kernel_size(stdDeviationY
);
619 kernel_size
= kernel_width
* kernel_height
;
620 kernel
= malloc(sizeof(VGfloat
)*kernel_size
);
621 compute_gaussian_kernel(kernel
, kernel_width
, kernel_height
,
622 stdDeviationX
, stdDeviationY
);
624 buffer_len
= 8 + 2 * 4 * kernel_size
;
625 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
629 buffer
[2] = 2.f
; /*unused*/
630 buffer
[3] = 4.f
; /*unused*/
632 buffer
[4] = kernel_width
* kernel_height
;
633 buffer
[5] = 1.f
;/*scale*/
634 buffer
[6] = 0.f
;/*bias*/
638 for (j
= 0; j
< kernel_height
; ++j
) {
639 for (i
= 0; i
< kernel_width
; ++i
) {
640 VGint index
= j
* kernel_width
+ i
;
643 x
= texture_offset(s
->width
, kernel_width
, i
, kernel_width
/2);
644 y
= texture_offset(s
->height
, kernel_height
, j
, kernel_height
/2);
646 buffer
[idx
+ index
*4 + 0] = x
;
647 buffer
[idx
+ index
*4 + 1] = y
;
648 buffer
[idx
+ index
*4 + 2] = 0.f
;
649 buffer
[idx
+ index
*4 + 3] = 0.f
;
652 idx
+= kernel_size
* 4;
654 for (j
= 0; j
< kernel_height
; ++j
) {
655 for (i
= 0; i
< kernel_width
; ++i
) {
656 /* transpose the kernel */
657 VGint index
= j
* kernel_width
+ i
;
658 VGint kindex
= (kernel_width
- i
- 1) * kernel_height
+ (kernel_height
- j
- 1);
659 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
660 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
661 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
662 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
668 info
.setup_shader
= &setup_convolution
;
669 info
.user_data
= (void*)(long)(buffer_len
/4);
670 info
.const_buffer
= buffer
;
671 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
672 info
.tiling_mode
= tilingMode
;
673 info
.extra_texture
= 0;
674 execute_filter(ctx
, &info
);
680 void vgLookup(VGImage dst
, VGImage src
,
681 const VGubyte
* redLUT
,
682 const VGubyte
* greenLUT
,
683 const VGubyte
* blueLUT
,
684 const VGubyte
* alphaLUT
,
685 VGboolean outputLinear
,
686 VGboolean outputPremultiplied
)
688 struct vg_context
*ctx
= vg_current_context();
689 struct vg_image
*d
, *s
;
690 VGuint color_data
[256];
692 struct pipe_texture
*lut_texture
;
694 struct filter_info info
;
696 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
697 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
701 if (!redLUT
|| !greenLUT
|| !blueLUT
|| !alphaLUT
) {
702 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
706 d
= (struct vg_image
*)dst
;
707 s
= (struct vg_image
*)src
;
709 if (vg_image_overlaps(d
, s
)) {
710 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
714 for (i
= 0; i
< 256; ++i
) {
715 color_data
[i
] = blueLUT
[i
] << 24 | greenLUT
[i
] << 16 |
716 redLUT
[i
] << 8 | alphaLUT
[i
];
718 lut_texture
= create_texture_1d(ctx
, color_data
, 255);
727 info
.setup_shader
= &setup_lookup
;
728 info
.user_data
= NULL
;
729 info
.const_buffer
= buffer
;
730 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
731 info
.tiling_mode
= VG_TILE_PAD
;
732 info
.extra_texture
= lut_texture
;
734 execute_filter(ctx
, &info
);
736 pipe_texture_reference(&lut_texture
, NULL
);
739 void vgLookupSingle(VGImage dst
, VGImage src
,
740 const VGuint
* lookupTable
,
741 VGImageChannel sourceChannel
,
742 VGboolean outputLinear
,
743 VGboolean outputPremultiplied
)
745 struct vg_context
*ctx
= vg_current_context();
746 struct vg_image
*d
, *s
;
747 struct pipe_texture
*lut_texture
;
749 struct filter_info info
;
750 VGuint color_data
[256];
753 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
754 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
758 if (!lookupTable
|| !is_aligned(lookupTable
)) {
759 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
763 if (sourceChannel
!= VG_RED
&& sourceChannel
!= VG_GREEN
&&
764 sourceChannel
!= VG_BLUE
&& sourceChannel
!= VG_ALPHA
) {
765 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
769 d
= (struct vg_image
*)dst
;
770 s
= (struct vg_image
*)src
;
772 if (vg_image_overlaps(d
, s
)) {
773 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
777 for (i
= 0; i
< 256; ++i
) {
778 VGuint rgba
= lookupTable
[i
];
779 VGubyte blue
, green
, red
, alpha
;
780 red
= (rgba
& 0xff000000)>>24;
781 green
= (rgba
& 0x00ff0000)>>16;
782 blue
= (rgba
& 0x0000ff00)>> 8;
783 alpha
= (rgba
& 0x000000ff)>> 0;
784 color_data
[i
] = blue
<< 24 | green
<< 16 |
787 lut_texture
= create_texture_1d(ctx
, color_data
, 256);
796 info
.setup_shader
= &setup_lookup_single
;
797 info
.user_data
= (void*)sourceChannel
;
798 info
.const_buffer
= buffer
;
799 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
800 info
.tiling_mode
= VG_TILE_PAD
;
801 info
.extra_texture
= lut_texture
;
803 execute_filter(ctx
, &info
);
805 pipe_texture_reference(&lut_texture
, NULL
);