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"
41 #include "util/u_format.h"
42 #include "util/u_sampler.h"
43 #include "util/u_string.h"
46 #include "asm_filters.h"
52 struct vg_shader
* (*setup_shader
)(struct vg_context
*, void *);
54 const void *const_buffer
;
55 VGint const_buffer_len
;
56 VGTilingMode tiling_mode
;
57 struct pipe_sampler_view
*extra_texture_view
;
60 static INLINE
struct pipe_resource
*create_texture_1d(struct vg_context
*ctx
,
61 const VGuint
*color_data
,
62 const VGint color_data_len
)
64 struct pipe_context
*pipe
= ctx
->pipe
;
65 struct pipe_screen
*screen
= pipe
->screen
;
66 struct pipe_resource
*tex
= 0;
67 struct pipe_resource templ
;
69 memset(&templ
, 0, sizeof(templ
));
70 templ
.target
= PIPE_TEXTURE_1D
;
71 templ
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
73 templ
.width0
= color_data_len
;
76 templ
.bind
= PIPE_BIND_SAMPLER_VIEW
;
78 tex
= screen
->resource_create(screen
, &templ
);
80 { /* upload color_data */
81 struct pipe_transfer
*transfer
=
82 pipe_get_transfer(pipe
, tex
,
84 PIPE_TRANSFER_READ_WRITE
,
85 0, 0, tex
->width0
, tex
->height0
);
86 void *map
= pipe
->transfer_map(pipe
, transfer
);
87 memcpy(map
, color_data
, sizeof(VGint
)*color_data_len
);
88 pipe
->transfer_unmap(pipe
, transfer
);
89 pipe
->transfer_destroy(pipe
, transfer
);
95 static INLINE
struct pipe_sampler_view
*create_texture_1d_view(struct vg_context
*ctx
,
96 const VGuint
*color_data
,
97 const VGint color_data_len
)
99 struct pipe_context
*pipe
= ctx
->pipe
;
100 struct pipe_resource
*texture
;
101 struct pipe_sampler_view view_templ
;
102 struct pipe_sampler_view
*view
;
104 texture
= create_texture_1d(ctx
, color_data
, color_data_len
);
109 u_sampler_view_default_template(&view_templ
, texture
, texture
->format
);
110 view
= pipe
->create_sampler_view(pipe
, texture
, &view_templ
);
111 /* want the texture to go away if the view is freed */
112 pipe_resource_reference(&texture
, NULL
);
117 static struct vg_shader
* setup_color_matrix(struct vg_context
*ctx
, void *user_data
)
119 struct vg_shader
*shader
=
120 shader_create_from_text(ctx
->pipe
, color_matrix_asm
, 200,
121 PIPE_SHADER_FRAGMENT
);
125 static struct vg_shader
* setup_convolution(struct vg_context
*ctx
, void *user_data
)
128 VGint num_consts
= (VGint
)(long)(user_data
);
129 struct vg_shader
*shader
;
131 util_snprintf(buffer
, 1023, convolution_asm
, num_consts
, num_consts
/ 2 + 1);
133 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
134 PIPE_SHADER_FRAGMENT
);
139 static struct vg_shader
* setup_lookup(struct vg_context
*ctx
, void *user_data
)
141 struct vg_shader
*shader
=
142 shader_create_from_text(ctx
->pipe
, lookup_asm
,
143 200, PIPE_SHADER_FRAGMENT
);
149 static struct vg_shader
* setup_lookup_single(struct vg_context
*ctx
, void *user_data
)
152 VGImageChannel channel
= (VGImageChannel
)(user_data
);
153 struct vg_shader
*shader
;
157 util_snprintf(buffer
, 1023, lookup_single_asm
, "xxxx");
160 util_snprintf(buffer
, 1023, lookup_single_asm
, "yyyy");
163 util_snprintf(buffer
, 1023, lookup_single_asm
, "zzzz");
166 util_snprintf(buffer
, 1023, lookup_single_asm
, "wwww");
169 debug_assert(!"Unknown color channel");
172 shader
= shader_create_from_text(ctx
->pipe
, buffer
, 200,
173 PIPE_SHADER_FRAGMENT
);
178 static void execute_filter(struct vg_context
*ctx
,
179 struct filter_info
*info
)
181 struct vg_shader
*shader
;
182 const struct pipe_sampler_state
*samplers
[2];
183 struct pipe_sampler_view
*views
[2];
184 struct pipe_sampler_state sampler
;
187 memset(&sampler
, 0, sizeof(sampler
));
188 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
189 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
190 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NONE
;
191 sampler
.normalized_coords
= 1;
193 switch (info
->tiling_mode
) {
195 tex_wrap
= PIPE_TEX_WRAP_CLAMP_TO_BORDER
;
196 /* copy border color */
197 memcpy(sampler
.border_color
, ctx
->state
.vg
.tile_fill_color
,
198 sizeof(sampler
.border_color
));
201 tex_wrap
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;;
204 tex_wrap
= PIPE_TEX_WRAP_REPEAT
;;
206 case VG_TILE_REFLECT
:
207 tex_wrap
= PIPE_TEX_WRAP_MIRROR_REPEAT
;
210 debug_assert(!"Unknown tiling mode");
214 sampler
.wrap_s
= tex_wrap
;
215 sampler
.wrap_t
= tex_wrap
;
216 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
218 samplers
[0] = samplers
[1] = &sampler
;
219 views
[0] = info
->src
->sampler_view
;
220 views
[1] = info
->extra_texture_view
;
222 shader
= info
->setup_shader(ctx
, info
->user_data
);
224 if (renderer_filter_begin(ctx
->renderer
,
225 info
->dst
->sampler_view
->texture
, VG_TRUE
,
226 ctx
->state
.vg
.filter_channel_mask
,
227 samplers
, views
, (info
->extra_texture_view
) ? 2 : 1,
228 shader
->driver
, info
->const_buffer
, info
->const_buffer_len
)) {
229 renderer_filter(ctx
->renderer
,
230 info
->dst
->x
, info
->dst
->y
, info
->dst
->width
, info
->dst
->height
,
231 info
->src
->x
, info
->src
->y
, info
->src
->width
, info
->src
->height
);
232 renderer_filter_end(ctx
->renderer
);
235 vg_shader_destroy(ctx
, shader
);
238 void vegaColorMatrix(VGImage dst
, VGImage src
,
239 const VGfloat
* matrix
)
241 struct vg_context
*ctx
= vg_current_context();
242 struct vg_image
*d
, *s
;
243 struct filter_info info
;
245 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
246 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
249 if (!matrix
|| !is_aligned(matrix
)) {
250 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
254 d
= (struct vg_image
*)dst
;
255 s
= (struct vg_image
*)src
;
257 if (vg_image_overlaps(d
, s
)) {
258 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
264 info
.setup_shader
= &setup_color_matrix
;
265 info
.user_data
= NULL
;
266 info
.const_buffer
= matrix
;
267 info
.const_buffer_len
= 20 * sizeof(VGfloat
);
268 info
.tiling_mode
= VG_TILE_PAD
;
269 info
.extra_texture_view
= NULL
;
270 execute_filter(ctx
, &info
);
273 static VGfloat
texture_offset(VGfloat width
, VGint kernelSize
, VGint current
, VGint shift
)
275 VGfloat diff
= current
- shift
;
280 void vegaConvolve(VGImage dst
, VGImage src
,
281 VGint kernelWidth
, VGint kernelHeight
,
282 VGint shiftX
, VGint shiftY
,
283 const VGshort
* kernel
,
286 VGTilingMode tilingMode
)
288 struct vg_context
*ctx
= vg_current_context();
293 struct vg_image
*d
, *s
;
294 VGint kernel_size
= kernelWidth
* kernelHeight
;
295 struct filter_info info
;
296 const VGint max_kernel_size
= vgGeti(VG_MAX_KERNEL_SIZE
);
298 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
299 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
303 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
304 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
305 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
309 if (!kernel
|| !is_aligned_to(kernel
, 2)) {
310 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
314 if (tilingMode
< VG_TILE_FILL
||
315 tilingMode
> VG_TILE_REFLECT
) {
316 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
320 d
= (struct vg_image
*)dst
;
321 s
= (struct vg_image
*)src
;
323 if (vg_image_overlaps(d
, s
)) {
324 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
328 vg_validate_state(ctx
);
330 buffer_len
= 8 + 2 * 4 * kernel_size
;
331 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
335 buffer
[2] = 2.f
; /*unused*/
336 buffer
[3] = 4.f
; /*unused*/
338 buffer
[4] = kernelWidth
* kernelHeight
;
344 for (j
= 0; j
< kernelHeight
; ++j
) {
345 for (i
= 0; i
< kernelWidth
; ++i
) {
346 VGint index
= j
* kernelWidth
+ i
;
349 x
= texture_offset(s
->width
, kernelWidth
, i
, shiftX
);
350 y
= texture_offset(s
->height
, kernelHeight
, j
, shiftY
);
352 buffer
[idx
+ index
*4 + 0] = x
;
353 buffer
[idx
+ index
*4 + 1] = y
;
354 buffer
[idx
+ index
*4 + 2] = 0.f
;
355 buffer
[idx
+ index
*4 + 3] = 0.f
;
358 idx
+= kernel_size
* 4;
360 for (j
= 0; j
< kernelHeight
; ++j
) {
361 for (i
= 0; i
< kernelWidth
; ++i
) {
362 /* transpose the kernel */
363 VGint index
= j
* kernelWidth
+ i
;
364 VGint kindex
= (kernelWidth
- i
- 1) * kernelHeight
+ (kernelHeight
- j
- 1);
365 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
366 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
367 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
368 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
374 info
.setup_shader
= &setup_convolution
;
375 info
.user_data
= (void*)(long)(buffer_len
/4);
376 info
.const_buffer
= buffer
;
377 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
378 info
.tiling_mode
= tilingMode
;
379 info
.extra_texture_view
= NULL
;
380 execute_filter(ctx
, &info
);
385 void vegaSeparableConvolve(VGImage dst
, VGImage src
,
388 VGint shiftX
, VGint shiftY
,
389 const VGshort
* kernelX
,
390 const VGshort
* kernelY
,
393 VGTilingMode tilingMode
)
395 struct vg_context
*ctx
= vg_current_context();
398 const VGint max_kernel_size
= vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE
);
400 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
401 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
405 if (kernelWidth
<= 0 || kernelHeight
<= 0 ||
406 kernelWidth
> max_kernel_size
|| kernelHeight
> max_kernel_size
) {
407 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
411 if (!kernelX
|| !kernelY
||
412 !is_aligned_to(kernelX
, 2) || !is_aligned_to(kernelY
, 2)) {
413 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
416 if (tilingMode
< VG_TILE_FILL
||
417 tilingMode
> VG_TILE_REFLECT
) {
418 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
421 kernel
= malloc(sizeof(VGshort
)*kernelWidth
*kernelHeight
);
422 for (i
= 0; i
< kernelWidth
; ++i
) {
423 for (j
= 0; j
< kernelHeight
; ++j
) {
424 kernel
[idx
] = kernelX
[i
] * kernelY
[j
];
428 vgConvolve(dst
, src
, kernelWidth
, kernelHeight
, shiftX
, shiftY
,
429 kernel
, scale
, bias
, tilingMode
);
433 static INLINE VGfloat
compute_gaussian_componenet(VGfloat x
, VGfloat y
,
434 VGfloat stdDeviationX
,
435 VGfloat stdDeviationY
)
437 VGfloat mult
= 1 / ( 2 * M_PI
* stdDeviationX
* stdDeviationY
);
438 VGfloat e
= exp( - ( pow(x
, 2)/(2*pow(stdDeviationX
, 2)) +
439 pow(y
, 2)/(2*pow(stdDeviationY
, 2)) ) );
443 static INLINE VGint
compute_kernel_size(VGfloat deviation
)
445 VGint size
= ceil(2.146 * deviation
);
451 static void compute_gaussian_kernel(VGfloat
*kernel
,
452 VGint width
, VGint height
,
453 VGfloat stdDeviationX
,
454 VGfloat stdDeviationY
)
457 VGfloat scale
= 0.0f
;
459 for (j
= 0; j
< height
; ++j
) {
460 for (i
= 0; i
< width
; ++i
) {
461 VGint idx
= (height
- j
-1) * width
+ (width
- i
-1);
462 kernel
[idx
] = compute_gaussian_componenet(i
-(ceil(width
/2))-1,
464 stdDeviationX
, stdDeviationY
);
465 scale
+= kernel
[idx
];
469 for (j
= 0; j
< height
; ++j
) {
470 for (i
= 0; i
< width
; ++i
) {
471 VGint idx
= j
* width
+ i
;
472 kernel
[idx
] /= scale
;
477 void vegaGaussianBlur(VGImage dst
, VGImage src
,
478 VGfloat stdDeviationX
,
479 VGfloat stdDeviationY
,
480 VGTilingMode tilingMode
)
482 struct vg_context
*ctx
= vg_current_context();
483 struct vg_image
*d
, *s
;
484 VGfloat
*buffer
, *kernel
;
485 VGint kernel_width
, kernel_height
, kernel_size
;
488 struct filter_info info
;
490 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
491 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
494 if (stdDeviationX
<= 0 || stdDeviationY
<= 0) {
495 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
499 if (tilingMode
< VG_TILE_FILL
||
500 tilingMode
> VG_TILE_REFLECT
) {
501 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
505 d
= (struct vg_image
*)dst
;
506 s
= (struct vg_image
*)src
;
508 if (vg_image_overlaps(d
, s
)) {
509 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
513 kernel_width
= compute_kernel_size(stdDeviationX
);
514 kernel_height
= compute_kernel_size(stdDeviationY
);
515 kernel_size
= kernel_width
* kernel_height
;
516 kernel
= malloc(sizeof(VGfloat
)*kernel_size
);
517 compute_gaussian_kernel(kernel
, kernel_width
, kernel_height
,
518 stdDeviationX
, stdDeviationY
);
520 buffer_len
= 8 + 2 * 4 * kernel_size
;
521 buffer
= (VGfloat
*)malloc(buffer_len
* sizeof(VGfloat
));
525 buffer
[2] = 2.f
; /*unused*/
526 buffer
[3] = 4.f
; /*unused*/
528 buffer
[4] = kernel_width
* kernel_height
;
529 buffer
[5] = 1.f
;/*scale*/
530 buffer
[6] = 0.f
;/*bias*/
534 for (j
= 0; j
< kernel_height
; ++j
) {
535 for (i
= 0; i
< kernel_width
; ++i
) {
536 VGint index
= j
* kernel_width
+ i
;
539 x
= texture_offset(s
->width
, kernel_width
, i
, kernel_width
/2);
540 y
= texture_offset(s
->height
, kernel_height
, j
, kernel_height
/2);
542 buffer
[idx
+ index
*4 + 0] = x
;
543 buffer
[idx
+ index
*4 + 1] = y
;
544 buffer
[idx
+ index
*4 + 2] = 0.f
;
545 buffer
[idx
+ index
*4 + 3] = 0.f
;
548 idx
+= kernel_size
* 4;
550 for (j
= 0; j
< kernel_height
; ++j
) {
551 for (i
= 0; i
< kernel_width
; ++i
) {
552 /* transpose the kernel */
553 VGint index
= j
* kernel_width
+ i
;
554 VGint kindex
= (kernel_width
- i
- 1) * kernel_height
+ (kernel_height
- j
- 1);
555 buffer
[idx
+ index
*4 + 0] = kernel
[kindex
];
556 buffer
[idx
+ index
*4 + 1] = kernel
[kindex
];
557 buffer
[idx
+ index
*4 + 2] = kernel
[kindex
];
558 buffer
[idx
+ index
*4 + 3] = kernel
[kindex
];
564 info
.setup_shader
= &setup_convolution
;
565 info
.user_data
= (void*)(long)(buffer_len
/4);
566 info
.const_buffer
= buffer
;
567 info
.const_buffer_len
= buffer_len
* sizeof(VGfloat
);
568 info
.tiling_mode
= tilingMode
;
569 info
.extra_texture_view
= NULL
;
570 execute_filter(ctx
, &info
);
576 void vegaLookup(VGImage dst
, VGImage src
,
577 const VGubyte
* redLUT
,
578 const VGubyte
* greenLUT
,
579 const VGubyte
* blueLUT
,
580 const VGubyte
* alphaLUT
,
581 VGboolean outputLinear
,
582 VGboolean outputPremultiplied
)
584 struct vg_context
*ctx
= vg_current_context();
585 struct vg_image
*d
, *s
;
586 VGuint color_data
[256];
588 struct pipe_sampler_view
*lut_texture_view
;
590 struct filter_info info
;
592 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
593 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
597 if (!redLUT
|| !greenLUT
|| !blueLUT
|| !alphaLUT
) {
598 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
602 d
= (struct vg_image
*)dst
;
603 s
= (struct vg_image
*)src
;
605 if (vg_image_overlaps(d
, s
)) {
606 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
610 for (i
= 0; i
< 256; ++i
) {
611 color_data
[i
] = blueLUT
[i
] << 24 | greenLUT
[i
] << 16 |
612 redLUT
[i
] << 8 | alphaLUT
[i
];
614 lut_texture_view
= create_texture_1d_view(ctx
, color_data
, 255);
623 info
.setup_shader
= &setup_lookup
;
624 info
.user_data
= NULL
;
625 info
.const_buffer
= buffer
;
626 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
627 info
.tiling_mode
= VG_TILE_PAD
;
628 info
.extra_texture_view
= lut_texture_view
;
630 execute_filter(ctx
, &info
);
632 pipe_sampler_view_reference(&lut_texture_view
, NULL
);
635 void vegaLookupSingle(VGImage dst
, VGImage src
,
636 const VGuint
* lookupTable
,
637 VGImageChannel sourceChannel
,
638 VGboolean outputLinear
,
639 VGboolean outputPremultiplied
)
641 struct vg_context
*ctx
= vg_current_context();
642 struct vg_image
*d
, *s
;
643 struct pipe_sampler_view
*lut_texture_view
;
645 struct filter_info info
;
646 VGuint color_data
[256];
649 if (dst
== VG_INVALID_HANDLE
|| src
== VG_INVALID_HANDLE
) {
650 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
654 if (!lookupTable
|| !is_aligned(lookupTable
)) {
655 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
659 if (sourceChannel
!= VG_RED
&& sourceChannel
!= VG_GREEN
&&
660 sourceChannel
!= VG_BLUE
&& sourceChannel
!= VG_ALPHA
) {
661 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
665 d
= (struct vg_image
*)dst
;
666 s
= (struct vg_image
*)src
;
668 if (vg_image_overlaps(d
, s
)) {
669 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
673 vg_validate_state(ctx
);
675 for (i
= 0; i
< 256; ++i
) {
676 VGuint rgba
= lookupTable
[i
];
677 VGubyte blue
, green
, red
, alpha
;
678 red
= (rgba
& 0xff000000)>>24;
679 green
= (rgba
& 0x00ff0000)>>16;
680 blue
= (rgba
& 0x0000ff00)>> 8;
681 alpha
= (rgba
& 0x000000ff)>> 0;
682 color_data
[i
] = blue
<< 24 | green
<< 16 |
685 lut_texture_view
= create_texture_1d_view(ctx
, color_data
, 256);
694 info
.setup_shader
= &setup_lookup_single
;
695 info
.user_data
= (void*)sourceChannel
;
696 info
.const_buffer
= buffer
;
697 info
.const_buffer_len
= 4 * sizeof(VGfloat
);
698 info
.tiling_mode
= VG_TILE_PAD
;
699 info
.extra_texture_view
= lut_texture_view
;
701 execute_filter(ctx
, &info
);
703 pipe_sampler_view_reference(&lut_texture_view
, NULL
);