xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/vdpau/mixer.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker  *
3*61046927SAndroid Build Coastguard Worker  * Copyright 2010 Thomas Balling Sørensen.
4*61046927SAndroid Build Coastguard Worker  * All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the
8*61046927SAndroid Build Coastguard Worker  * "Software"), to deal in the Software without restriction, including
9*61046927SAndroid Build Coastguard Worker  * without limitation the rights to use, copy, modify, merge, publish,
10*61046927SAndroid Build Coastguard Worker  * distribute, sub license, and/or sell copies of the Software, and to
11*61046927SAndroid Build Coastguard Worker  * permit persons to whom the Software is furnished to do so, subject to
12*61046927SAndroid Build Coastguard Worker  * the following conditions:
13*61046927SAndroid Build Coastguard Worker  *
14*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the
15*61046927SAndroid Build Coastguard Worker  * next paragraph) shall be included in all copies or substantial portions
16*61046927SAndroid Build Coastguard Worker  * of the Software.
17*61046927SAndroid Build Coastguard Worker  *
18*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*61046927SAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21*61046927SAndroid Build Coastguard Worker  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22*61046927SAndroid Build Coastguard Worker  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23*61046927SAndroid Build Coastguard Worker  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24*61046927SAndroid Build Coastguard Worker  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  **************************************************************************/
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker #include <vdpau/vdpau.h>
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include "util/u_memory.h"
31*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "vl/vl_csc.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker #include "vdpau_private.h"
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker /**
38*61046927SAndroid Build Coastguard Worker  * Create a VdpVideoMixer.
39*61046927SAndroid Build Coastguard Worker  */
40*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerCreate(VdpDevice device,uint32_t feature_count,VdpVideoMixerFeature const * features,uint32_t parameter_count,VdpVideoMixerParameter const * parameters,void const * const * parameter_values,VdpVideoMixer * mixer)41*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerCreate(VdpDevice device,
42*61046927SAndroid Build Coastguard Worker                       uint32_t feature_count,
43*61046927SAndroid Build Coastguard Worker                       VdpVideoMixerFeature const *features,
44*61046927SAndroid Build Coastguard Worker                       uint32_t parameter_count,
45*61046927SAndroid Build Coastguard Worker                       VdpVideoMixerParameter const *parameters,
46*61046927SAndroid Build Coastguard Worker                       void const *const *parameter_values,
47*61046927SAndroid Build Coastguard Worker                       VdpVideoMixer *mixer)
48*61046927SAndroid Build Coastguard Worker {
49*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer = NULL;
50*61046927SAndroid Build Coastguard Worker    VdpStatus ret;
51*61046927SAndroid Build Coastguard Worker    struct pipe_screen *screen;
52*61046927SAndroid Build Coastguard Worker    unsigned max_size, i;
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker    vlVdpDevice *dev = vlGetDataHTAB(device);
55*61046927SAndroid Build Coastguard Worker    if (!dev)
56*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
57*61046927SAndroid Build Coastguard Worker    screen = dev->vscreen->pscreen;
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker    vmixer = CALLOC(1, sizeof(vlVdpVideoMixer));
60*61046927SAndroid Build Coastguard Worker    if (!vmixer)
61*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_RESOURCES;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    DeviceReference(&vmixer->device, dev);
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    mtx_lock(&dev->mutex);
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    if (!vl_compositor_init_state(&vmixer->cstate, dev->context)) {
68*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_ERROR;
69*61046927SAndroid Build Coastguard Worker       goto no_compositor_state;
70*61046927SAndroid Build Coastguard Worker    }
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker    vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &vmixer->csc);
73*61046927SAndroid Build Coastguard Worker    if (!debug_get_bool_option("G3DVL_NO_CSC", false)) {
74*61046927SAndroid Build Coastguard Worker       if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc, 1.0f, 0.0f)) {
75*61046927SAndroid Build Coastguard Worker          ret = VDP_STATUS_ERROR;
76*61046927SAndroid Build Coastguard Worker          goto err_csc_matrix;
77*61046927SAndroid Build Coastguard Worker       }
78*61046927SAndroid Build Coastguard Worker    }
79*61046927SAndroid Build Coastguard Worker 
80*61046927SAndroid Build Coastguard Worker    *mixer = vlAddDataHTAB(vmixer);
81*61046927SAndroid Build Coastguard Worker    if (*mixer == 0) {
82*61046927SAndroid Build Coastguard Worker       ret = VDP_STATUS_ERROR;
83*61046927SAndroid Build Coastguard Worker       goto no_handle;
84*61046927SAndroid Build Coastguard Worker    }
85*61046927SAndroid Build Coastguard Worker 
86*61046927SAndroid Build Coastguard Worker    ret = VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
87*61046927SAndroid Build Coastguard Worker    for (i = 0; i < feature_count; ++i) {
88*61046927SAndroid Build Coastguard Worker       switch (features[i]) {
89*61046927SAndroid Build Coastguard Worker       /* they are valid, but we doesn't support them */
90*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
91*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
92*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
93*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
94*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5:
95*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6:
96*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7:
97*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8:
98*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
99*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
100*61046927SAndroid Build Coastguard Worker          break;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
103*61046927SAndroid Build Coastguard Worker          vmixer->deint.supported = true;
104*61046927SAndroid Build Coastguard Worker          break;
105*61046927SAndroid Build Coastguard Worker 
106*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
107*61046927SAndroid Build Coastguard Worker          vmixer->sharpness.supported = true;
108*61046927SAndroid Build Coastguard Worker          break;
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
111*61046927SAndroid Build Coastguard Worker          vmixer->noise_reduction.supported = true;
112*61046927SAndroid Build Coastguard Worker          break;
113*61046927SAndroid Build Coastguard Worker 
114*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
115*61046927SAndroid Build Coastguard Worker          vmixer->luma_key.supported = true;
116*61046927SAndroid Build Coastguard Worker          break;
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
119*61046927SAndroid Build Coastguard Worker          vmixer->bicubic.supported = true;
120*61046927SAndroid Build Coastguard Worker          break;
121*61046927SAndroid Build Coastguard Worker       default: goto no_params;
122*61046927SAndroid Build Coastguard Worker       }
123*61046927SAndroid Build Coastguard Worker    }
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
126*61046927SAndroid Build Coastguard Worker    ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
127*61046927SAndroid Build Coastguard Worker    for (i = 0; i < parameter_count; ++i) {
128*61046927SAndroid Build Coastguard Worker       switch (parameters[i]) {
129*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
130*61046927SAndroid Build Coastguard Worker          vmixer->video_width = *(uint32_t*)parameter_values[i];
131*61046927SAndroid Build Coastguard Worker          break;
132*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
133*61046927SAndroid Build Coastguard Worker          vmixer->video_height = *(uint32_t*)parameter_values[i];
134*61046927SAndroid Build Coastguard Worker          break;
135*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
136*61046927SAndroid Build Coastguard Worker          vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]);
137*61046927SAndroid Build Coastguard Worker          break;
138*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
139*61046927SAndroid Build Coastguard Worker          vmixer->max_layers = *(uint32_t*)parameter_values[i];
140*61046927SAndroid Build Coastguard Worker          break;
141*61046927SAndroid Build Coastguard Worker       default: goto no_params;
142*61046927SAndroid Build Coastguard Worker       }
143*61046927SAndroid Build Coastguard Worker    }
144*61046927SAndroid Build Coastguard Worker    ret = VDP_STATUS_INVALID_VALUE;
145*61046927SAndroid Build Coastguard Worker    if (vmixer->max_layers > 4) {
146*61046927SAndroid Build Coastguard Worker       VDPAU_MSG(VDPAU_WARN, "[VDPAU] Max layers %u > 4 not supported\n", vmixer->max_layers);
147*61046927SAndroid Build Coastguard Worker       goto no_params;
148*61046927SAndroid Build Coastguard Worker    }
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker    max_size = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
151*61046927SAndroid Build Coastguard Worker    if (vmixer->video_width < 48 || vmixer->video_width > max_size) {
152*61046927SAndroid Build Coastguard Worker       VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u not valid for width\n",
153*61046927SAndroid Build Coastguard Worker                 vmixer->video_width, max_size);
154*61046927SAndroid Build Coastguard Worker       goto no_params;
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker    if (vmixer->video_height < 48 || vmixer->video_height > max_size) {
157*61046927SAndroid Build Coastguard Worker       VDPAU_MSG(VDPAU_WARN, "[VDPAU] 48 < %u < %u  not valid for height\n",
158*61046927SAndroid Build Coastguard Worker                 vmixer->video_height, max_size);
159*61046927SAndroid Build Coastguard Worker       goto no_params;
160*61046927SAndroid Build Coastguard Worker    }
161*61046927SAndroid Build Coastguard Worker    vmixer->luma_key.luma_min = 1.0f;
162*61046927SAndroid Build Coastguard Worker    vmixer->luma_key.luma_max = 0.0f;
163*61046927SAndroid Build Coastguard Worker    mtx_unlock(&dev->mutex);
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker no_params:
168*61046927SAndroid Build Coastguard Worker    vlRemoveDataHTAB(*mixer);
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker no_handle:
171*61046927SAndroid Build Coastguard Worker err_csc_matrix:
172*61046927SAndroid Build Coastguard Worker    vl_compositor_cleanup_state(&vmixer->cstate);
173*61046927SAndroid Build Coastguard Worker no_compositor_state:
174*61046927SAndroid Build Coastguard Worker    mtx_unlock(&dev->mutex);
175*61046927SAndroid Build Coastguard Worker    DeviceReference(&vmixer->device, NULL);
176*61046927SAndroid Build Coastguard Worker    FREE(vmixer);
177*61046927SAndroid Build Coastguard Worker    return ret;
178*61046927SAndroid Build Coastguard Worker }
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker /**
181*61046927SAndroid Build Coastguard Worker  * Destroy a VdpVideoMixer.
182*61046927SAndroid Build Coastguard Worker  */
183*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerDestroy(VdpVideoMixer mixer)184*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
185*61046927SAndroid Build Coastguard Worker {
186*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer;
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker    vmixer = vlGetDataHTAB(mixer);
189*61046927SAndroid Build Coastguard Worker    if (!vmixer)
190*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    mtx_lock(&vmixer->device->mutex);
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    vlRemoveDataHTAB(mixer);
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    vl_compositor_cleanup_state(&vmixer->cstate);
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    if (vmixer->deint.filter) {
199*61046927SAndroid Build Coastguard Worker       vl_deint_filter_cleanup(vmixer->deint.filter);
200*61046927SAndroid Build Coastguard Worker       FREE(vmixer->deint.filter);
201*61046927SAndroid Build Coastguard Worker    }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker    if (vmixer->noise_reduction.filter) {
204*61046927SAndroid Build Coastguard Worker       vl_median_filter_cleanup(vmixer->noise_reduction.filter);
205*61046927SAndroid Build Coastguard Worker       FREE(vmixer->noise_reduction.filter);
206*61046927SAndroid Build Coastguard Worker    }
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker    if (vmixer->sharpness.filter) {
209*61046927SAndroid Build Coastguard Worker       vl_matrix_filter_cleanup(vmixer->sharpness.filter);
210*61046927SAndroid Build Coastguard Worker       FREE(vmixer->sharpness.filter);
211*61046927SAndroid Build Coastguard Worker    }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker    if (vmixer->bicubic.filter) {
214*61046927SAndroid Build Coastguard Worker       vl_bicubic_filter_cleanup(vmixer->bicubic.filter);
215*61046927SAndroid Build Coastguard Worker       FREE(vmixer->bicubic.filter);
216*61046927SAndroid Build Coastguard Worker    }
217*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
218*61046927SAndroid Build Coastguard Worker    DeviceReference(&vmixer->device, NULL);
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker    FREE(vmixer);
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
223*61046927SAndroid Build Coastguard Worker }
224*61046927SAndroid Build Coastguard Worker 
225*61046927SAndroid Build Coastguard Worker /**
226*61046927SAndroid Build Coastguard Worker  * Perform a video post-processing and compositing operation.
227*61046927SAndroid Build Coastguard Worker  */
vlVdpVideoMixerRender(VdpVideoMixer mixer,VdpOutputSurface background_surface,VdpRect const * background_source_rect,VdpVideoMixerPictureStructure current_picture_structure,uint32_t video_surface_past_count,VdpVideoSurface const * video_surface_past,VdpVideoSurface video_surface_current,uint32_t video_surface_future_count,VdpVideoSurface const * video_surface_future,VdpRect const * video_source_rect,VdpOutputSurface destination_surface,VdpRect const * destination_rect,VdpRect const * destination_video_rect,uint32_t layer_count,VdpLayer const * layers)228*61046927SAndroid Build Coastguard Worker VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
229*61046927SAndroid Build Coastguard Worker                                 VdpOutputSurface background_surface,
230*61046927SAndroid Build Coastguard Worker                                 VdpRect const *background_source_rect,
231*61046927SAndroid Build Coastguard Worker                                 VdpVideoMixerPictureStructure current_picture_structure,
232*61046927SAndroid Build Coastguard Worker                                 uint32_t video_surface_past_count,
233*61046927SAndroid Build Coastguard Worker                                 VdpVideoSurface const *video_surface_past,
234*61046927SAndroid Build Coastguard Worker                                 VdpVideoSurface video_surface_current,
235*61046927SAndroid Build Coastguard Worker                                 uint32_t video_surface_future_count,
236*61046927SAndroid Build Coastguard Worker                                 VdpVideoSurface const *video_surface_future,
237*61046927SAndroid Build Coastguard Worker                                 VdpRect const *video_source_rect,
238*61046927SAndroid Build Coastguard Worker                                 VdpOutputSurface destination_surface,
239*61046927SAndroid Build Coastguard Worker                                 VdpRect const *destination_rect,
240*61046927SAndroid Build Coastguard Worker                                 VdpRect const *destination_video_rect,
241*61046927SAndroid Build Coastguard Worker                                 uint32_t layer_count,
242*61046927SAndroid Build Coastguard Worker                                 VdpLayer const *layers)
243*61046927SAndroid Build Coastguard Worker {
244*61046927SAndroid Build Coastguard Worker    enum vl_compositor_deinterlace deinterlace;
245*61046927SAndroid Build Coastguard Worker    struct u_rect rect, clip, *prect, dirty_area;
246*61046927SAndroid Build Coastguard Worker    unsigned i, layer = 0;
247*61046927SAndroid Build Coastguard Worker    struct pipe_video_buffer *video_buffer;
248*61046927SAndroid Build Coastguard Worker    struct pipe_sampler_view *sampler_view, sv_templ;
249*61046927SAndroid Build Coastguard Worker    struct pipe_surface *surface, surf_templ;
250*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = NULL;
251*61046927SAndroid Build Coastguard Worker    struct pipe_resource res_tmpl, *res;
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer;
254*61046927SAndroid Build Coastguard Worker    vlVdpSurface *surf;
255*61046927SAndroid Build Coastguard Worker    vlVdpOutputSurface *dst, *bg = NULL;
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker    struct vl_compositor *compositor;
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker    vmixer = vlGetDataHTAB(mixer);
260*61046927SAndroid Build Coastguard Worker    if (!vmixer)
261*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker    compositor = &vmixer->device->compositor;
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    surf = vlGetDataHTAB(video_surface_current);
266*61046927SAndroid Build Coastguard Worker    if (!surf)
267*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
268*61046927SAndroid Build Coastguard Worker    video_buffer = surf->video_buffer;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    if (surf->device != vmixer->device)
271*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    if (vmixer->video_width > video_buffer->width ||
274*61046927SAndroid Build Coastguard Worker        vmixer->video_height > video_buffer->height ||
275*61046927SAndroid Build Coastguard Worker        vmixer->chroma_format != pipe_format_to_chroma_format(video_buffer->buffer_format))
276*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_SIZE;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    if (layer_count > vmixer->max_layers)
279*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_VALUE;
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker    dst = vlGetDataHTAB(destination_surface);
282*61046927SAndroid Build Coastguard Worker    if (!dst)
283*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    if (background_surface != VDP_INVALID_HANDLE) {
286*61046927SAndroid Build Coastguard Worker       bg = vlGetDataHTAB(background_surface);
287*61046927SAndroid Build Coastguard Worker       if (!bg)
288*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_HANDLE;
289*61046927SAndroid Build Coastguard Worker    }
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    mtx_lock(&vmixer->device->mutex);
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker    vl_compositor_clear_layers(&vmixer->cstate);
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker    if (bg)
296*61046927SAndroid Build Coastguard Worker       vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer++, bg->sampler_view,
297*61046927SAndroid Build Coastguard Worker                                    RectToPipe(background_source_rect, &rect), NULL, NULL);
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker    switch (current_picture_structure) {
300*61046927SAndroid Build Coastguard Worker    case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD:
301*61046927SAndroid Build Coastguard Worker       deinterlace = VL_COMPOSITOR_BOB_TOP;
302*61046927SAndroid Build Coastguard Worker       break;
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
305*61046927SAndroid Build Coastguard Worker       deinterlace = VL_COMPOSITOR_BOB_BOTTOM;
306*61046927SAndroid Build Coastguard Worker       break;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME:
309*61046927SAndroid Build Coastguard Worker       deinterlace = VL_COMPOSITOR_WEAVE;
310*61046927SAndroid Build Coastguard Worker       break;
311*61046927SAndroid Build Coastguard Worker 
312*61046927SAndroid Build Coastguard Worker    default:
313*61046927SAndroid Build Coastguard Worker       mtx_unlock(&vmixer->device->mutex);
314*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE;
315*61046927SAndroid Build Coastguard Worker    }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker    if (deinterlace != VL_COMPOSITOR_WEAVE && vmixer->deint.enabled &&
318*61046927SAndroid Build Coastguard Worker        video_surface_past_count > 1 && video_surface_future_count > 0) {
319*61046927SAndroid Build Coastguard Worker       vlVdpSurface *prevprev = vlGetDataHTAB(video_surface_past[1]);
320*61046927SAndroid Build Coastguard Worker       vlVdpSurface *prev = vlGetDataHTAB(video_surface_past[0]);
321*61046927SAndroid Build Coastguard Worker       vlVdpSurface *next = vlGetDataHTAB(video_surface_future[0]);
322*61046927SAndroid Build Coastguard Worker       if (prevprev && prev && next &&
323*61046927SAndroid Build Coastguard Worker           vl_deint_filter_check_buffers(vmixer->deint.filter,
324*61046927SAndroid Build Coastguard Worker           prevprev->video_buffer, prev->video_buffer, surf->video_buffer, next->video_buffer)) {
325*61046927SAndroid Build Coastguard Worker          vl_deint_filter_render(vmixer->deint.filter, prevprev->video_buffer,
326*61046927SAndroid Build Coastguard Worker                                 prev->video_buffer, surf->video_buffer,
327*61046927SAndroid Build Coastguard Worker                                 next->video_buffer,
328*61046927SAndroid Build Coastguard Worker                                 deinterlace == VL_COMPOSITOR_BOB_BOTTOM);
329*61046927SAndroid Build Coastguard Worker          deinterlace = VL_COMPOSITOR_WEAVE;
330*61046927SAndroid Build Coastguard Worker          video_buffer = vmixer->deint.filter->video_buffer;
331*61046927SAndroid Build Coastguard Worker       }
332*61046927SAndroid Build Coastguard Worker    }
333*61046927SAndroid Build Coastguard Worker 
334*61046927SAndroid Build Coastguard Worker    if (!destination_video_rect)
335*61046927SAndroid Build Coastguard Worker       destination_video_rect = video_source_rect;
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker    prect = RectToPipe(video_source_rect, &rect);
338*61046927SAndroid Build Coastguard Worker    if (!prect) {
339*61046927SAndroid Build Coastguard Worker       rect.x0 = 0;
340*61046927SAndroid Build Coastguard Worker       rect.y0 = 0;
341*61046927SAndroid Build Coastguard Worker       rect.x1 = surf->templat.width;
342*61046927SAndroid Build Coastguard Worker       rect.y1 = surf->templat.height;
343*61046927SAndroid Build Coastguard Worker       prect = &rect;
344*61046927SAndroid Build Coastguard Worker    }
345*61046927SAndroid Build Coastguard Worker    vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    if (vmixer->bicubic.filter || vmixer->sharpness.filter || vmixer->noise_reduction.filter) {
348*61046927SAndroid Build Coastguard Worker       pipe = vmixer->device->context;
349*61046927SAndroid Build Coastguard Worker       memset(&res_tmpl, 0, sizeof(res_tmpl));
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker       res_tmpl.target = PIPE_TEXTURE_2D;
352*61046927SAndroid Build Coastguard Worker       res_tmpl.format = dst->sampler_view->format;
353*61046927SAndroid Build Coastguard Worker       res_tmpl.depth0 = 1;
354*61046927SAndroid Build Coastguard Worker       res_tmpl.array_size = 1;
355*61046927SAndroid Build Coastguard Worker       res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
356*61046927SAndroid Build Coastguard Worker       res_tmpl.usage = PIPE_USAGE_DEFAULT;
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker       if (!vmixer->bicubic.filter) {
359*61046927SAndroid Build Coastguard Worker          res_tmpl.width0 = dst->surface->width;
360*61046927SAndroid Build Coastguard Worker          res_tmpl.height0 = dst->surface->height;
361*61046927SAndroid Build Coastguard Worker       } else {
362*61046927SAndroid Build Coastguard Worker          res_tmpl.width0 = surf->templat.width;
363*61046927SAndroid Build Coastguard Worker          res_tmpl.height0 = surf->templat.height;
364*61046927SAndroid Build Coastguard Worker       }
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker       res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker       vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
369*61046927SAndroid Build Coastguard Worker       sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker       memset(&surf_templ, 0, sizeof(surf_templ));
372*61046927SAndroid Build Coastguard Worker       surf_templ.format = res->format;
373*61046927SAndroid Build Coastguard Worker       surface = pipe->create_surface(pipe, res, &surf_templ);
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker       vl_compositor_reset_dirty_area(&dirty_area);
376*61046927SAndroid Build Coastguard Worker       pipe_resource_reference(&res, NULL);
377*61046927SAndroid Build Coastguard Worker    } else {
378*61046927SAndroid Build Coastguard Worker       surface = dst->surface;
379*61046927SAndroid Build Coastguard Worker       sampler_view = dst->sampler_view;
380*61046927SAndroid Build Coastguard Worker       dirty_area = dst->dirty_area;
381*61046927SAndroid Build Coastguard Worker    }
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker    if (!vmixer->bicubic.filter) {
384*61046927SAndroid Build Coastguard Worker       vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect));
385*61046927SAndroid Build Coastguard Worker       vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &clip));
386*61046927SAndroid Build Coastguard Worker    }
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker    for (i = 0; i < layer_count; ++i) {
389*61046927SAndroid Build Coastguard Worker       vlVdpOutputSurface *src = vlGetDataHTAB(layers->source_surface);
390*61046927SAndroid Build Coastguard Worker       if (!src) {
391*61046927SAndroid Build Coastguard Worker          mtx_unlock(&vmixer->device->mutex);
392*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_HANDLE;
393*61046927SAndroid Build Coastguard Worker       }
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker       assert(layers->struct_version == VDP_LAYER_VERSION);
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker       vl_compositor_set_rgba_layer(&vmixer->cstate, compositor, layer, src->sampler_view,
398*61046927SAndroid Build Coastguard Worker                                    RectToPipe(layers->source_rect, &rect), NULL, NULL);
399*61046927SAndroid Build Coastguard Worker       vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(layers->destination_rect, &rect));
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker       ++layers;
402*61046927SAndroid Build Coastguard Worker    }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker    vl_compositor_render(&vmixer->cstate, compositor, surface, &dirty_area, true);
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    if (vmixer->noise_reduction.filter) {
407*61046927SAndroid Build Coastguard Worker       if (!vmixer->sharpness.filter && !vmixer->bicubic.filter) {
408*61046927SAndroid Build Coastguard Worker          vl_median_filter_render(vmixer->noise_reduction.filter,
409*61046927SAndroid Build Coastguard Worker                                  sampler_view, dst->surface);
410*61046927SAndroid Build Coastguard Worker       } else {
411*61046927SAndroid Build Coastguard Worker          res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
412*61046927SAndroid Build Coastguard Worker          struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ);
413*61046927SAndroid Build Coastguard Worker          struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ);
414*61046927SAndroid Build Coastguard Worker          pipe_resource_reference(&res, NULL);
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker          vl_median_filter_render(vmixer->noise_reduction.filter,
417*61046927SAndroid Build Coastguard Worker                                  sampler_view, surface_temp);
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker          pipe_sampler_view_reference(&sampler_view, NULL);
420*61046927SAndroid Build Coastguard Worker          pipe_surface_reference(&surface, NULL);
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker          sampler_view = sampler_view_temp;
423*61046927SAndroid Build Coastguard Worker          surface = surface_temp;
424*61046927SAndroid Build Coastguard Worker       }
425*61046927SAndroid Build Coastguard Worker    }
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    if (vmixer->sharpness.filter) {
428*61046927SAndroid Build Coastguard Worker       if (!vmixer->bicubic.filter) {
429*61046927SAndroid Build Coastguard Worker          vl_matrix_filter_render(vmixer->sharpness.filter,
430*61046927SAndroid Build Coastguard Worker                                  sampler_view, dst->surface);
431*61046927SAndroid Build Coastguard Worker       } else {
432*61046927SAndroid Build Coastguard Worker          res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
433*61046927SAndroid Build Coastguard Worker          struct pipe_sampler_view *sampler_view_temp = pipe->create_sampler_view(pipe, res, &sv_templ);
434*61046927SAndroid Build Coastguard Worker          struct pipe_surface *surface_temp = pipe->create_surface(pipe, res, &surf_templ);
435*61046927SAndroid Build Coastguard Worker          pipe_resource_reference(&res, NULL);
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker          vl_matrix_filter_render(vmixer->sharpness.filter,
438*61046927SAndroid Build Coastguard Worker                                  sampler_view, surface_temp);
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker          pipe_sampler_view_reference(&sampler_view, NULL);
441*61046927SAndroid Build Coastguard Worker          pipe_surface_reference(&surface, NULL);
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker          sampler_view = sampler_view_temp;
444*61046927SAndroid Build Coastguard Worker          surface = surface_temp;
445*61046927SAndroid Build Coastguard Worker       }
446*61046927SAndroid Build Coastguard Worker    }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    if (vmixer->bicubic.filter)
449*61046927SAndroid Build Coastguard Worker       vl_bicubic_filter_render(vmixer->bicubic.filter,
450*61046927SAndroid Build Coastguard Worker                                sampler_view, dst->surface,
451*61046927SAndroid Build Coastguard Worker                                RectToPipe(destination_video_rect, &rect),
452*61046927SAndroid Build Coastguard Worker                                RectToPipe(destination_rect, &clip));
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker    if(surface != dst->surface) {
455*61046927SAndroid Build Coastguard Worker       pipe_sampler_view_reference(&sampler_view, NULL);
456*61046927SAndroid Build Coastguard Worker       pipe_surface_reference(&surface, NULL);
457*61046927SAndroid Build Coastguard Worker    }
458*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
459*61046927SAndroid Build Coastguard Worker 
460*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
461*61046927SAndroid Build Coastguard Worker }
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker static void
vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer * vmixer)464*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer *vmixer)
465*61046927SAndroid Build Coastguard Worker {
466*61046927SAndroid Build Coastguard Worker    struct pipe_context *pipe = vmixer->device->context;
467*61046927SAndroid Build Coastguard Worker    assert(vmixer);
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker    /* remove existing filter */
470*61046927SAndroid Build Coastguard Worker    if (vmixer->deint.filter) {
471*61046927SAndroid Build Coastguard Worker       vl_deint_filter_cleanup(vmixer->deint.filter);
472*61046927SAndroid Build Coastguard Worker       FREE(vmixer->deint.filter);
473*61046927SAndroid Build Coastguard Worker       vmixer->deint.filter = NULL;
474*61046927SAndroid Build Coastguard Worker    }
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    /* create a new filter if requested */
477*61046927SAndroid Build Coastguard Worker    if (vmixer->deint.enabled && vmixer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
478*61046927SAndroid Build Coastguard Worker       vmixer->deint.filter = MALLOC(sizeof(struct vl_deint_filter));
479*61046927SAndroid Build Coastguard Worker       vmixer->deint.enabled = vl_deint_filter_init(vmixer->deint.filter, pipe,
480*61046927SAndroid Build Coastguard Worker             vmixer->video_width, vmixer->video_height,
481*61046927SAndroid Build Coastguard Worker             vmixer->skip_chroma_deint, vmixer->deint.spatial, false);
482*61046927SAndroid Build Coastguard Worker       if (!vmixer->deint.enabled) {
483*61046927SAndroid Build Coastguard Worker          FREE(vmixer->deint.filter);
484*61046927SAndroid Build Coastguard Worker       }
485*61046927SAndroid Build Coastguard Worker    }
486*61046927SAndroid Build Coastguard Worker }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker /**
489*61046927SAndroid Build Coastguard Worker  * Update the noise reduction setting
490*61046927SAndroid Build Coastguard Worker  */
491*61046927SAndroid Build Coastguard Worker static void
vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer * vmixer)492*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerUpdateNoiseReductionFilter(vlVdpVideoMixer *vmixer)
493*61046927SAndroid Build Coastguard Worker {
494*61046927SAndroid Build Coastguard Worker    assert(vmixer);
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    /* if present remove the old filter first */
497*61046927SAndroid Build Coastguard Worker    if (vmixer->noise_reduction.filter) {
498*61046927SAndroid Build Coastguard Worker       vl_median_filter_cleanup(vmixer->noise_reduction.filter);
499*61046927SAndroid Build Coastguard Worker       FREE(vmixer->noise_reduction.filter);
500*61046927SAndroid Build Coastguard Worker       vmixer->noise_reduction.filter = NULL;
501*61046927SAndroid Build Coastguard Worker    }
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    /* and create a new filter as needed */
504*61046927SAndroid Build Coastguard Worker    if (vmixer->noise_reduction. enabled && vmixer->noise_reduction.level > 0) {
505*61046927SAndroid Build Coastguard Worker       vmixer->noise_reduction.filter = MALLOC(sizeof(struct vl_median_filter));
506*61046927SAndroid Build Coastguard Worker       vl_median_filter_init(vmixer->noise_reduction.filter, vmixer->device->context,
507*61046927SAndroid Build Coastguard Worker                             vmixer->video_width, vmixer->video_height,
508*61046927SAndroid Build Coastguard Worker                             vmixer->noise_reduction.level + 1,
509*61046927SAndroid Build Coastguard Worker                             VL_MEDIAN_FILTER_CROSS);
510*61046927SAndroid Build Coastguard Worker    }
511*61046927SAndroid Build Coastguard Worker }
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker static void
vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer * vmixer)514*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer)
515*61046927SAndroid Build Coastguard Worker {
516*61046927SAndroid Build Coastguard Worker    assert(vmixer);
517*61046927SAndroid Build Coastguard Worker 
518*61046927SAndroid Build Coastguard Worker    /* if present remove the old filter first */
519*61046927SAndroid Build Coastguard Worker    if (vmixer->sharpness.filter) {
520*61046927SAndroid Build Coastguard Worker       vl_matrix_filter_cleanup(vmixer->sharpness.filter);
521*61046927SAndroid Build Coastguard Worker       FREE(vmixer->sharpness.filter);
522*61046927SAndroid Build Coastguard Worker       vmixer->sharpness.filter = NULL;
523*61046927SAndroid Build Coastguard Worker    }
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker    /* and create a new filter as needed */
526*61046927SAndroid Build Coastguard Worker    if (vmixer->sharpness.enabled && vmixer->sharpness.value != 0.0f) {
527*61046927SAndroid Build Coastguard Worker       float matrix[9];
528*61046927SAndroid Build Coastguard Worker       unsigned i;
529*61046927SAndroid Build Coastguard Worker 
530*61046927SAndroid Build Coastguard Worker       if (vmixer->sharpness.value > 0.0f) {
531*61046927SAndroid Build Coastguard Worker          matrix[0] = -1.0f; matrix[1] = -1.0f; matrix[2] = -1.0f;
532*61046927SAndroid Build Coastguard Worker          matrix[3] = -1.0f; matrix[4] =  8.0f; matrix[5] = -1.0f;
533*61046927SAndroid Build Coastguard Worker          matrix[6] = -1.0f; matrix[7] = -1.0f; matrix[8] = -1.0f;
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker          for (i = 0; i < 9; ++i)
536*61046927SAndroid Build Coastguard Worker             matrix[i] *= vmixer->sharpness.value;
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker          matrix[4] += 1.0f;
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker       } else {
541*61046927SAndroid Build Coastguard Worker          matrix[0] = 1.0f; matrix[1] = 2.0f; matrix[2] = 1.0f;
542*61046927SAndroid Build Coastguard Worker          matrix[3] = 2.0f; matrix[4] = 4.0f; matrix[5] = 2.0f;
543*61046927SAndroid Build Coastguard Worker          matrix[6] = 1.0f; matrix[7] = 2.0f; matrix[8] = 1.0f;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker          for (i = 0; i < 9; ++i)
546*61046927SAndroid Build Coastguard Worker                matrix[i] *= fabsf(vmixer->sharpness.value) / 16.0f;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker          matrix[4] += 1.0f - fabsf(vmixer->sharpness.value);
549*61046927SAndroid Build Coastguard Worker       }
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker       vmixer->sharpness.filter = MALLOC(sizeof(struct vl_matrix_filter));
552*61046927SAndroid Build Coastguard Worker       vl_matrix_filter_init(vmixer->sharpness.filter, vmixer->device->context,
553*61046927SAndroid Build Coastguard Worker                             vmixer->video_width, vmixer->video_height,
554*61046927SAndroid Build Coastguard Worker                             3, 3, matrix);
555*61046927SAndroid Build Coastguard Worker    }
556*61046927SAndroid Build Coastguard Worker }
557*61046927SAndroid Build Coastguard Worker 
558*61046927SAndroid Build Coastguard Worker /**
559*61046927SAndroid Build Coastguard Worker  * Update the bicubic filter
560*61046927SAndroid Build Coastguard Worker  */
561*61046927SAndroid Build Coastguard Worker static void
vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer * vmixer)562*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer *vmixer)
563*61046927SAndroid Build Coastguard Worker {
564*61046927SAndroid Build Coastguard Worker    assert(vmixer);
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    /* if present remove the old filter first */
567*61046927SAndroid Build Coastguard Worker    if (vmixer->bicubic.filter) {
568*61046927SAndroid Build Coastguard Worker       vl_bicubic_filter_cleanup(vmixer->bicubic.filter);
569*61046927SAndroid Build Coastguard Worker       FREE(vmixer->bicubic.filter);
570*61046927SAndroid Build Coastguard Worker       vmixer->bicubic.filter = NULL;
571*61046927SAndroid Build Coastguard Worker    }
572*61046927SAndroid Build Coastguard Worker    /* and create a new filter as needed */
573*61046927SAndroid Build Coastguard Worker    if (vmixer->bicubic.enabled) {
574*61046927SAndroid Build Coastguard Worker       vmixer->bicubic.filter = MALLOC(sizeof(struct vl_bicubic_filter));
575*61046927SAndroid Build Coastguard Worker       vl_bicubic_filter_init(vmixer->bicubic.filter, vmixer->device->context,
576*61046927SAndroid Build Coastguard Worker                             vmixer->video_width, vmixer->video_height);
577*61046927SAndroid Build Coastguard Worker    }
578*61046927SAndroid Build Coastguard Worker }
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker /**
581*61046927SAndroid Build Coastguard Worker  * Retrieve whether features were requested at creation time.
582*61046927SAndroid Build Coastguard Worker  */
583*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,uint32_t feature_count,VdpVideoMixerFeature const * features,VdpBool * feature_supports)584*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
585*61046927SAndroid Build Coastguard Worker                                  uint32_t feature_count,
586*61046927SAndroid Build Coastguard Worker                                  VdpVideoMixerFeature const *features,
587*61046927SAndroid Build Coastguard Worker                                  VdpBool *feature_supports)
588*61046927SAndroid Build Coastguard Worker {
589*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer;
590*61046927SAndroid Build Coastguard Worker    unsigned i;
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker    if (!(features && feature_supports))
593*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
594*61046927SAndroid Build Coastguard Worker 
595*61046927SAndroid Build Coastguard Worker    vmixer = vlGetDataHTAB(mixer);
596*61046927SAndroid Build Coastguard Worker    if (!vmixer)
597*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker    for (i = 0; i < feature_count; ++i) {
600*61046927SAndroid Build Coastguard Worker       switch (features[i]) {
601*61046927SAndroid Build Coastguard Worker       /* they are valid, but we doesn't support them */
602*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
603*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
604*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
605*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
606*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5:
607*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6:
608*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7:
609*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8:
610*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
611*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
612*61046927SAndroid Build Coastguard Worker          feature_supports[i] = false;
613*61046927SAndroid Build Coastguard Worker          break;
614*61046927SAndroid Build Coastguard Worker 
615*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
616*61046927SAndroid Build Coastguard Worker          feature_supports[i] = vmixer->deint.supported;
617*61046927SAndroid Build Coastguard Worker          break;
618*61046927SAndroid Build Coastguard Worker 
619*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
620*61046927SAndroid Build Coastguard Worker          feature_supports[i] = vmixer->sharpness.supported;
621*61046927SAndroid Build Coastguard Worker          break;
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
624*61046927SAndroid Build Coastguard Worker          feature_supports[i] = vmixer->noise_reduction.supported;
625*61046927SAndroid Build Coastguard Worker          break;
626*61046927SAndroid Build Coastguard Worker 
627*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
628*61046927SAndroid Build Coastguard Worker          feature_supports[i] = vmixer->luma_key.supported;
629*61046927SAndroid Build Coastguard Worker          break;
630*61046927SAndroid Build Coastguard Worker 
631*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
632*61046927SAndroid Build Coastguard Worker          feature_supports[i] = vmixer->bicubic.supported;
633*61046927SAndroid Build Coastguard Worker          break;
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker       default:
636*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
637*61046927SAndroid Build Coastguard Worker       }
638*61046927SAndroid Build Coastguard Worker    }
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
641*61046927SAndroid Build Coastguard Worker }
642*61046927SAndroid Build Coastguard Worker 
643*61046927SAndroid Build Coastguard Worker /**
644*61046927SAndroid Build Coastguard Worker  * Enable or disable features.
645*61046927SAndroid Build Coastguard Worker  */
646*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,uint32_t feature_count,VdpVideoMixerFeature const * features,VdpBool const * feature_enables)647*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
648*61046927SAndroid Build Coastguard Worker                                  uint32_t feature_count,
649*61046927SAndroid Build Coastguard Worker                                  VdpVideoMixerFeature const *features,
650*61046927SAndroid Build Coastguard Worker                                  VdpBool const *feature_enables)
651*61046927SAndroid Build Coastguard Worker {
652*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer;
653*61046927SAndroid Build Coastguard Worker    unsigned i;
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker    if (!(features && feature_enables))
656*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker    vmixer = vlGetDataHTAB(mixer);
659*61046927SAndroid Build Coastguard Worker    if (!vmixer)
660*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
661*61046927SAndroid Build Coastguard Worker 
662*61046927SAndroid Build Coastguard Worker    mtx_lock(&vmixer->device->mutex);
663*61046927SAndroid Build Coastguard Worker    for (i = 0; i < feature_count; ++i) {
664*61046927SAndroid Build Coastguard Worker       switch (features[i]) {
665*61046927SAndroid Build Coastguard Worker       /* they are valid, but we doesn't support them */
666*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
667*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
668*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
669*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
670*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5:
671*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6:
672*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7:
673*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8:
674*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
675*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
676*61046927SAndroid Build Coastguard Worker          break;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
679*61046927SAndroid Build Coastguard Worker          vmixer->deint.enabled = feature_enables[i];
680*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer);
681*61046927SAndroid Build Coastguard Worker          break;
682*61046927SAndroid Build Coastguard Worker 
683*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
684*61046927SAndroid Build Coastguard Worker          vmixer->sharpness.enabled = feature_enables[i];
685*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
686*61046927SAndroid Build Coastguard Worker          break;
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
689*61046927SAndroid Build Coastguard Worker          vmixer->noise_reduction.enabled = feature_enables[i];
690*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer);
691*61046927SAndroid Build Coastguard Worker          break;
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
694*61046927SAndroid Build Coastguard Worker          vmixer->luma_key.enabled = feature_enables[i];
695*61046927SAndroid Build Coastguard Worker          if (!debug_get_bool_option("G3DVL_NO_CSC", false))
696*61046927SAndroid Build Coastguard Worker             if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
697*61046927SAndroid Build Coastguard Worker                         vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) {
698*61046927SAndroid Build Coastguard Worker                mtx_unlock(&vmixer->device->mutex);
699*61046927SAndroid Build Coastguard Worker                return VDP_STATUS_ERROR;
700*61046927SAndroid Build Coastguard Worker             }
701*61046927SAndroid Build Coastguard Worker          break;
702*61046927SAndroid Build Coastguard Worker 
703*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
704*61046927SAndroid Build Coastguard Worker          vmixer->bicubic.enabled = feature_enables[i];
705*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateBicubicFilter(vmixer);
706*61046927SAndroid Build Coastguard Worker          break;
707*61046927SAndroid Build Coastguard Worker 
708*61046927SAndroid Build Coastguard Worker       default:
709*61046927SAndroid Build Coastguard Worker          mtx_unlock(&vmixer->device->mutex);
710*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
711*61046927SAndroid Build Coastguard Worker       }
712*61046927SAndroid Build Coastguard Worker    }
713*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
716*61046927SAndroid Build Coastguard Worker }
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker /**
719*61046927SAndroid Build Coastguard Worker  * Retrieve whether features are enabled.
720*61046927SAndroid Build Coastguard Worker  */
721*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,uint32_t feature_count,VdpVideoMixerFeature const * features,VdpBool * feature_enables)722*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
723*61046927SAndroid Build Coastguard Worker                                  uint32_t feature_count,
724*61046927SAndroid Build Coastguard Worker                                  VdpVideoMixerFeature const *features,
725*61046927SAndroid Build Coastguard Worker                                  VdpBool *feature_enables)
726*61046927SAndroid Build Coastguard Worker {
727*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer;
728*61046927SAndroid Build Coastguard Worker    unsigned i;
729*61046927SAndroid Build Coastguard Worker 
730*61046927SAndroid Build Coastguard Worker    if (!(features && feature_enables))
731*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker    vmixer = vlGetDataHTAB(mixer);
734*61046927SAndroid Build Coastguard Worker    if (!vmixer)
735*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
736*61046927SAndroid Build Coastguard Worker 
737*61046927SAndroid Build Coastguard Worker    for (i = 0; i < feature_count; ++i) {
738*61046927SAndroid Build Coastguard Worker       switch (features[i]) {
739*61046927SAndroid Build Coastguard Worker       /* they are valid, but we doesn't support them */
740*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
741*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
742*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
743*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
744*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
745*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5:
746*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6:
747*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7:
748*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8:
749*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
750*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
751*61046927SAndroid Build Coastguard Worker          break;
752*61046927SAndroid Build Coastguard Worker 
753*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
754*61046927SAndroid Build Coastguard Worker          feature_enables[i] = vmixer->sharpness.enabled;
755*61046927SAndroid Build Coastguard Worker          break;
756*61046927SAndroid Build Coastguard Worker 
757*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
758*61046927SAndroid Build Coastguard Worker          feature_enables[i] = vmixer->noise_reduction.enabled;
759*61046927SAndroid Build Coastguard Worker          break;
760*61046927SAndroid Build Coastguard Worker 
761*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
762*61046927SAndroid Build Coastguard Worker          feature_enables[i] = vmixer->luma_key.enabled;
763*61046927SAndroid Build Coastguard Worker          break;
764*61046927SAndroid Build Coastguard Worker 
765*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
766*61046927SAndroid Build Coastguard Worker          feature_enables[i] = vmixer->bicubic.enabled;
767*61046927SAndroid Build Coastguard Worker          break;
768*61046927SAndroid Build Coastguard Worker 
769*61046927SAndroid Build Coastguard Worker       default:
770*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
771*61046927SAndroid Build Coastguard Worker       }
772*61046927SAndroid Build Coastguard Worker    }
773*61046927SAndroid Build Coastguard Worker 
774*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
775*61046927SAndroid Build Coastguard Worker }
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker /**
778*61046927SAndroid Build Coastguard Worker  * Set attribute values.
779*61046927SAndroid Build Coastguard Worker  */
780*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,uint32_t attribute_count,VdpVideoMixerAttribute const * attributes,void const * const * attribute_values)781*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
782*61046927SAndroid Build Coastguard Worker                                   uint32_t attribute_count,
783*61046927SAndroid Build Coastguard Worker                                   VdpVideoMixerAttribute const *attributes,
784*61046927SAndroid Build Coastguard Worker                                   void const *const *attribute_values)
785*61046927SAndroid Build Coastguard Worker {
786*61046927SAndroid Build Coastguard Worker    const VdpColor *background_color;
787*61046927SAndroid Build Coastguard Worker    union pipe_color_union color;
788*61046927SAndroid Build Coastguard Worker    const float *vdp_csc;
789*61046927SAndroid Build Coastguard Worker    float val;
790*61046927SAndroid Build Coastguard Worker    unsigned i;
791*61046927SAndroid Build Coastguard Worker    VdpStatus ret;
792*61046927SAndroid Build Coastguard Worker 
793*61046927SAndroid Build Coastguard Worker    if (!(attributes && attribute_values))
794*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
795*61046927SAndroid Build Coastguard Worker 
796*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
797*61046927SAndroid Build Coastguard Worker    if (!vmixer)
798*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker    mtx_lock(&vmixer->device->mutex);
801*61046927SAndroid Build Coastguard Worker    for (i = 0; i < attribute_count; ++i) {
802*61046927SAndroid Build Coastguard Worker       switch (attributes[i]) {
803*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
804*61046927SAndroid Build Coastguard Worker          background_color = attribute_values[i];
805*61046927SAndroid Build Coastguard Worker          color.f[0] = background_color->red;
806*61046927SAndroid Build Coastguard Worker          color.f[1] = background_color->green;
807*61046927SAndroid Build Coastguard Worker          color.f[2] = background_color->blue;
808*61046927SAndroid Build Coastguard Worker          color.f[3] = background_color->alpha;
809*61046927SAndroid Build Coastguard Worker          vl_compositor_set_clear_color(&vmixer->cstate, &color);
810*61046927SAndroid Build Coastguard Worker          break;
811*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
812*61046927SAndroid Build Coastguard Worker          vdp_csc = attribute_values[i];
813*61046927SAndroid Build Coastguard Worker          vmixer->custom_csc = !!vdp_csc;
814*61046927SAndroid Build Coastguard Worker          if (!vdp_csc)
815*61046927SAndroid Build Coastguard Worker             vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &vmixer->csc);
816*61046927SAndroid Build Coastguard Worker          else
817*61046927SAndroid Build Coastguard Worker             memcpy(vmixer->csc, vdp_csc, sizeof(vl_csc_matrix));
818*61046927SAndroid Build Coastguard Worker          if (!debug_get_bool_option("G3DVL_NO_CSC", false))
819*61046927SAndroid Build Coastguard Worker             if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
820*61046927SAndroid Build Coastguard Worker                                          vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) {
821*61046927SAndroid Build Coastguard Worker                ret = VDP_STATUS_ERROR;
822*61046927SAndroid Build Coastguard Worker                goto fail;
823*61046927SAndroid Build Coastguard Worker             }
824*61046927SAndroid Build Coastguard Worker          break;
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker          val = *(float*)attribute_values[i];
829*61046927SAndroid Build Coastguard Worker          if (val < 0.0f || val > 1.0f) {
830*61046927SAndroid Build Coastguard Worker             ret = VDP_STATUS_INVALID_VALUE;
831*61046927SAndroid Build Coastguard Worker             goto fail;
832*61046927SAndroid Build Coastguard Worker          }
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker          vmixer->noise_reduction.level = val * 10;
835*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer);
836*61046927SAndroid Build Coastguard Worker          break;
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
839*61046927SAndroid Build Coastguard Worker          val = *(float*)attribute_values[i];
840*61046927SAndroid Build Coastguard Worker          if (val < 0.0f || val > 1.0f) {
841*61046927SAndroid Build Coastguard Worker             ret = VDP_STATUS_INVALID_VALUE;
842*61046927SAndroid Build Coastguard Worker             goto fail;
843*61046927SAndroid Build Coastguard Worker          }
844*61046927SAndroid Build Coastguard Worker          vmixer->luma_key.luma_min = val;
845*61046927SAndroid Build Coastguard Worker          if (!debug_get_bool_option("G3DVL_NO_CSC", false))
846*61046927SAndroid Build Coastguard Worker             if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
847*61046927SAndroid Build Coastguard Worker                         vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) {
848*61046927SAndroid Build Coastguard Worker                ret = VDP_STATUS_ERROR;
849*61046927SAndroid Build Coastguard Worker                goto fail;
850*61046927SAndroid Build Coastguard Worker             }
851*61046927SAndroid Build Coastguard Worker          break;
852*61046927SAndroid Build Coastguard Worker 
853*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
854*61046927SAndroid Build Coastguard Worker          val = *(float*)attribute_values[i];
855*61046927SAndroid Build Coastguard Worker          if (val < 0.0f || val > 1.0f) {
856*61046927SAndroid Build Coastguard Worker             ret = VDP_STATUS_INVALID_VALUE;
857*61046927SAndroid Build Coastguard Worker             goto fail;
858*61046927SAndroid Build Coastguard Worker          }
859*61046927SAndroid Build Coastguard Worker          vmixer->luma_key.luma_max = val;
860*61046927SAndroid Build Coastguard Worker          if (!debug_get_bool_option("G3DVL_NO_CSC", false))
861*61046927SAndroid Build Coastguard Worker             if (!vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
862*61046927SAndroid Build Coastguard Worker                         vmixer->luma_key.luma_min, vmixer->luma_key.luma_max)) {
863*61046927SAndroid Build Coastguard Worker                ret = VDP_STATUS_ERROR;
864*61046927SAndroid Build Coastguard Worker                goto fail;
865*61046927SAndroid Build Coastguard Worker             }
866*61046927SAndroid Build Coastguard Worker          break;
867*61046927SAndroid Build Coastguard Worker 
868*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
869*61046927SAndroid Build Coastguard Worker 
870*61046927SAndroid Build Coastguard Worker          val = *(float*)attribute_values[i];
871*61046927SAndroid Build Coastguard Worker          if (val < -1.0f || val > 1.0f) {
872*61046927SAndroid Build Coastguard Worker             ret = VDP_STATUS_INVALID_VALUE;
873*61046927SAndroid Build Coastguard Worker             goto fail;
874*61046927SAndroid Build Coastguard Worker          }
875*61046927SAndroid Build Coastguard Worker 
876*61046927SAndroid Build Coastguard Worker          vmixer->sharpness.value = val;
877*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
878*61046927SAndroid Build Coastguard Worker          break;
879*61046927SAndroid Build Coastguard Worker 
880*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
881*61046927SAndroid Build Coastguard Worker          if (*(uint8_t*)attribute_values[i] > 1) {
882*61046927SAndroid Build Coastguard Worker             ret = VDP_STATUS_INVALID_VALUE;
883*61046927SAndroid Build Coastguard Worker             goto fail;
884*61046927SAndroid Build Coastguard Worker          }
885*61046927SAndroid Build Coastguard Worker          vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i];
886*61046927SAndroid Build Coastguard Worker          vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer);
887*61046927SAndroid Build Coastguard Worker          break;
888*61046927SAndroid Build Coastguard Worker       default:
889*61046927SAndroid Build Coastguard Worker          ret = VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
890*61046927SAndroid Build Coastguard Worker          goto fail;
891*61046927SAndroid Build Coastguard Worker       }
892*61046927SAndroid Build Coastguard Worker    }
893*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
894*61046927SAndroid Build Coastguard Worker 
895*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
896*61046927SAndroid Build Coastguard Worker fail:
897*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
898*61046927SAndroid Build Coastguard Worker    return ret;
899*61046927SAndroid Build Coastguard Worker }
900*61046927SAndroid Build Coastguard Worker 
901*61046927SAndroid Build Coastguard Worker /**
902*61046927SAndroid Build Coastguard Worker  * Retrieve parameter values given at creation time.
903*61046927SAndroid Build Coastguard Worker  */
904*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer,uint32_t parameter_count,VdpVideoMixerParameter const * parameters,void * const * parameter_values)905*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer,
906*61046927SAndroid Build Coastguard Worker                                   uint32_t parameter_count,
907*61046927SAndroid Build Coastguard Worker                                   VdpVideoMixerParameter const *parameters,
908*61046927SAndroid Build Coastguard Worker                                   void *const *parameter_values)
909*61046927SAndroid Build Coastguard Worker {
910*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
911*61046927SAndroid Build Coastguard Worker    unsigned i;
912*61046927SAndroid Build Coastguard Worker    if (!vmixer)
913*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
914*61046927SAndroid Build Coastguard Worker 
915*61046927SAndroid Build Coastguard Worker    if (!parameter_count)
916*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_OK;
917*61046927SAndroid Build Coastguard Worker    if (!(parameters && parameter_values))
918*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
919*61046927SAndroid Build Coastguard Worker    for (i = 0; i < parameter_count; ++i) {
920*61046927SAndroid Build Coastguard Worker       switch (parameters[i]) {
921*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
922*61046927SAndroid Build Coastguard Worker          *(uint32_t*)parameter_values[i] = vmixer->video_width;
923*61046927SAndroid Build Coastguard Worker          break;
924*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
925*61046927SAndroid Build Coastguard Worker          *(uint32_t*)parameter_values[i] = vmixer->video_height;
926*61046927SAndroid Build Coastguard Worker          break;
927*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
928*61046927SAndroid Build Coastguard Worker          *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format);
929*61046927SAndroid Build Coastguard Worker          break;
930*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
931*61046927SAndroid Build Coastguard Worker          *(uint32_t*)parameter_values[i] = vmixer->max_layers;
932*61046927SAndroid Build Coastguard Worker          break;
933*61046927SAndroid Build Coastguard Worker       default:
934*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
935*61046927SAndroid Build Coastguard Worker       }
936*61046927SAndroid Build Coastguard Worker    }
937*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
938*61046927SAndroid Build Coastguard Worker }
939*61046927SAndroid Build Coastguard Worker 
940*61046927SAndroid Build Coastguard Worker /**
941*61046927SAndroid Build Coastguard Worker  * Retrieve current attribute values.
942*61046927SAndroid Build Coastguard Worker  */
943*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer,uint32_t attribute_count,VdpVideoMixerAttribute const * attributes,void * const * attribute_values)944*61046927SAndroid Build Coastguard Worker vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer,
945*61046927SAndroid Build Coastguard Worker                                   uint32_t attribute_count,
946*61046927SAndroid Build Coastguard Worker                                   VdpVideoMixerAttribute const *attributes,
947*61046927SAndroid Build Coastguard Worker                                   void *const *attribute_values)
948*61046927SAndroid Build Coastguard Worker {
949*61046927SAndroid Build Coastguard Worker    unsigned i;
950*61046927SAndroid Build Coastguard Worker    VdpCSCMatrix **vdp_csc;
951*61046927SAndroid Build Coastguard Worker 
952*61046927SAndroid Build Coastguard Worker    if (!(attributes && attribute_values))
953*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
954*61046927SAndroid Build Coastguard Worker 
955*61046927SAndroid Build Coastguard Worker    vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
956*61046927SAndroid Build Coastguard Worker    if (!vmixer)
957*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_HANDLE;
958*61046927SAndroid Build Coastguard Worker 
959*61046927SAndroid Build Coastguard Worker    mtx_lock(&vmixer->device->mutex);
960*61046927SAndroid Build Coastguard Worker    for (i = 0; i < attribute_count; ++i) {
961*61046927SAndroid Build Coastguard Worker       switch (attributes[i]) {
962*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
963*61046927SAndroid Build Coastguard Worker          vl_compositor_get_clear_color(&vmixer->cstate, attribute_values[i]);
964*61046927SAndroid Build Coastguard Worker          break;
965*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
966*61046927SAndroid Build Coastguard Worker          vdp_csc = attribute_values[i];
967*61046927SAndroid Build Coastguard Worker          if (!vmixer->custom_csc) {
968*61046927SAndroid Build Coastguard Worker              *vdp_csc = NULL;
969*61046927SAndroid Build Coastguard Worker             break;
970*61046927SAndroid Build Coastguard Worker          }
971*61046927SAndroid Build Coastguard Worker          memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12);
972*61046927SAndroid Build Coastguard Worker          break;
973*61046927SAndroid Build Coastguard Worker 
974*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
975*61046927SAndroid Build Coastguard Worker          *(float*)attribute_values[i] = (float)vmixer->noise_reduction.level / 10.0f;
976*61046927SAndroid Build Coastguard Worker          break;
977*61046927SAndroid Build Coastguard Worker 
978*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
979*61046927SAndroid Build Coastguard Worker          *(float*)attribute_values[i] = vmixer->luma_key.luma_min;
980*61046927SAndroid Build Coastguard Worker          break;
981*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
982*61046927SAndroid Build Coastguard Worker          *(float*)attribute_values[i] = vmixer->luma_key.luma_max;
983*61046927SAndroid Build Coastguard Worker          break;
984*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
985*61046927SAndroid Build Coastguard Worker          *(float*)attribute_values[i] = vmixer->sharpness.value;
986*61046927SAndroid Build Coastguard Worker          break;
987*61046927SAndroid Build Coastguard Worker       case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
988*61046927SAndroid Build Coastguard Worker          *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint;
989*61046927SAndroid Build Coastguard Worker          break;
990*61046927SAndroid Build Coastguard Worker       default:
991*61046927SAndroid Build Coastguard Worker          mtx_unlock(&vmixer->device->mutex);
992*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
993*61046927SAndroid Build Coastguard Worker       }
994*61046927SAndroid Build Coastguard Worker    }
995*61046927SAndroid Build Coastguard Worker    mtx_unlock(&vmixer->device->mutex);
996*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
997*61046927SAndroid Build Coastguard Worker }
998*61046927SAndroid Build Coastguard Worker 
999*61046927SAndroid Build Coastguard Worker /**
1000*61046927SAndroid Build Coastguard Worker  * Generate a color space conversion matrix.
1001*61046927SAndroid Build Coastguard Worker  */
1002*61046927SAndroid Build Coastguard Worker VdpStatus
vlVdpGenerateCSCMatrix(VdpProcamp * procamp,VdpColorStandard standard,VdpCSCMatrix * csc_matrix)1003*61046927SAndroid Build Coastguard Worker vlVdpGenerateCSCMatrix(VdpProcamp *procamp,
1004*61046927SAndroid Build Coastguard Worker                        VdpColorStandard standard,
1005*61046927SAndroid Build Coastguard Worker                        VdpCSCMatrix *csc_matrix)
1006*61046927SAndroid Build Coastguard Worker {
1007*61046927SAndroid Build Coastguard Worker    enum VL_CSC_COLOR_STANDARD vl_std;
1008*61046927SAndroid Build Coastguard Worker    struct vl_procamp camp;
1009*61046927SAndroid Build Coastguard Worker 
1010*61046927SAndroid Build Coastguard Worker    if (!csc_matrix)
1011*61046927SAndroid Build Coastguard Worker       return VDP_STATUS_INVALID_POINTER;
1012*61046927SAndroid Build Coastguard Worker 
1013*61046927SAndroid Build Coastguard Worker    switch (standard) {
1014*61046927SAndroid Build Coastguard Worker       case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break;
1015*61046927SAndroid Build Coastguard Worker       case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break;
1016*61046927SAndroid Build Coastguard Worker       case VDP_COLOR_STANDARD_SMPTE_240M:  vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break;
1017*61046927SAndroid Build Coastguard Worker       default: return VDP_STATUS_INVALID_COLOR_STANDARD;
1018*61046927SAndroid Build Coastguard Worker    }
1019*61046927SAndroid Build Coastguard Worker 
1020*61046927SAndroid Build Coastguard Worker    if (procamp) {
1021*61046927SAndroid Build Coastguard Worker       if (procamp->struct_version > VDP_PROCAMP_VERSION)
1022*61046927SAndroid Build Coastguard Worker          return VDP_STATUS_INVALID_STRUCT_VERSION;
1023*61046927SAndroid Build Coastguard Worker       camp.brightness = procamp->brightness;
1024*61046927SAndroid Build Coastguard Worker       camp.contrast = procamp->contrast;
1025*61046927SAndroid Build Coastguard Worker       camp.saturation = procamp->saturation;
1026*61046927SAndroid Build Coastguard Worker       camp.hue = procamp->hue;
1027*61046927SAndroid Build Coastguard Worker    }
1028*61046927SAndroid Build Coastguard Worker 
1029*61046927SAndroid Build Coastguard Worker    vl_csc_get_matrix(vl_std, procamp ? &camp : NULL, true, csc_matrix);
1030*61046927SAndroid Build Coastguard Worker    return VDP_STATUS_OK;
1031*61046927SAndroid Build Coastguard Worker }
1032