OSDN Git Service

Added the support of panorama view mode in AaaG HWC.
[android-x86/external-IA-Hardware-Composer.git] / common / display / virtualpanoramadisplay.cpp
1 /*
2 // Copyright (c) 2016 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 "virtualpanoramadisplay.h"
18
19 #include <drm_fourcc.h>
20
21 #include <hwclayer.h>
22 #include <nativebufferhandler.h>
23
24 #include <sstream>
25 #include <vector>
26
27 #include "hwctrace.h"
28 #include "overlaylayer.h"
29
30 #include "hwcutils.h"
31
32 namespace hwcomposer {
33
34 VirtualPanoramaDisplay::VirtualPanoramaDisplay(
35     uint32_t gpu_fd, NativeBufferHandler *buffer_handler,
36     FrameBufferManager *frame_buffer_manager, uint32_t pipe_id,
37     uint32_t /*crtc_id*/)
38     : output_handle_(0),
39       acquire_fence_(-1),
40       width_(0),
41       height_(0),
42       display_index_(pipe_id) {
43   resource_manager_.reset(new ResourceManager(buffer_handler));
44   if (!resource_manager_) {
45     ETRACE("Failed to construct hwc layer buffer manager");
46   }
47   fb_manager_ = frame_buffer_manager;
48   compositor_.Init(resource_manager_.get(), gpu_fd, fb_manager_);
49 }
50
51 void VirtualPanoramaDisplay::InitHyperDmaBuf() {
52   if (hyper_dmabuf_initialized)
53     return;
54 #ifdef HYPER_DMABUF_SHARING
55   int ret;
56   struct ioctl_hyper_dmabuf_tx_ch_setup msg;
57   memset(&msg, 0, sizeof(ioctl_hyper_dmabuf_tx_ch_setup));
58
59   mHyperDmaBuf_Fd = open(HYPER_DMABUF_PATH, O_RDWR);
60
61   if (mHyperDmaBuf_Fd < 0)
62     ETRACE("Hyper DmaBuf: open hyper dmabuf device node %s failed because %s",
63            HYPER_DMABUF_PATH, strerror(errno));
64   else {
65     ITRACE("Hyper DmaBuf: open hyper dmabuf device node %s successfully!",
66            HYPER_DMABUF_PATH);
67
68     /* TODO: add config option to specify which domains should be used, for
69      * now we share always with dom0 */
70     msg.remote_domain = 0;
71     ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_TX_CH_SETUP, &msg);
72     if (ret) {
73       ETRACE(
74           "Hyper DmaBuf:"
75           "IOCTL_HYPER_DMABUF_TX_CH_SETUP failed with error %d\n",
76           ret);
77       close(mHyperDmaBuf_Fd);
78       mHyperDmaBuf_Fd = -1;
79     } else
80       ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_TX_CH_SETUP Done!\n");
81   }
82 #endif
83   hyper_dmabuf_initialized = true;
84 }
85
86 VirtualPanoramaDisplay::~VirtualPanoramaDisplay() {
87   if (acquire_fence_ > 0) {
88     close(acquire_fence_);
89   }
90
91   if (handle_) {
92     ResourceHandle temp;
93     temp.handle_ = handle_;
94     resource_manager_->MarkResourceForDeletion(temp, false);
95   }
96
97   delete output_handle_;
98   std::vector<OverlayLayer>().swap(in_flight_layers_);
99
100   resource_manager_->PurgeBuffer();
101   compositor_.Reset();
102 #ifdef HYPER_DMABUF_SHARING
103   if (mHyperDmaBuf_Fd > 0) {
104     auto it = mHyperDmaExportedBuffers.begin();
105     for (; it != mHyperDmaExportedBuffers.end(); ++it) {
106       struct ioctl_hyper_dmabuf_unexport msg;
107       int ret;
108       msg.hid = it->second.hyper_dmabuf_id;
109       // Todo: find a reduced dmabuf free delay time
110       msg.delay_ms = 1000;
111       ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
112       if (ret) {
113         ETRACE(
114             "Hyper DmaBuf:"
115             "IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d [0x%x]\n",
116             ret, it->second.hyper_dmabuf_id.id);
117       } else {
118         ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
119                it->second.hyper_dmabuf_id.id);
120         mHyperDmaExportedBuffers.erase(it);
121       }
122     }
123
124     close(mHyperDmaBuf_Fd);
125     mHyperDmaBuf_Fd = -1;
126   }
127 #endif
128 }
129
130 void VirtualPanoramaDisplay::InitVirtualDisplay(uint32_t width,
131                                                 uint32_t height) {
132   width_ = width;
133   height_ = height;
134   CreateOutBuffer();
135 }
136
137 bool VirtualPanoramaDisplay::GetActiveConfig(uint32_t *config) {
138   if (!config)
139     return false;
140
141   config[0] = 1;
142   return true;
143 }
144
145 bool VirtualPanoramaDisplay::SetActiveConfig(uint32_t /*config*/) {
146   return true;
147 }
148
149 void VirtualPanoramaDisplay::HyperDmaExport() {
150 #ifdef HYPER_DMABUF_SHARING
151   int ret = 0;
152   size_t buffer_number = 0;
153   uint32_t surf_index = display_index_;
154   size_t info_size = sizeof(vm_buffer_info);
155   size_t header_size = sizeof(vm_header);
156   vm_header header;
157   vm_buffer_info info;
158   memset(&header, 0, header_size);
159   memset(&info, 0, info_size);
160   struct ioctl_hyper_dmabuf_export_remote msg;
161   char meta_data[header_size + info_size];
162   uint32_t imported_fd = 0;
163
164   header.n_buffers = 1;
165   header.version = 3;
166   header.output = display_index_;
167   header.counter = frame_count_++;
168   header.disp_w = width_;
169   header.disp_h = height_;
170
171   std::shared_ptr<OverlayBuffer> buffer(NULL);
172   uint32_t gpu_fd = resource_manager_->GetNativeBufferHandler()->GetFd();
173   uint32_t id = GetNativeBuffer(gpu_fd, output_handle_);
174   buffer = resource_manager_->FindCachedBuffer(id);
175   const uint32_t *pitches;
176   const uint32_t *offsets;
177
178   if (buffer == NULL) {
179     buffer = OverlayBuffer::CreateOverlayBuffer();
180     buffer->InitializeFromNativeHandle(output_handle_, resource_manager_.get(),
181                                        fb_manager_);
182     resource_manager_->RegisterBuffer(id, buffer);
183     imported_fd = buffer->GetPrimeFD();
184     if (mHyperDmaBuf_Fd > 0 && imported_fd > 0) {
185       mHyperDmaExportedBuffers[imported_fd].width = buffer->GetWidth();
186       mHyperDmaExportedBuffers[imported_fd].height = buffer->GetHeight();
187       mHyperDmaExportedBuffers[imported_fd].format = buffer->GetFormat();
188       pitches = buffer->GetPitches();
189       offsets = buffer->GetOffsets();
190       mHyperDmaExportedBuffers[imported_fd].pitch[0] = pitches[0];
191       mHyperDmaExportedBuffers[imported_fd].pitch[1] = pitches[1];
192       mHyperDmaExportedBuffers[imported_fd].pitch[2] = pitches[2];
193       mHyperDmaExportedBuffers[imported_fd].offset[0] = offsets[0];
194       mHyperDmaExportedBuffers[imported_fd].offset[1] = offsets[1];
195       mHyperDmaExportedBuffers[imported_fd].offset[2] = offsets[2];
196       mHyperDmaExportedBuffers[imported_fd].tile_format =
197           buffer->GetTilingMode();
198       mHyperDmaExportedBuffers[imported_fd].rotation = 0;
199       mHyperDmaExportedBuffers[imported_fd].status = 0;
200       mHyperDmaExportedBuffers[imported_fd].counter = 0;
201       mHyperDmaExportedBuffers[imported_fd].surface_id = display_index_;
202       mHyperDmaExportedBuffers[imported_fd].bbox[0] = 0;
203       mHyperDmaExportedBuffers[imported_fd].bbox[1] = 0;
204       mHyperDmaExportedBuffers[imported_fd].bbox[2] = buffer->GetWidth();
205       mHyperDmaExportedBuffers[imported_fd].bbox[3] = buffer->GetHeight();
206     }
207   }
208
209   msg.sz_priv = header_size + info_size;
210   msg.priv = meta_data;
211
212   /* TODO: add more flexibility here, instead of hardcoded domain 0*/
213   msg.remote_domain = 0;
214   msg.dmabuf_fd = buffer->GetPrimeFD();
215
216   char index[15];
217   mHyperDmaExportedBuffers[buffer->GetPrimeFD()].surf_index = surf_index;
218   memset(index, 0, sizeof(index));
219   sprintf(index, "Cluster_%d", surf_index);
220   strncpy(mHyperDmaExportedBuffers[buffer->GetPrimeFD()].surface_name, index,
221           SURFACE_NAME_LENGTH);
222   mHyperDmaExportedBuffers[buffer->GetPrimeFD()].hyper_dmabuf_id =
223       (hyper_dmabuf_id_t){-1, {-1, -1, -1}};
224   memcpy(meta_data, &header, header_size);
225   memcpy(meta_data + header_size,
226          &mHyperDmaExportedBuffers[buffer->GetPrimeFD()], info_size);
227
228   ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_EXPORT_REMOTE, &msg);
229   if (ret) {
230     ETRACE("Hyper DmaBuf: Exporting hyper_dmabuf failed with error %d\n", ret);
231     return;
232   }
233
234   resource_manager_->PreparePurgedResources();
235
236   std::vector<ResourceHandle> purged_gl_resources;
237   std::vector<MediaResourceHandle> purged_media_resources;
238   bool has_gpu_resource = false;
239
240   resource_manager_->GetPurgedResources(
241       purged_gl_resources, purged_media_resources, &has_gpu_resource);
242
243   size_t purged_size = purged_gl_resources.size();
244
245   if (purged_size != 0) {
246     const NativeBufferHandler *handler =
247         resource_manager_->GetNativeBufferHandler();
248
249     for (size_t i = 0; i < purged_size; i++) {
250       const ResourceHandle &handle = purged_gl_resources.at(i);
251       if (!handle.handle_) {
252         continue;
253       }
254       auto search = mHyperDmaExportedBuffers.find(
255           handle.handle_->imported_handle_->data[0]);
256       if (search != mHyperDmaExportedBuffers.end()) {
257         struct ioctl_hyper_dmabuf_unexport msg;
258         int ret;
259         msg.hid = search->second.hyper_dmabuf_id;
260         msg.delay_ms = 1000;
261         ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
262         if (ret) {
263           ETRACE(
264               "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d "
265               "[0x%x]\n",
266               ret, search->second.hyper_dmabuf_id.id);
267         } else {
268           ITRACE(
269               "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
270               search->second.hyper_dmabuf_id.id);
271         }
272         mHyperDmaExportedBuffers.erase(search);
273       }
274       handler->ReleaseBuffer(handle.handle_);
275       handler->DestroyHandle(handle.handle_);
276     }
277   }
278 #endif
279 }
280
281 bool VirtualPanoramaDisplay::Present(std::vector<HwcLayer *> &source_layers,
282                                      int32_t *retire_fence,
283                                      PixelUploaderCallback * /*call_back*/,
284                                      bool handle_constraints) {
285   CTRACE();
286   if (!hyper_dmabuf_initialized) {
287     InitHyperDmaBuf();
288   }
289
290   std::vector<OverlayLayer> layers;
291   std::vector<HwcRect<int>> layers_rects;
292   std::vector<size_t> index;
293   int ret = 0;
294   size_t size = source_layers.size();
295   size_t previous_size = in_flight_layers_.size();
296   bool frame_changed = (size != previous_size);
297   bool layers_changed = frame_changed;
298   *retire_fence = -1;
299   uint32_t z_order = 0;
300
301   resource_manager_->RefreshBufferCache();
302   for (size_t layer_index = 0; layer_index < size; layer_index++) {
303     HwcLayer *layer = source_layers.at(layer_index);
304     layer->SetReleaseFence(-1);
305     if (!layer->IsVisible())
306       continue;
307     if (discard_protected_video_) {
308       if (layer->GetNativeHandle() != NULL &&
309           (layer->GetNativeHandle()->meta_data_.usage_ &
310            hwcomposer::kLayerProtected))
311         continue;
312     }
313
314     layers.emplace_back();
315     OverlayLayer &overlay_layer = layers.back();
316     OverlayLayer *previous_layer = NULL;
317     if (previous_size > z_order) {
318       previous_layer = &(in_flight_layers_.at(z_order));
319     }
320
321     handle_constraints = true;
322
323     overlay_layer.InitializeFromHwcLayer(
324         layer, resource_manager_.get(), previous_layer, z_order, layer_index,
325         height_, kIdentity, handle_constraints, fb_manager_);
326     index.emplace_back(z_order);
327     layers_rects.emplace_back(overlay_layer.GetDisplayFrame());
328
329     z_order++;
330
331     if (frame_changed) {
332       layer->Validate();
333       continue;
334     }
335
336     if (!previous_layer || overlay_layer.HasLayerContentChanged() ||
337         overlay_layer.HasDimensionsChanged()) {
338       layers_changed = true;
339     }
340
341     layer->Validate();
342   }
343
344   if (layers_changed) {
345     compositor_.BeginFrame(false);
346     // Prepare for final composition.
347     if (!compositor_.DrawOffscreen(
348             layers, layers_rects, index, resource_manager_.get(), fb_manager_,
349             width_, height_, output_handle_, acquire_fence_, retire_fence)) {
350       ETRACE("Failed to prepare for the frame composition ret=%d", ret);
351       return false;
352     }
353
354     acquire_fence_ = 0;
355
356     in_flight_layers_.swap(layers);
357   }
358
359   int32_t fence = *retire_fence;
360
361   if (fence > 0) {
362     for (size_t layer_index = 0; layer_index < size; layer_index++) {
363       HwcLayer *layer = source_layers.at(layer_index);
364       layer->SetReleaseFence(dup(fence));
365     }
366   } else {
367     for (size_t layer_index = 0; layer_index < size; layer_index++) {
368       const OverlayLayer &overlay_layer =
369           in_flight_layers_.at(index.at(layer_index));
370       HwcLayer *layer = source_layers.at(overlay_layer.GetLayerIndex());
371       layer->SetReleaseFence(overlay_layer.ReleaseAcquireFence());
372     }
373   }
374   if (resource_manager_->PreparePurgedResources()) {
375     compositor_.FreeResources();
376   }
377
378 #ifdef HYPER_DMABUF_SHARING
379   HyperDmaExport();
380 #endif
381
382   return true;
383 }
384
385 void VirtualPanoramaDisplay::CreateOutBuffer() {
386   const NativeBufferHandler *handler =
387       resource_manager_->GetNativeBufferHandler();
388   HWCNativeHandle native_handle = 0;
389   bool modifier_used = false;
390   uint32_t usage = hwcomposer::kLayerNormal;
391
392   handler->CreateBuffer(width_, height_, DRM_FORMAT_BGRA8888, &native_handle,
393                         usage, &modifier_used);
394
395   DTRACE("Create Buffer handler :%p", native_handle);
396   SetOutputBuffer(native_handle, -1);
397 }
398
399 void VirtualPanoramaDisplay::SetOutputBuffer(HWCNativeHandle buffer,
400                                              int32_t acquire_fence) {
401   if (!output_handle_ || output_handle_ != buffer) {
402     const NativeBufferHandler *handler =
403         resource_manager_->GetNativeBufferHandler();
404
405     if (handle_) {
406       handler->ReleaseBuffer(handle_);
407       handler->DestroyHandle(handle_);
408     }
409
410     delete output_handle_;
411     output_handle_ = buffer;
412     handle_ = 0;
413
414     if (output_handle_) {
415       handler->CopyHandle(output_handle_, &handle_);
416     }
417   }
418
419   if (acquire_fence_ > 0) {
420     close(acquire_fence_);
421     acquire_fence_ = -1;
422   }
423
424   if (acquire_fence > 0) {
425     acquire_fence_ = dup(acquire_fence);
426   }
427 }
428
429 bool VirtualPanoramaDisplay::Initialize(
430     NativeBufferHandler * /*buffer_manager*/,
431     FrameBufferManager *frame_buffer_manager) {
432   return true;
433 }
434
435 bool VirtualPanoramaDisplay::GetDisplayAttribute(uint32_t /*config*/,
436                                                  HWCDisplayAttribute attribute,
437                                                  int32_t *value) {
438   // We always get the values from preferred mode config.
439   switch (attribute) {
440     case HWCDisplayAttribute::kWidth:
441       *value = width_;
442       break;
443     case HWCDisplayAttribute::kHeight:
444       *value = height_;
445       break;
446     case HWCDisplayAttribute::kRefreshRate:
447       // in nanoseconds
448       *value = 16666666;
449       break;
450     case HWCDisplayAttribute::kDpiX:
451       // Dots per 1000 inches
452       *value = 1;
453       break;
454     case HWCDisplayAttribute::kDpiY:
455       // Dots per 1000 inches
456       *value = 1;
457       break;
458     default:
459       *value = -1;
460       return false;
461   }
462
463   return true;
464 }
465
466 bool VirtualPanoramaDisplay::GetDisplayConfigs(uint32_t *num_configs,
467                                                uint32_t *configs) {
468   if (!num_configs)
469     return false;
470   *num_configs = 1;
471   if (configs)
472     configs[0] = 0;
473
474   return true;
475 }
476
477 bool VirtualPanoramaDisplay::GetDisplayName(uint32_t *size, char *name) {
478   std::ostringstream stream;
479   stream << "Virtual Panorama:" << display_index_;
480   std::string string = stream.str();
481   size_t length = string.length();
482   if (!name) {
483     *size = length;
484     return true;
485   }
486
487   *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
488   strncpy(name, string.c_str(), *size);
489   return true;
490 }
491
492 int VirtualPanoramaDisplay::GetDisplayPipe() {
493   return -1;
494 }
495
496 bool VirtualPanoramaDisplay::SetPowerMode(uint32_t /*power_mode*/) {
497   return true;
498 }
499
500 int VirtualPanoramaDisplay::RegisterVsyncCallback(
501     std::shared_ptr<VsyncCallback> /*callback*/, uint32_t /*display_id*/) {
502   // return 0;
503   return 1;
504 }
505
506 void VirtualPanoramaDisplay::VSyncControl(bool /*enabled*/) {
507 }
508
509 bool VirtualPanoramaDisplay::CheckPlaneFormat(uint32_t /*format*/) {
510   // assuming that virtual display supports the format
511   return true;
512 }
513 }  // namespace hwcomposer