2 // Copyright (c) 2017 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include "varenderer.h"
18 #include "platformdefines.h"
21 #include <drm_fourcc.h>
24 #include "nativesurface.h"
25 #include "overlaybuffer.h"
26 #include "renderstate.h"
29 #include <va/va_android.h>
32 #define ANDROID_DISPLAY_HANDLE 0x18C34078
33 #define UNUSED(x) (void*)(&x)
35 namespace hwcomposer {
37 VARenderer::~VARenderer() {
41 vaTerminate(va_display_);
45 bool VARenderer::Init(int gpu_fd) {
47 unsigned int native_display = ANDROID_DISPLAY_HANDLE;
48 va_display_ = vaGetDisplay(&native_display);
51 va_display_ = vaGetDisplayDRM(gpu_fd);
54 ETRACE("vaGetDisplay failed\n");
57 VAStatus ret = VA_STATUS_SUCCESS;
59 ret = vaInitialize(va_display_, &major, &minor);
60 return ret == VA_STATUS_SUCCESS ? true : false;
63 bool VARenderer::QueryVAProcFilterCaps(VAContextID context,
64 VAProcFilterType type, void* caps,
67 vaQueryVideoProcFilterCaps(va_display_, context, type, caps, num);
68 if (ret != VA_STATUS_SUCCESS)
69 ETRACE("Query Filter Caps failed\n");
70 return ret == VA_STATUS_SUCCESS ? true : false;
73 bool VARenderer::MapVAProcFilterColorModetoHwc(HWCColorControl& vppmode,
74 VAProcColorBalanceType vamode) {
76 case VAProcColorBalanceHue:
77 vppmode = HWCColorControl::kColorHue;
79 case VAProcColorBalanceSaturation:
80 vppmode = HWCColorControl::kColorSaturation;
82 case VAProcColorBalanceBrightness:
83 vppmode = HWCColorControl::kColorBrightness;
85 case VAProcColorBalanceContrast:
86 vppmode = HWCColorControl::kColorContrast;
94 bool VARenderer::SetVAProcFilterColorDefaultValue(
95 VAProcFilterCapColorBalance* caps) {
97 for (int i = 0; i < VAProcColorBalanceCount; i++) {
98 if (MapVAProcFilterColorModetoHwc(mode, caps[i].type)) {
99 colorbalance_caps_[mode].caps_ = caps[i];
100 colorbalance_caps_[mode].value_ = caps[i].range.default_value;
103 sharp_caps_.value_ = sharp_caps_.caps_.range.default_value;
108 bool VARenderer::SetVAProcFilterDeinterlaceDefaultMode() {
109 if (deinterlace_caps_.mode_ != VAProcDeinterlacingNone) {
110 deinterlace_caps_.mode_ = VAProcDeinterlacingNone;
116 bool VARenderer::SetVAProcFilterColorValue(HWCColorControl mode,
117 const HWCColorProp& prop) {
118 if (mode == HWCColorControl::kColorHue ||
119 mode == HWCColorControl::kColorSaturation ||
120 mode == HWCColorControl::kColorBrightness ||
121 mode == HWCColorControl::kColorContrast) {
122 if (prop.use_default_) {
123 if (!colorbalance_caps_[mode].use_default_) {
124 colorbalance_caps_[mode].use_default_ = true;
127 } else if (prop.value_ != colorbalance_caps_[mode].value_) {
128 if (prop.value_ > colorbalance_caps_[mode].caps_.range.max_value ||
129 prop.value_ < colorbalance_caps_[mode].caps_.range.min_value) {
130 ETRACE("VA Filter value out of range\n");
133 colorbalance_caps_[mode].value_ = prop.value_;
134 colorbalance_caps_[mode].use_default_ = false;
138 } else if (mode == HWCColorControl::kColorSharpness) {
139 if (prop.use_default_) {
140 if (!sharp_caps_.use_default_) {
141 sharp_caps_.use_default_ = true;
144 } else if (prop.value_ != sharp_caps_.value_) {
145 if (prop.value_ > sharp_caps_.caps_.range.max_value ||
146 prop.value_ < sharp_caps_.caps_.range.min_value) {
147 ETRACE("VA Filter sharp value out of range\n");
150 sharp_caps_.value_ = prop.value_;
151 sharp_caps_.use_default_ = false;
156 ETRACE("VA Filter undefined color mode\n");
161 bool VARenderer::GetVAProcDeinterlaceFlagFromVideo(HWCDeinterlaceFlag flag) {
162 if (flag != HWCDeinterlaceFlag::kDeinterlaceFlagAuto) {
165 // TODO:Need video buffer meta data to judge if the frame really need
170 bool VARenderer::SetVAProcFilterDeinterlaceMode(
171 const HWCDeinterlaceProp& prop) {
172 if (prop.flag_ == HWCDeinterlaceFlag::kDeinterlaceFlagNone) {
173 SetVAProcFilterDeinterlaceDefaultMode();
175 } else if (prop.flag_ == HWCDeinterlaceFlag::kDeinterlaceFlagForce ||
176 GetVAProcDeinterlaceFlagFromVideo(prop.flag_)) {
177 switch (prop.mode_) {
178 case HWCDeinterlaceControl::kDeinterlaceNone:
179 deinterlace_caps_.mode_ = VAProcDeinterlacingNone;
181 case HWCDeinterlaceControl::kDeinterlaceBob:
182 deinterlace_caps_.mode_ = VAProcDeinterlacingBob;
184 case HWCDeinterlaceControl::kDeinterlaceWeave:
185 deinterlace_caps_.mode_ = VAProcDeinterlacingWeave;
187 case HWCDeinterlaceControl::kDeinterlaceMotionAdaptive:
188 deinterlace_caps_.mode_ = VAProcDeinterlacingMotionAdaptive;
190 case HWCDeinterlaceControl::kDeinterlaceMotionCompensated:
191 deinterlace_caps_.mode_ = VAProcDeinterlacingMotionCompensated;
194 ETRACE("Hwc unsupport deinterlace mode\n");
197 for (int i = 0; i < VAProcDeinterlacingCount; i++) {
198 if (deinterlace_caps_.caps_[i].type == deinterlace_caps_.mode_) {
203 ETRACE("VA Filter unsupport deinterlace mode\n");
209 bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) {
211 OverlayBuffer* buffer_out = surface->GetLayer()->GetBuffer();
212 int rt_format = DrmFormatToRTFormat(buffer_out->GetFormat());
213 if (va_context_ == VA_INVALID_ID || render_target_format_ != rt_format) {
214 render_target_format_ = rt_format;
215 if (!CreateContext()) {
216 ETRACE("Create VA context failed\n");
221 // Get Input Surface.
222 OverlayBuffer* buffer_in = state.layer_->GetBuffer();
223 const MediaResourceHandle& resource = buffer_in->GetMediaResource(
224 va_display_, state.layer_->GetSourceCropWidth(),
225 state.layer_->GetSourceCropHeight());
226 VASurfaceID surface_in = resource.surface_;
227 if (surface_in == VA_INVALID_ID) {
228 ETRACE("Failed to create Va Input Surface. \n");
232 // Get Output Surface.
233 const OverlayLayer* layer_out = surface->GetLayer();
234 const MediaResourceHandle& out_resource =
235 layer_out->GetBuffer()->GetMediaResource(
236 va_display_, layer_out->GetSourceCropWidth(),
237 layer_out->GetSourceCropHeight());
238 VASurfaceID surface_out = out_resource.surface_;
239 if (surface_out == VA_INVALID_ID) {
240 ETRACE("Failed to create Va Output Surface. \n");
244 VARectangle surface_region;
245 const OverlayLayer* layer_in = state.layer_;
246 const HwcRect<float>& source_crop = layer_in->GetSourceCrop();
247 surface_region.x = static_cast<int>(source_crop.left);
248 surface_region.y = static_cast<int>(source_crop.top);
249 surface_region.width = layer_in->GetSourceCropWidth();
250 surface_region.height = layer_in->GetSourceCropHeight();
252 VARectangle output_region;
253 const HwcRect<float>& source_crop_out = layer_out->GetSourceCrop();
254 output_region.x = static_cast<int>(source_crop_out.left);
255 output_region.y = static_cast<int>(source_crop_out.top);
256 output_region.width = layer_out->GetSourceCropWidth();
257 output_region.height = layer_out->GetSourceCropHeight();
259 param_.surface = surface_in;
260 param_.surface_region = &surface_region;
261 param_.output_region = &output_region;
263 DUMPTRACE("surface_region: (%d, %d, %d, %d)\n", surface_region.x,
264 surface_region.y, surface_region.width, surface_region.height);
265 DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n", output_region.x,
266 output_region.y, output_region.width, output_region.height);
268 for (auto itr = state.colors_.begin(); itr != state.colors_.end(); itr++) {
269 SetVAProcFilterColorValue(itr->first, itr->second);
271 SetVAProcFilterDeinterlaceMode(state.deinterlace_);
274 ETRACE("Failed to update capabailities. \n");
278 ScopedVABufferID pipeline_buffer(va_display_);
279 if (!pipeline_buffer.CreateBuffer(
280 va_context_, VAProcPipelineParameterBufferType,
281 sizeof(VAProcPipelineParameterBuffer), 1, ¶m_)) {
285 VAStatus ret = VA_STATUS_SUCCESS;
286 ret = vaBeginPicture(va_display_, va_context_, surface_out);
288 vaRenderPicture(va_display_, va_context_, &pipeline_buffer.buffer(), 1);
289 ret |= vaEndPicture(va_display_, va_context_);
291 return ret == VA_STATUS_SUCCESS ? true : false;
294 bool VARenderer::DestroyMediaResources(
295 std::vector<struct media_import>& resources) {
296 size_t purged_size = resources.size();
297 for (size_t i = 0; i < purged_size; i++) {
298 MediaResourceHandle& handle = resources.at(i);
299 if (handle.surface_ != VA_INVALID_ID) {
300 vaDestroySurfaces(va_display_, &handle.surface_, 1);
307 bool VARenderer::CreateContext() {
310 VAConfigAttrib config_attrib;
311 config_attrib.type = VAConfigAttribRTFormat;
312 config_attrib.value = render_target_format_;
314 vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc,
315 &config_attrib, 1, &va_config_);
316 if (ret != VA_STATUS_SUCCESS) {
317 ETRACE("Create VA Config failed\n");
321 // These parameters are not used in vaCreateContext so just set them to dummy
325 ret = vaCreateContext(va_display_, va_config_, width, height, 0x00, nullptr,
329 return ret == VA_STATUS_SUCCESS ? true : false;
332 void VARenderer::DestroyContext() {
333 if (va_context_ != VA_INVALID_ID) {
334 vaDestroyContext(va_display_, va_context_);
335 va_context_ = VA_INVALID_ID;
337 if (va_config_ != VA_INVALID_ID) {
338 vaDestroyConfig(va_display_, va_config_);
339 va_config_ = VA_INVALID_ID;
342 std::vector<VABufferID>().swap(filters_);
343 std::vector<ScopedVABufferID>().swap(cb_elements_);
344 std::vector<ScopedVABufferID>().swap(sharp_);
347 bool VARenderer::UpdateCaps() {
352 update_caps_ = false;
354 VAProcFilterCapColorBalance colorbalancecaps[VAProcColorBalanceCount];
355 uint32_t colorbalance_num = VAProcColorBalanceCount;
356 uint32_t sharp_num = 1;
357 uint32_t deinterlace_num = VAProcDeinterlacingCount;
359 if (colorbalance_caps_.empty()) {
360 if (!QueryVAProcFilterCaps(va_context_, VAProcFilterColorBalance,
361 colorbalancecaps, &colorbalance_num)) {
364 if (!QueryVAProcFilterCaps(va_context_, VAProcFilterSharpening,
365 &sharp_caps_.caps_, &sharp_num)) {
368 if (!QueryVAProcFilterCaps(va_context_, VAProcFilterDeinterlacing,
369 &deinterlace_caps_.caps_, &deinterlace_num)) {
373 SetVAProcFilterColorDefaultValue(&colorbalancecaps[0]);
374 SetVAProcFilterDeinterlaceDefaultMode();
377 std::vector<ScopedVABufferID> cb_elements(VAProcColorBalanceCount,
379 std::vector<ScopedVABufferID> sharp(1, va_display_);
380 std::vector<ScopedVABufferID> deinterlace(1, va_display_);
382 std::vector<VABufferID>().swap(filters_);
383 std::vector<ScopedVABufferID>().swap(cb_elements_);
384 std::vector<ScopedVABufferID>().swap(sharp_);
385 std::vector<ScopedVABufferID>().swap(deinterlace_);
387 VAProcFilterParameterBufferColorBalance cbparam;
388 VAProcFilterParameterBuffer sharpparam;
389 VAProcFilterParameterBufferDeinterlacing deinterlaceparam;
391 for (auto itr = colorbalance_caps_.begin(); itr != colorbalance_caps_.end();
394 itr->second.use_default_ &&
395 itr->second.value_ != itr->second.caps_.range.default_value;
396 if (fabs(itr->second.value_ - itr->second.caps_.range.default_value) >=
397 itr->second.caps_.range.step ||
400 itr->second.value_ = itr->second.caps_.range.default_value;
402 cbparam.type = VAProcFilterColorBalance;
403 cbparam.value = itr->second.value_;
404 cbparam.attrib = itr->second.caps_.type;
405 if (!cb_elements[static_cast<int>(itr->first)].CreateBuffer(
406 va_context_, VAProcFilterParameterBufferType,
407 sizeof(VAProcFilterParameterBufferColorBalance), 1, &cbparam)) {
410 filters_.push_back(cb_elements[static_cast<int>(itr->first)].buffer());
414 cb_elements_.swap(cb_elements);
416 bool sharp_use_default =
417 sharp_caps_.use_default_ &&
418 sharp_caps_.value_ != sharp_caps_.caps_.range.default_value;
419 if (fabs(sharp_caps_.value_ - sharp_caps_.caps_.range.default_value) >=
420 sharp_caps_.caps_.range.step ||
422 if (sharp_use_default) {
423 sharp_caps_.value_ = sharp_caps_.caps_.range.default_value;
425 sharpparam.value = sharp_caps_.value_;
426 sharpparam.type = VAProcFilterSharpening;
427 if (!sharp[0].CreateBuffer(va_context_, VAProcFilterParameterBufferType,
428 sizeof(VAProcFilterParameterBuffer), 1,
432 filters_.push_back(sharp[0].buffer());
436 if (deinterlace_caps_.mode_ != VAProcDeinterlacingNone) {
437 deinterlaceparam.algorithm = deinterlace_caps_.mode_;
438 deinterlaceparam.type = VAProcFilterDeinterlacing;
439 if (!deinterlace[0].CreateBuffer(
440 va_context_, VAProcFilterParameterBufferType,
441 sizeof(VAProcFilterDeinterlacing), 1, &deinterlaceparam)) {
444 filters_.push_back(deinterlace[0].buffer());
446 deinterlace_.swap(deinterlace);
449 memset(¶m_, 0, sizeof(VAProcPipelineParameterBuffer));
450 param_.surface_color_standard = VAProcColorStandardBT601;
451 param_.output_color_standard = VAProcColorStandardBT601;
452 param_.num_filters = 0;
453 param_.filters = nullptr;
454 param_.filter_flags = VA_FRAME_PICTURE;
456 if (filters_.size()) {
457 param_.filters = &filters_[0];
458 param_.num_filters = static_cast<unsigned int>(filters_.size());
464 } // namespace hwcomposer