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::SetVAProcFilterColorValue(HWCColorControl mode, float value) {
109 if (mode == HWCColorControl::kColorHue ||
110 mode == HWCColorControl::kColorSaturation ||
111 mode == HWCColorControl::kColorBrightness ||
112 mode == HWCColorControl::kColorContrast) {
113 if (value > colorbalance_caps_[mode].caps_.range.max_value ||
114 value < colorbalance_caps_[mode].caps_.range.min_value) {
115 ETRACE("VA Filter value out of range\n");
118 colorbalance_caps_[mode].value_ = value;
121 } else if (mode == HWCColorControl::kColorSharp) {
122 if (value > sharp_caps_.caps_.range.max_value ||
123 value < sharp_caps_.caps_.range.min_value) {
124 ETRACE("VA Filter sharp value out of range\n");
127 sharp_caps_.value_ = value;
131 ETRACE("VA Filter undefined color mode\n");
135 bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) {
137 OverlayBuffer* buffer_out = surface->GetLayer()->GetBuffer();
138 int rt_format = DrmFormatToRTFormat(buffer_out->GetFormat());
140 if (va_context_ == VA_INVALID_ID || render_target_format_ != rt_format) {
141 render_target_format_ = rt_format;
142 if (!CreateContext()) {
143 ETRACE("Create VA context failed\n");
149 ETRACE("Failed to update capabailities. \n");
153 // Get Input Surface.
154 OverlayBuffer* buffer_in = state.layer_->GetBuffer();
155 const MediaResourceHandle& resource = buffer_in->GetMediaResource(
156 va_display_, state.layer_->GetSourceCropWidth(),
157 state.layer_->GetSourceCropHeight());
158 VASurfaceID surface_in = resource.surface_;
159 if (surface_in == VA_INVALID_ID) {
160 ETRACE("Failed to create Va Input Surface. \n");
164 // Get Output Surface.
165 const OverlayLayer* layer_out = surface->GetLayer();
166 const MediaResourceHandle& out_resource =
167 layer_out->GetBuffer()->GetMediaResource(
168 va_display_, layer_out->GetSourceCropWidth(),
169 layer_out->GetSourceCropHeight());
170 VASurfaceID surface_out = out_resource.surface_;
171 if (surface_out == VA_INVALID_ID) {
172 ETRACE("Failed to create Va Output Surface. \n");
176 VARectangle surface_region;
177 const OverlayLayer* layer_in = state.layer_;
178 const HwcRect<float>& source_crop = layer_in->GetSourceCrop();
179 surface_region.x = static_cast<int>(source_crop.left);
180 surface_region.y = static_cast<int>(source_crop.top);
181 surface_region.width = layer_in->GetSourceCropWidth();
182 surface_region.height = layer_in->GetSourceCropHeight();
184 VARectangle output_region;
185 const HwcRect<float>& source_crop_out = layer_out->GetSourceCrop();
186 output_region.x = static_cast<int>(source_crop_out.left);
187 output_region.y = static_cast<int>(source_crop_out.top);
188 output_region.width = layer_out->GetSourceCropWidth();
189 output_region.height = layer_out->GetSourceCropHeight();
191 param_.surface = surface_in;
192 param_.surface_region = &surface_region;
193 param_.output_region = &output_region;
195 DUMPTRACE("surface_region: (%d, %d, %d, %d)\n", surface_region.x,
196 surface_region.y, surface_region.width, surface_region.height);
197 DUMPTRACE("Layer DisplayFrame:(%d,%d,%d,%d)\n", output_region.x,
198 output_region.y, output_region.width, output_region.height);
200 for (HWCColorMap::const_iterator itr = state.colors_.begin();
201 itr != state.colors_.end(); itr++) {
202 SetVAProcFilterColorValue(itr->first, itr->second);
205 ScopedVABufferID pipeline_buffer(va_display_);
206 if (!pipeline_buffer.CreateBuffer(
207 va_context_, VAProcPipelineParameterBufferType,
208 sizeof(VAProcPipelineParameterBuffer), 1, ¶m_)) {
212 VAStatus ret = VA_STATUS_SUCCESS;
213 ret = vaBeginPicture(va_display_, va_context_, surface_out);
215 vaRenderPicture(va_display_, va_context_, &pipeline_buffer.buffer(), 1);
216 ret |= vaEndPicture(va_display_, va_context_);
218 return ret == VA_STATUS_SUCCESS ? true : false;
221 bool VARenderer::DestroyMediaResources(
222 std::vector<struct media_import>& resources) {
223 size_t purged_size = resources.size();
224 for (size_t i = 0; i < purged_size; i++) {
225 MediaResourceHandle& handle = resources.at(i);
226 if (handle.surface_ != VA_INVALID_ID) {
227 vaDestroySurfaces(va_display_, &handle.surface_, 1);
234 bool VARenderer::CreateContext() {
237 VAConfigAttrib config_attrib;
238 config_attrib.type = VAConfigAttribRTFormat;
239 config_attrib.value = render_target_format_;
241 vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc,
242 &config_attrib, 1, &va_config_);
243 if (ret != VA_STATUS_SUCCESS) {
244 ETRACE("Create VA Config failed\n");
248 // These parameters are not used in vaCreateContext so just set them to dummy
252 ret = vaCreateContext(va_display_, va_config_, width, height, 0x00, nullptr,
256 return ret == VA_STATUS_SUCCESS ? true : false;
259 void VARenderer::DestroyContext() {
260 if (va_context_ != VA_INVALID_ID) {
261 vaDestroyContext(va_display_, va_context_);
262 va_context_ = VA_INVALID_ID;
264 if (va_config_ != VA_INVALID_ID) {
265 vaDestroyConfig(va_display_, va_config_);
266 va_config_ = VA_INVALID_ID;
269 std::vector<VABufferID>().swap(filters_);
270 std::vector<ScopedVABufferID>().swap(cb_elements_);
271 std::vector<ScopedVABufferID>().swap(sharp_);
274 bool VARenderer::UpdateCaps() {
279 update_caps_ = false;
281 VAProcFilterCapColorBalance colorbalancecaps[VAProcColorBalanceCount];
282 uint32_t colorbalance_num = VAProcColorBalanceCount;
283 uint32_t sharp_num = 1;
285 if (colorbalance_caps_.empty()) {
286 if (!QueryVAProcFilterCaps(va_context_, VAProcFilterColorBalance,
287 colorbalancecaps, &colorbalance_num)) {
290 if (!QueryVAProcFilterCaps(va_context_, VAProcFilterSharpening,
291 &sharp_caps_.caps_, &sharp_num)) {
294 SetVAProcFilterColorDefaultValue(&colorbalancecaps[0]);
297 std::vector<ScopedVABufferID> cb_elements(VAProcColorBalanceCount,
299 std::vector<ScopedVABufferID> sharp(1, va_display_);
301 std::vector<VABufferID>().swap(filters_);
302 std::vector<ScopedVABufferID>().swap(cb_elements_);
303 std::vector<ScopedVABufferID>().swap(sharp_);
305 VAProcFilterParameterBufferColorBalance cbparam;
306 VAProcFilterParameterBuffer sharpparam;
308 for (ColorBalanceCapMapItr itr = colorbalance_caps_.begin();
309 itr != colorbalance_caps_.end(); itr++) {
310 if (fabs(itr->second.value_ - itr->second.caps_.range.default_value) >=
311 itr->second.caps_.range.step) {
312 cbparam.type = VAProcFilterColorBalance;
313 cbparam.value = itr->second.value_;
314 cbparam.attrib = itr->second.caps_.type;
315 if (!cb_elements[static_cast<int>(itr->first)].CreateBuffer(
316 va_context_, VAProcFilterParameterBufferType,
317 sizeof(VAProcFilterParameterBufferColorBalance), 1, &cbparam)) {
320 filters_.push_back(cb_elements[static_cast<int>(itr->first)].buffer());
324 cb_elements_.swap(cb_elements);
326 if (fabs(sharp_caps_.value_ - sharp_caps_.caps_.range.default_value) >=
327 sharp_caps_.caps_.range.step) {
328 sharpparam.value = sharp_caps_.value_;
329 sharpparam.type = VAProcFilterSharpening;
330 if (!sharp[0].CreateBuffer(va_context_, VAProcFilterParameterBufferType,
331 sizeof(VAProcFilterParameterBuffer), 1,
335 filters_.push_back(sharp[0].buffer());
340 memset(¶m_, 0, sizeof(VAProcPipelineParameterBuffer));
341 param_.surface_color_standard = VAProcColorStandardBT601;
342 param_.output_color_standard = VAProcColorStandardBT601;
343 param_.num_filters = 0;
344 param_.filters = nullptr;
345 param_.filter_flags = VA_FRAME_PICTURE;
347 if (filters_.size()) {
348 param_.filters = &filters_[0];
349 param_.num_filters = static_cast<unsigned int>(filters_.size());
355 } // namespace hwcomposer