+ vlVdpVideoMixer *vmixer;
+ unsigned i;
+
+ if (!(features && feature_enables))
+ return VDP_STATUS_INVALID_POINTER;
+
+ vmixer = vlGetDataHTAB(mixer);
+ if (!vmixer)
+ return VDP_STATUS_INVALID_HANDLE;
+
+ for (i = 0; i < feature_count; ++i) {
+ switch (features[i]) {
+ /* they are valid, but we doesn't support them */
+ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
+ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L5:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L6:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L7:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L8:
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L9:
+ case VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE:
+ break;
+
+ case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
+ feature_enables[i] = vmixer->sharpness.enabled;
+ break;
+
+ case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
+ feature_enables[i] = vmixer->noise_reduction.enabled;
+ break;
+
+ case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
+ feature_enables[i] = vmixer->luma_key.enabled;
+ break;
+
+ case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
+ feature_enables[i] = vmixer->bicubic.enabled;
+ break;
+
+ default:
+ return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE;
+ }
+ }
+
+ return VDP_STATUS_OK;
+}
+
+/**
+ * Set attribute values.
+ */
+VdpStatus
+vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer,
+ uint32_t attribute_count,
+ VdpVideoMixerAttribute const *attributes,
+ void const *const *attribute_values)
+{
+ const VdpColor *background_color;
+ union pipe_color_union color;
+ const float *vdp_csc;
+ float val;
+ unsigned i;
+ VdpStatus ret;
+
+ if (!(attributes && attribute_values))
+ return VDP_STATUS_INVALID_POINTER;
+
+ vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer);
+ if (!vmixer)
+ return VDP_STATUS_INVALID_HANDLE;
+
+ pipe_mutex_lock(vmixer->device->mutex);
+ for (i = 0; i < attribute_count; ++i) {
+ switch (attributes[i]) {
+ case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
+ background_color = attribute_values[i];
+ color.f[0] = background_color->red;
+ color.f[1] = background_color->green;
+ color.f[2] = background_color->blue;
+ color.f[3] = background_color->alpha;
+ vl_compositor_set_clear_color(&vmixer->cstate, &color);
+ break;
+ case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
+ vdp_csc = attribute_values[i];
+ vmixer->custom_csc = !!vdp_csc;
+ if (!vdp_csc)
+ vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &vmixer->csc);
+ else
+ memcpy(vmixer->csc, vdp_csc, sizeof(vl_csc_matrix));
+ if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
+ vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
+ vmixer->luma_key.luma_min, vmixer->luma_key.luma_max);
+ break;
+
+ case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
+
+ val = *(float*)attribute_values[i];
+ if (val < 0.0f || val > 1.0f) {
+ ret = VDP_STATUS_INVALID_VALUE;
+ goto fail;
+ }
+
+ vmixer->noise_reduction.level = val * 10;
+ vlVdpVideoMixerUpdateNoiseReductionFilter(vmixer);
+ break;
+
+ case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
+ val = *(float*)attribute_values[i];
+ if (val < 0.0f || val > 1.0f) {
+ ret = VDP_STATUS_INVALID_VALUE;
+ goto fail;
+ }
+ vmixer->luma_key.luma_min = val;
+ if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
+ vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
+ vmixer->luma_key.luma_min, vmixer->luma_key.luma_max);
+ break;
+
+ case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
+ val = *(float*)attribute_values[i];
+ if (val < 0.0f || val > 1.0f) {
+ ret = VDP_STATUS_INVALID_VALUE;
+ goto fail;
+ }
+ vmixer->luma_key.luma_max = val;
+ if (!debug_get_bool_option("G3DVL_NO_CSC", FALSE))
+ vl_compositor_set_csc_matrix(&vmixer->cstate, (const vl_csc_matrix *)&vmixer->csc,
+ vmixer->luma_key.luma_min, vmixer->luma_key.luma_max);
+ break;
+
+ case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
+
+ val = *(float*)attribute_values[i];
+ if (val < -1.0f || val > 1.0f) {
+ ret = VDP_STATUS_INVALID_VALUE;
+ goto fail;
+ }
+
+ vmixer->sharpness.value = val;
+ vlVdpVideoMixerUpdateSharpnessFilter(vmixer);
+ break;
+
+ case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
+ if (*(uint8_t*)attribute_values[i] > 1) {
+ ret = VDP_STATUS_INVALID_VALUE;
+ goto fail;
+ }
+ vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i];
+ vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer);
+ break;
+ default:
+ ret = VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
+ goto fail;
+ }
+ }
+ pipe_mutex_unlock(vmixer->device->mutex);
+
+ return VDP_STATUS_OK;
+fail:
+ pipe_mutex_unlock(vmixer->device->mutex);
+ return ret;