OSDN Git Service

9080b4e31d669754ceafee7f81a86e48d81a303c
[android-x86/external-IA-Hardware-Composer.git] / common / compositor / va / varenderer.cpp
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include "varenderer.h"
18 #include "platformdefines.h"
19
20 #include <xf86drm.h>
21 #include <drm_fourcc.h>
22
23 #include "hwctrace.h"
24 #include "nativesurface.h"
25 #include "overlaybuffer.h"
26 #include "renderstate.h"
27
28 #ifdef ANDROID
29 #include <va/va_android.h>
30 #endif
31
32 #define ANDROID_DISPLAY_HANDLE 0x18C34078
33 #define UNUSED(x) (void*)(&x)
34
35 namespace hwcomposer {
36
37 VARenderer::~VARenderer() {
38   DestroyContext();
39
40   if (va_display_) {
41     vaTerminate(va_display_);
42   }
43 }
44
45 bool VARenderer::Init(int gpu_fd) {
46 #ifdef ANDROID
47   unsigned int native_display = ANDROID_DISPLAY_HANDLE;
48   va_display_ = vaGetDisplay(&native_display);
49   UNUSED(gpu_fd);
50 #else
51   va_display_ = vaGetDisplayDRM(gpu_fd);
52 #endif
53   if (!va_display_) {
54     ETRACE("vaGetDisplay failed\n");
55     return false;
56   }
57   VAStatus ret = VA_STATUS_SUCCESS;
58   int major, minor;
59   ret = vaInitialize(va_display_, &major, &minor);
60   return ret == VA_STATUS_SUCCESS ? true : false;
61 }
62
63 bool VARenderer::QueryVAProcFilterCaps(VAContextID context,
64                                        VAProcFilterType type, void* caps,
65                                        uint32_t* num) {
66   VAStatus ret =
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;
71 }
72
73 bool VARenderer::MapVAProcFilterColorModetoHwc(HWCColorControl& vppmode,
74                                                VAProcColorBalanceType vamode) {
75   switch (vamode) {
76     case VAProcColorBalanceHue:
77       vppmode = HWCColorControl::kColorHue;
78       break;
79     case VAProcColorBalanceSaturation:
80       vppmode = HWCColorControl::kColorSaturation;
81       break;
82     case VAProcColorBalanceBrightness:
83       vppmode = HWCColorControl::kColorBrightness;
84       break;
85     case VAProcColorBalanceContrast:
86       vppmode = HWCColorControl::kColorContrast;
87       break;
88     default:
89       return false;
90   }
91   return true;
92 }
93
94 bool VARenderer::SetVAProcFilterColorDefaultValue(
95     VAProcFilterCapColorBalance* caps) {
96   HWCColorControl mode;
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;
101     }
102   }
103   sharp_caps_.value_ = sharp_caps_.caps_.range.default_value;
104   update_caps_ = true;
105   return true;
106 }
107
108 bool VARenderer::SetVAProcFilterDeinterlaceDefaultMode() {
109   if (deinterlace_caps_.mode_ != VAProcDeinterlacingNone) {
110     deinterlace_caps_.mode_ = VAProcDeinterlacingNone;
111     update_caps_ = true;
112   }
113   return true;
114 }
115
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;
125         update_caps_ = true;
126       }
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");
131         return false;
132       }
133       colorbalance_caps_[mode].value_ = prop.value_;
134       colorbalance_caps_[mode].use_default_ = false;
135       update_caps_ = true;
136     }
137     return true;
138   } else if (mode == HWCColorControl::kColorSharpness) {
139     if (prop.use_default_) {
140       if (!sharp_caps_.use_default_) {
141         sharp_caps_.use_default_ = true;
142         update_caps_ = true;
143       }
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");
148         return false;
149       }
150       sharp_caps_.value_ = prop.value_;
151       sharp_caps_.use_default_ = false;
152       update_caps_ = true;
153     }
154     return true;
155   } else {
156     ETRACE("VA Filter undefined color mode\n");
157     return false;
158   }
159 }
160
161 bool VARenderer::GetVAProcDeinterlaceFlagFromVideo(HWCDeinterlaceFlag flag) {
162   if (flag != HWCDeinterlaceFlag::kDeinterlaceFlagAuto) {
163     return false;
164   } else {
165     // TODO:Need video buffer meta data to judge if the frame really need
166     // Deinterlace.
167   }
168   return false;
169 }
170 bool VARenderer::SetVAProcFilterDeinterlaceMode(
171     const HWCDeinterlaceProp& prop) {
172   if (prop.flag_ == HWCDeinterlaceFlag::kDeinterlaceFlagNone) {
173     SetVAProcFilterDeinterlaceDefaultMode();
174     return true;
175   } else if (prop.flag_ == HWCDeinterlaceFlag::kDeinterlaceFlagForce ||
176              GetVAProcDeinterlaceFlagFromVideo(prop.flag_)) {
177     switch (prop.mode_) {
178       case HWCDeinterlaceControl::kDeinterlaceNone:
179         deinterlace_caps_.mode_ = VAProcDeinterlacingNone;
180         break;
181       case HWCDeinterlaceControl::kDeinterlaceBob:
182         deinterlace_caps_.mode_ = VAProcDeinterlacingBob;
183         break;
184       case HWCDeinterlaceControl::kDeinterlaceWeave:
185         deinterlace_caps_.mode_ = VAProcDeinterlacingWeave;
186         break;
187       case HWCDeinterlaceControl::kDeinterlaceMotionAdaptive:
188         deinterlace_caps_.mode_ = VAProcDeinterlacingMotionAdaptive;
189         break;
190       case HWCDeinterlaceControl::kDeinterlaceMotionCompensated:
191         deinterlace_caps_.mode_ = VAProcDeinterlacingMotionCompensated;
192         break;
193       default:
194         ETRACE("Hwc unsupport deinterlace mode\n");
195         return false;
196     }
197   for (int i = 0; i < VAProcDeinterlacingCount; i++) {
198     if (deinterlace_caps_.caps_[i].type == deinterlace_caps_.mode_) {
199       update_caps_ = true;
200       return true;
201     }
202   }
203   ETRACE("VA Filter unsupport deinterlace mode\n");
204   return false;
205   }
206   return false;
207 }
208
209 bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) {
210   CTRACE();
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");
217       return false;
218     }
219   }
220
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");
229     return false;
230   }
231
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");
241     return false;
242   }
243
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();
251
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();
258
259   param_.surface = surface_in;
260   param_.surface_region = &surface_region;
261   param_.output_region = &output_region;
262
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);
267
268   for (auto itr = state.colors_.begin(); itr != state.colors_.end(); itr++) {
269     SetVAProcFilterColorValue(itr->first, itr->second);
270   }
271   SetVAProcFilterDeinterlaceMode(state.deinterlace_);
272
273   if (!UpdateCaps()) {
274     ETRACE("Failed to update capabailities. \n");
275     return false;
276   }
277
278   ScopedVABufferID pipeline_buffer(va_display_);
279   if (!pipeline_buffer.CreateBuffer(
280           va_context_, VAProcPipelineParameterBufferType,
281           sizeof(VAProcPipelineParameterBuffer), 1, &param_)) {
282     return false;
283   }
284
285   VAStatus ret = VA_STATUS_SUCCESS;
286   ret = vaBeginPicture(va_display_, va_context_, surface_out);
287   ret |=
288       vaRenderPicture(va_display_, va_context_, &pipeline_buffer.buffer(), 1);
289   ret |= vaEndPicture(va_display_, va_context_);
290
291   return ret == VA_STATUS_SUCCESS ? true : false;
292 }
293
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);
301     }
302   }
303
304   return true;
305 }
306
307 bool VARenderer::CreateContext() {
308   DestroyContext();
309
310   VAConfigAttrib config_attrib;
311   config_attrib.type = VAConfigAttribRTFormat;
312   config_attrib.value = render_target_format_;
313   VAStatus ret =
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");
318     return false;
319   }
320
321   // These parameters are not used in vaCreateContext so just set them to dummy
322   // values
323   int width = 1;
324   int height = 1;
325   ret = vaCreateContext(va_display_, va_config_, width, height, 0x00, nullptr,
326                         0, &va_context_);
327
328   update_caps_ = true;
329   return ret == VA_STATUS_SUCCESS ? true : false;
330 }
331
332 void VARenderer::DestroyContext() {
333   if (va_context_ != VA_INVALID_ID) {
334     vaDestroyContext(va_display_, va_context_);
335     va_context_ = VA_INVALID_ID;
336   }
337   if (va_config_ != VA_INVALID_ID) {
338     vaDestroyConfig(va_display_, va_config_);
339     va_config_ = VA_INVALID_ID;
340   }
341
342   std::vector<VABufferID>().swap(filters_);
343   std::vector<ScopedVABufferID>().swap(cb_elements_);
344   std::vector<ScopedVABufferID>().swap(sharp_);
345 }
346
347 bool VARenderer::UpdateCaps() {
348   if (!update_caps_) {
349     return true;
350   }
351
352   update_caps_ = false;
353
354   VAProcFilterCapColorBalance colorbalancecaps[VAProcColorBalanceCount];
355   uint32_t colorbalance_num = VAProcColorBalanceCount;
356   uint32_t sharp_num = 1;
357   uint32_t deinterlace_num = VAProcDeinterlacingCount;
358
359   if (colorbalance_caps_.empty()) {
360     if (!QueryVAProcFilterCaps(va_context_, VAProcFilterColorBalance,
361                                colorbalancecaps, &colorbalance_num)) {
362       return false;
363     }
364     if (!QueryVAProcFilterCaps(va_context_, VAProcFilterSharpening,
365                                &sharp_caps_.caps_, &sharp_num)) {
366       return false;
367     }
368     if (!QueryVAProcFilterCaps(va_context_, VAProcFilterDeinterlacing,
369                                &deinterlace_caps_.caps_, &deinterlace_num)) {
370       return false;
371     }
372
373     SetVAProcFilterColorDefaultValue(&colorbalancecaps[0]);
374     SetVAProcFilterDeinterlaceDefaultMode();
375
376   } else {
377     std::vector<ScopedVABufferID> cb_elements(VAProcColorBalanceCount,
378                                               va_display_);
379     std::vector<ScopedVABufferID> sharp(1, va_display_);
380     std::vector<ScopedVABufferID> deinterlace(1, va_display_);
381
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_);
386
387     VAProcFilterParameterBufferColorBalance cbparam;
388     VAProcFilterParameterBuffer sharpparam;
389     VAProcFilterParameterBufferDeinterlacing deinterlaceparam;
390
391     for (auto itr = colorbalance_caps_.begin(); itr != colorbalance_caps_.end();
392          itr++) {
393       bool use_default =
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 ||
398           use_default) {
399         if (use_default) {
400           itr->second.value_ = itr->second.caps_.range.default_value;
401         }
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)) {
408           return false;
409         }
410         filters_.push_back(cb_elements[static_cast<int>(itr->first)].buffer());
411       }
412     }
413
414     cb_elements_.swap(cb_elements);
415
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 ||
421         sharp_use_default) {
422       if (sharp_use_default) {
423         sharp_caps_.value_ = sharp_caps_.caps_.range.default_value;
424       }
425       sharpparam.value = sharp_caps_.value_;
426       sharpparam.type = VAProcFilterSharpening;
427       if (!sharp[0].CreateBuffer(va_context_, VAProcFilterParameterBufferType,
428                                  sizeof(VAProcFilterParameterBuffer), 1,
429                                  &sharpparam)) {
430         return false;
431       }
432       filters_.push_back(sharp[0].buffer());
433     }
434     sharp_.swap(sharp);
435
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)) {
442         return false;
443       }
444       filters_.push_back(deinterlace[0].buffer());
445     }
446     deinterlace_.swap(deinterlace);
447   }
448
449   memset(&param_, 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;
455
456   if (filters_.size()) {
457     param_.filters = &filters_[0];
458     param_.num_filters = static_cast<unsigned int>(filters_.size());
459   }
460
461   return true;
462 }
463
464 }  // namespace hwcomposer