g3dvl: Use sobel filter for chroma interpolation
[mesa/nouveau-pmpeg.git] / src / gallium / state_trackers / vdpau / mixer.c
blob9da489282b7c2efc62c8d9c2917771b5c5581925
1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
4 * All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include <vdpau/vdpau.h>
30 #include "util/u_memory.h"
31 #include "util/u_debug.h"
33 #include "vl/vl_csc.h"
35 #include "vdpau_private.h"
37 /**
38 * Create a VdpVideoMixer.
40 VdpStatus
41 vlVdpVideoMixerCreate(VdpDevice device,
42 uint32_t feature_count,
43 VdpVideoMixerFeature const *features,
44 uint32_t parameter_count,
45 VdpVideoMixerParameter const *parameters,
46 void const *const *parameter_values,
47 VdpVideoMixer *mixer)
49 vlVdpVideoMixer *vmixer = NULL;
50 VdpStatus ret;
51 struct pipe_screen *screen;
52 unsigned max_width, max_height, i;
53 enum pipe_video_profile prof = PIPE_VIDEO_PROFILE_UNKNOWN;
55 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating VideoMixer\n");
57 vlVdpDevice *dev = vlGetDataHTAB(device);
58 if (!dev)
59 return VDP_STATUS_INVALID_HANDLE;
60 screen = dev->vscreen->pscreen;
62 vmixer = CALLOC(1, sizeof(vlVdpVideoMixer));
63 if (!vmixer)
64 return VDP_STATUS_RESOURCES;
66 vmixer->device = dev;
69 * TODO: Handle features
72 *mixer = vlAddDataHTAB(vmixer);
73 if (*mixer == 0) {
74 ret = VDP_STATUS_ERROR;
75 goto no_handle;
77 vmixer->chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
78 ret = VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
79 for (i = 0; i < parameter_count; ++i) {
80 switch (parameters[i]) {
81 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
82 vmixer->video_width = *(uint32_t*)parameter_values[i];
83 break;
84 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
85 vmixer->video_height = *(uint32_t*)parameter_values[i];
86 break;
87 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
88 vmixer->chroma_format = ChromaToPipe(*(VdpChromaType*)parameter_values[i]);
89 break;
90 case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
91 vmixer->max_layers = *(uint32_t*)parameter_values[i];
92 break;
93 default: goto no_params;
96 ret = VDP_STATUS_INVALID_VALUE;
97 if (vmixer->max_layers > 4) {
98 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Max layers > 4 not supported\n", vmixer->max_layers);
99 goto no_params;
101 max_width = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_WIDTH);
102 max_height = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_HEIGHT);
103 if (vmixer->video_width < 48 ||
104 vmixer->video_width > max_width) {
105 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for width\n", vmixer->video_width, max_width);
106 goto no_params;
108 if (vmixer->video_height < 48 ||
109 vmixer->video_height > max_height) {
110 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] 48 < %u < %u not valid for height\n", vmixer->video_height, max_height);
111 goto no_params;
113 vmixer->luma_key_min = 0.f;
114 vmixer->luma_key_max = 1.f;
115 vmixer->noise_reduction_level = 0.f;
116 vmixer->sharpness = 0.f;
118 ret = VDP_STATUS_RESOURCES;
119 if (!vl_compositor_init_video(&vmixer->compositor, dev->context->pipe, vmixer->chroma_format, vmixer->video_width, vmixer->video_height))
120 goto no_resources;
122 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, vmixer->csc);
123 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
124 vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc);
126 return VDP_STATUS_OK;
128 no_resources:
129 no_params:
130 vlRemoveDataHTAB(*mixer);
131 no_handle:
132 FREE(vmixer);
133 return ret;
137 * Destroy a VdpVideoMixer.
139 VdpStatus
140 vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
142 vlVdpVideoMixer *vmixer;
144 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying VideoMixer\n");
146 vmixer = vlGetDataHTAB(mixer);
147 if (!vmixer)
148 return VDP_STATUS_INVALID_HANDLE;
149 vlRemoveDataHTAB(mixer);
151 vl_compositor_cleanup(&vmixer->compositor);
153 FREE(vmixer);
155 return VDP_STATUS_OK;
159 * Enable or disable features.
161 VdpStatus
162 vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer,
163 uint32_t feature_count,
164 VdpVideoMixerFeature const *features,
165 VdpBool const *feature_enables)
167 VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Setting VideoMixer features\n");
169 if (!(features && feature_enables))
170 return VDP_STATUS_INVALID_POINTER;
172 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
173 if (!vmixer)
174 return VDP_STATUS_INVALID_HANDLE;
177 * TODO: Set features
180 return VDP_STATUS_OK;
183 static VdpStatus
184 vl_check_video_surface(vlVdpVideoMixer *mixer, vlVdpSurface *surf)
186 if (surf->device != mixer->device)
187 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
188 if (mixer->video_width != surf->video_buffer->width ||
189 mixer->video_height != surf->video_buffer->height ||
190 mixer->chroma_format != surf->video_buffer->chroma_format)
191 return VDP_STATUS_INVALID_SIZE;
192 return VDP_STATUS_OK;
196 * Perform a video post-processing and compositing operation.
198 VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
199 VdpOutputSurface background_surface,
200 VdpRect const *background_source_rect,
201 VdpVideoMixerPictureStructure current_picture_structure,
202 uint32_t video_surface_past_count,
203 VdpVideoSurface const *video_surface_past,
204 VdpVideoSurface video_surface_current,
205 uint32_t video_surface_future_count,
206 VdpVideoSurface const *video_surface_future,
207 VdpRect const *video_source_rect,
208 VdpOutputSurface destination_surface,
209 VdpRect const *destination_rect,
210 VdpRect const *destination_video_rect,
211 uint32_t layer_count,
212 VdpLayer const *layers)
214 struct pipe_video_buffer *future[video_surface_future_count];
215 struct pipe_video_buffer *past[video_surface_past_count];
216 struct pipe_video_rect src_rect, dst_rect;
217 VdpStatus ret;
218 enum pipe_video_picture_structure ps;
219 switch (current_picture_structure) {
220 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD:
221 ps = PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_TOP;
222 break;
223 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD:
224 ps = PIPE_VIDEO_PICTURE_STRUCTURE_FIELD_BOTTOM;
225 break;
226 case VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME:
227 ps = PIPE_VIDEO_PICTURE_STRUCTURE_FRAME;
228 break;
229 default:
230 return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE;
233 vlVdpVideoMixer *vmixer;
234 vlVdpSurface *surf, *tmp;
235 vlVdpOutputSurface *dst, *bg;
236 unsigned i, layer = 0;
238 vmixer = vlGetDataHTAB(mixer);
239 if (!vmixer)
240 return VDP_STATUS_INVALID_HANDLE;
242 surf = vlGetDataHTAB(video_surface_current);
243 if (!surf)
244 return VDP_STATUS_INVALID_HANDLE;
245 ret = vl_check_video_surface(vmixer, surf);
246 if (ret)
247 return ret;
248 if (layer_count > vmixer->max_layers)
249 return VDP_STATUS_INVALID_VALUE;
251 dst = vlGetDataHTAB(destination_surface);
252 if (!dst)
253 return VDP_STATUS_INVALID_HANDLE;
254 for (i = 0; i < video_surface_past_count; ++i) {
255 if (video_surface_past[i] != VDP_INVALID_HANDLE) {
256 tmp = vlGetDataHTAB(video_surface_past[i]);
257 if (!tmp)
258 return VDP_STATUS_INVALID_HANDLE;
259 ret = vl_check_video_surface(vmixer, tmp);
260 if (ret)
261 return ret;
262 past[i] = tmp->video_buffer;
263 } else
264 past[i] = NULL;
266 for (i = 0; i < video_surface_future_count; ++i) {
267 if (video_surface_future[i] != VDP_INVALID_HANDLE) {
268 tmp = vlGetDataHTAB(video_surface_future[i]);
269 if (!tmp)
270 return VDP_STATUS_INVALID_HANDLE;
271 ret = vl_check_video_surface(vmixer, tmp);
272 if (ret)
273 return ret;
274 future[i] = tmp->video_buffer;
275 } else
276 future[i] = NULL;
279 vl_compositor_clear_layers(&vmixer->compositor);
280 vl_compositor_reset_dirty_area(&vmixer->compositor);
281 if (background_surface != VDP_INVALID_HANDLE) {
282 bg = vlGetDataHTAB(background_surface);
283 if (!bg)
284 return VDP_STATUS_INVALID_HANDLE;
285 vl_compositor_set_rgba_layer(&vmixer->compositor, layer++, bg->sampler_view,
286 RectToPipe(background_source_rect, &src_rect), NULL);
288 vl_compositor_set_buffer_layer(&vmixer->compositor, layer, ps,
289 surf->video_buffer,
290 RectToPipe(video_source_rect, &src_rect),
291 RectToPipe(destination_video_rect, &dst_rect),
292 video_surface_past_count, past,
293 video_surface_future_count, future);
294 vl_compositor_render(&vmixer->compositor, dst->surface, NULL,
295 RectToPipe(destination_rect, &dst_rect), !layer);
297 assert(!layer_count);
298 return VDP_STATUS_OK;
302 * Set attribute values.
304 VdpStatus
305 vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
306 uint32_t attribute_count,
307 VdpVideoMixerAttribute const *attributes,
308 void const *const *attribute_values)
310 const VdpColor *background_color;
311 union pipe_color_union color;
312 const float *vdp_csc;
313 float val;
314 unsigned i;
316 if (!(attributes && attribute_values))
317 return VDP_STATUS_INVALID_POINTER;
319 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
320 if (!vmixer)
321 return VDP_STATUS_INVALID_HANDLE;
323 for (i = 0; i < attribute_count; ++i) {
324 switch (attributes[i]) {
325 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
326 background_color = attribute_values[i];
327 color.f[0] = background_color->red;
328 color.f[1] = background_color->green;
329 color.f[2] = background_color->blue;
330 color.f[3] = background_color->alpha;
331 vl_compositor_set_clear_color(&vmixer->compositor, &color);
332 break;
333 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
334 vdp_csc = attribute_values[i];
335 vmixer->custom_csc = !!vdp_csc;
336 if (!vdp_csc)
337 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, vmixer->csc);
338 else
339 memcpy(vmixer->csc, vdp_csc, sizeof(float)*12);
340 if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
341 vl_compositor_set_csc_matrix(&vmixer->compositor, vmixer->csc);
342 break;
343 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
344 val = *(float*)attribute_values[i];
345 if (val < 0.f || val > 1.f)
346 return VDP_STATUS_INVALID_VALUE;
347 vmixer->noise_reduction_level = val;
348 break;
349 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
350 val = *(float*)attribute_values[i];
351 if (val < 0.f || val > 1.f)
352 return VDP_STATUS_INVALID_VALUE;
353 vmixer->luma_key_min = val;
354 break;
355 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
356 val = *(float*)attribute_values[i];
357 if (val < 0.f || val > 1.f)
358 return VDP_STATUS_INVALID_VALUE;
359 vmixer->luma_key_max = val;
360 break;
361 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
362 val = *(float*)attribute_values[i];
363 if (val < -1.f || val > 1.f)
364 return VDP_STATUS_INVALID_VALUE;
365 vmixer->sharpness = val;
366 break;
367 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
368 if (*(uint8_t*)attribute_values[i] > 1)
369 return VDP_STATUS_INVALID_VALUE;
370 vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i];
371 break;
372 default:
373 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
377 return VDP_STATUS_OK;
381 * Retrieve whether features were requested at creation time.
383 VdpStatus
384 vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer,
385 uint32_t feature_count,
386 VdpVideoMixerFeature const *features,
387 VdpBool *feature_supports)
389 return VDP_STATUS_NO_IMPLEMENTATION;
393 * Retrieve whether features are enabled.
395 VdpStatus
396 vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer,
397 uint32_t feature_count,
398 VdpVideoMixerFeature const *features,
399 VdpBool *feature_enables)
401 return VDP_STATUS_NO_IMPLEMENTATION;
405 * Retrieve parameter values given at creation time.
407 VdpStatus
408 vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer,
409 uint32_t parameter_count,
410 VdpVideoMixerParameter const *parameters,
411 void *const *parameter_values)
413 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
414 unsigned i;
415 if (!vmixer)
416 return VDP_STATUS_INVALID_HANDLE;
418 if (!parameter_count)
419 return VDP_STATUS_OK;
420 if (!(parameters && parameter_values))
421 return VDP_STATUS_INVALID_POINTER;
422 for (i = 0; i < parameter_count; ++i) {
423 switch (parameters[i]) {
424 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
425 *(uint32_t*)parameter_values[i] = vmixer->video_width;
426 break;
427 case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
428 *(uint32_t*)parameter_values[i] = vmixer->video_height;
429 break;
430 case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
431 *(VdpChromaType*)parameter_values[i] = PipeToChroma(vmixer->chroma_format);
432 break;
433 case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
434 *(uint32_t*)parameter_values[i] = vmixer->max_layers;
435 break;
436 default:
437 return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
440 return VDP_STATUS_OK;
444 * Retrieve current attribute values.
446 VdpStatus
447 vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer,
448 uint32_t attribute_count,
449 VdpVideoMixerAttribute const *attributes,
450 void *const *attribute_values)
452 unsigned i;
453 VdpCSCMatrix **vdp_csc;
455 if (!(attributes && attribute_values))
456 return VDP_STATUS_INVALID_POINTER;
458 vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
459 if (!vmixer)
460 return VDP_STATUS_INVALID_HANDLE;
462 for (i = 0; i < attribute_count; ++i) {
463 switch (attributes[i]) {
464 case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
465 vl_compositor_get_clear_color(&vmixer->compositor, attribute_values[i]);
466 break;
467 case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
468 vdp_csc = attribute_values[i];
469 if (!vmixer->custom_csc) {
470 *vdp_csc = NULL;
471 break;
473 memcpy(*vdp_csc, vmixer->csc, sizeof(float)*12);
474 break;
475 case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
476 *(float*)attribute_values[i] = vmixer->noise_reduction_level;
477 break;
478 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
479 *(float*)attribute_values[i] = vmixer->luma_key_min;
480 break;
481 case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
482 *(float*)attribute_values[i] = vmixer->luma_key_max;
483 break;
484 case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
485 *(float*)attribute_values[i] = vmixer->sharpness;
486 break;
487 case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
488 *(uint8_t*)attribute_values[i] = vmixer->skip_chroma_deint;
489 break;
490 default:
491 return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
494 return VDP_STATUS_OK;
498 * Generate a color space conversion matrix.
500 VdpStatus
501 vlVdpGenerateCSCMatrix(VdpProcamp *procamp,
502 VdpColorStandard standard,
503 VdpCSCMatrix *csc_matrix)
505 float matrix[16];
506 enum VL_CSC_COLOR_STANDARD vl_std;
507 struct vl_procamp camp;
509 if (!(csc_matrix && procamp))
510 return VDP_STATUS_INVALID_POINTER;
512 if (procamp->struct_version > VDP_PROCAMP_VERSION)
513 return VDP_STATUS_INVALID_STRUCT_VERSION;
515 switch (standard) {
516 case VDP_COLOR_STANDARD_ITUR_BT_601: vl_std = VL_CSC_COLOR_STANDARD_BT_601; break;
517 case VDP_COLOR_STANDARD_ITUR_BT_709: vl_std = VL_CSC_COLOR_STANDARD_BT_709; break;
518 case VDP_COLOR_STANDARD_SMPTE_240M: vl_std = VL_CSC_COLOR_STANDARD_SMPTE_240M; break;
519 default: return VDP_STATUS_INVALID_COLOR_STANDARD;
521 camp.brightness = procamp->brightness;
522 camp.contrast = procamp->contrast;
523 camp.saturation = procamp->saturation;
524 camp.hue = procamp->hue;
525 vl_csc_get_matrix(vl_std, &camp, 1, matrix);
526 memcpy(csc_matrix, matrix, sizeof(float)*12);
527 return VDP_STATUS_OK;