OSDN Git Service

Add sharp adjustment on VA module.
[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::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");
116       return false;
117     }
118     colorbalance_caps_[mode].value_ = value;
119     update_caps_ = true;
120     return true;
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");
125       return false;
126     }
127     sharp_caps_.value_ = value;
128     update_caps_ = true;
129     return true;
130   } else {
131     ETRACE("VA Filter undefined color mode\n");
132     return false;
133   }
134 }
135 bool VARenderer::Draw(const MediaState& state, NativeSurface* surface) {
136   CTRACE();
137   OverlayBuffer* buffer_out = surface->GetLayer()->GetBuffer();
138   int rt_format = DrmFormatToRTFormat(buffer_out->GetFormat());
139
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");
144       return false;
145     }
146   }
147
148   if (!UpdateCaps()) {
149     ETRACE("Failed to update capabailities. \n");
150     return false;
151   }
152
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");
161     return false;
162   }
163
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");
173     return false;
174   }
175
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();
183
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();
190
191   param_.surface = surface_in;
192   param_.surface_region = &surface_region;
193   param_.output_region = &output_region;
194
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);
199
200   for (HWCColorMap::const_iterator itr = state.colors_.begin();
201        itr != state.colors_.end(); itr++) {
202     SetVAProcFilterColorValue(itr->first, itr->second);
203   }
204
205   ScopedVABufferID pipeline_buffer(va_display_);
206   if (!pipeline_buffer.CreateBuffer(
207           va_context_, VAProcPipelineParameterBufferType,
208           sizeof(VAProcPipelineParameterBuffer), 1, &param_)) {
209     return false;
210   }
211
212   VAStatus ret = VA_STATUS_SUCCESS;
213   ret = vaBeginPicture(va_display_, va_context_, surface_out);
214   ret |=
215       vaRenderPicture(va_display_, va_context_, &pipeline_buffer.buffer(), 1);
216   ret |= vaEndPicture(va_display_, va_context_);
217
218   return ret == VA_STATUS_SUCCESS ? true : false;
219 }
220
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);
228     }
229   }
230
231   return true;
232 }
233
234 bool VARenderer::CreateContext() {
235   DestroyContext();
236
237   VAConfigAttrib config_attrib;
238   config_attrib.type = VAConfigAttribRTFormat;
239   config_attrib.value = render_target_format_;
240   VAStatus ret =
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");
245     return false;
246   }
247
248   // These parameters are not used in vaCreateContext so just set them to dummy
249   // values
250   int width = 1;
251   int height = 1;
252   ret = vaCreateContext(va_display_, va_config_, width, height, 0x00, nullptr,
253                         0, &va_context_);
254
255   update_caps_ = true;
256   return ret == VA_STATUS_SUCCESS ? true : false;
257 }
258
259 void VARenderer::DestroyContext() {
260   if (va_context_ != VA_INVALID_ID) {
261     vaDestroyContext(va_display_, va_context_);
262     va_context_ = VA_INVALID_ID;
263   }
264   if (va_config_ != VA_INVALID_ID) {
265     vaDestroyConfig(va_display_, va_config_);
266     va_config_ = VA_INVALID_ID;
267   }
268
269   std::vector<VABufferID>().swap(filters_);
270   std::vector<ScopedVABufferID>().swap(cb_elements_);
271   std::vector<ScopedVABufferID>().swap(sharp_);
272 }
273
274 bool VARenderer::UpdateCaps() {
275   if (!update_caps_) {
276     return true;
277   }
278
279   update_caps_ = false;
280
281   VAProcFilterCapColorBalance colorbalancecaps[VAProcColorBalanceCount];
282   uint32_t colorbalance_num = VAProcColorBalanceCount;
283   uint32_t sharp_num = 1;
284
285   if (colorbalance_caps_.empty()) {
286     if (!QueryVAProcFilterCaps(va_context_, VAProcFilterColorBalance,
287                                colorbalancecaps, &colorbalance_num)) {
288       return false;
289     }
290     if (!QueryVAProcFilterCaps(va_context_, VAProcFilterSharpening,
291                                &sharp_caps_.caps_, &sharp_num)) {
292       return false;
293     }
294     SetVAProcFilterColorDefaultValue(&colorbalancecaps[0]);
295
296   } else {
297     std::vector<ScopedVABufferID> cb_elements(VAProcColorBalanceCount,
298                                               va_display_);
299     std::vector<ScopedVABufferID> sharp(1, va_display_);
300
301     std::vector<VABufferID>().swap(filters_);
302     std::vector<ScopedVABufferID>().swap(cb_elements_);
303     std::vector<ScopedVABufferID>().swap(sharp_);
304
305     VAProcFilterParameterBufferColorBalance cbparam;
306     VAProcFilterParameterBuffer sharpparam;
307
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)) {
318           return false;
319         }
320         filters_.push_back(cb_elements[static_cast<int>(itr->first)].buffer());
321       }
322     }
323
324     cb_elements_.swap(cb_elements);
325
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,
332                                  &sharpparam)) {
333         return false;
334       }
335       filters_.push_back(sharp[0].buffer());
336     }
337     sharp_.swap(sharp);
338   }
339
340   memset(&param_, 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;
346
347   if (filters_.size()) {
348     param_.filters = &filters_[0];
349     param_.num_filters = static_cast<unsigned int>(filters_.size());
350   }
351
352   return true;
353 }
354
355 }  // namespace hwcomposer