2 // Copyright (c) 2016 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 "virtualpanoramadisplay.h"
19 #include <drm_fourcc.h>
22 #include <nativebufferhandler.h>
28 #include "overlaylayer.h"
32 namespace hwcomposer {
34 VirtualPanoramaDisplay::VirtualPanoramaDisplay(
35 uint32_t gpu_fd, NativeBufferHandler *buffer_handler,
36 FrameBufferManager *frame_buffer_manager, uint32_t pipe_id,
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");
47 fb_manager_ = frame_buffer_manager;
48 compositor_.Init(resource_manager_.get(), gpu_fd, fb_manager_);
51 void VirtualPanoramaDisplay::InitHyperDmaBuf() {
52 if (hyper_dmabuf_initialized)
54 #ifdef HYPER_DMABUF_SHARING
56 struct ioctl_hyper_dmabuf_tx_ch_setup msg;
57 memset(&msg, 0, sizeof(ioctl_hyper_dmabuf_tx_ch_setup));
59 mHyperDmaBuf_Fd = open(HYPER_DMABUF_PATH, O_RDWR);
61 if (mHyperDmaBuf_Fd < 0)
62 ETRACE("Hyper DmaBuf: open hyper dmabuf device node %s failed because %s",
63 HYPER_DMABUF_PATH, strerror(errno));
65 ITRACE("Hyper DmaBuf: open hyper dmabuf device node %s successfully!",
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);
75 "IOCTL_HYPER_DMABUF_TX_CH_SETUP failed with error %d\n",
77 close(mHyperDmaBuf_Fd);
80 ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_TX_CH_SETUP Done!\n");
83 hyper_dmabuf_initialized = true;
86 VirtualPanoramaDisplay::~VirtualPanoramaDisplay() {
87 if (acquire_fence_ > 0) {
88 close(acquire_fence_);
93 temp.handle_ = handle_;
94 resource_manager_->MarkResourceForDeletion(temp, false);
97 delete output_handle_;
98 std::vector<OverlayLayer>().swap(in_flight_layers_);
100 resource_manager_->PurgeBuffer();
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;
108 msg.hid = it->second.hyper_dmabuf_id;
109 // Todo: find a reduced dmabuf free delay time
111 ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
115 "IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d [0x%x]\n",
116 ret, it->second.hyper_dmabuf_id.id);
118 ITRACE("Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
119 it->second.hyper_dmabuf_id.id);
120 mHyperDmaExportedBuffers.erase(it);
124 close(mHyperDmaBuf_Fd);
125 mHyperDmaBuf_Fd = -1;
130 void VirtualPanoramaDisplay::InitVirtualDisplay(uint32_t width,
137 bool VirtualPanoramaDisplay::GetActiveConfig(uint32_t *config) {
145 bool VirtualPanoramaDisplay::SetActiveConfig(uint32_t /*config*/) {
149 void VirtualPanoramaDisplay::HyperDmaExport() {
150 #ifdef HYPER_DMABUF_SHARING
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);
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;
164 header.n_buffers = 1;
166 header.output = display_index_;
167 header.counter = frame_count_++;
168 header.disp_w = width_;
169 header.disp_h = height_;
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;
178 if (buffer == NULL) {
179 buffer = OverlayBuffer::CreateOverlayBuffer();
180 buffer->InitializeFromNativeHandle(output_handle_, resource_manager_.get(),
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();
209 msg.sz_priv = header_size + info_size;
210 msg.priv = meta_data;
212 /* TODO: add more flexibility here, instead of hardcoded domain 0*/
213 msg.remote_domain = 0;
214 msg.dmabuf_fd = buffer->GetPrimeFD();
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);
228 ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_EXPORT_REMOTE, &msg);
230 ETRACE("Hyper DmaBuf: Exporting hyper_dmabuf failed with error %d\n", ret);
234 resource_manager_->PreparePurgedResources();
236 std::vector<ResourceHandle> purged_gl_resources;
237 std::vector<MediaResourceHandle> purged_media_resources;
238 bool has_gpu_resource = false;
240 resource_manager_->GetPurgedResources(
241 purged_gl_resources, purged_media_resources, &has_gpu_resource);
243 size_t purged_size = purged_gl_resources.size();
245 if (purged_size != 0) {
246 const NativeBufferHandler *handler =
247 resource_manager_->GetNativeBufferHandler();
249 for (size_t i = 0; i < purged_size; i++) {
250 const ResourceHandle &handle = purged_gl_resources.at(i);
251 if (!handle.handle_) {
254 auto search = mHyperDmaExportedBuffers.find(
255 handle.handle_->imported_handle_->data[0]);
256 if (search != mHyperDmaExportedBuffers.end()) {
257 struct ioctl_hyper_dmabuf_unexport msg;
259 msg.hid = search->second.hyper_dmabuf_id;
261 ret = ioctl(mHyperDmaBuf_Fd, IOCTL_HYPER_DMABUF_UNEXPORT, &msg);
264 "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl failed %d "
266 ret, search->second.hyper_dmabuf_id.id);
269 "Hyper DmaBuf: IOCTL_HYPER_DMABUF_UNEXPORT ioctl Done [0x%x]!\n",
270 search->second.hyper_dmabuf_id.id);
272 mHyperDmaExportedBuffers.erase(search);
274 handler->ReleaseBuffer(handle.handle_);
275 handler->DestroyHandle(handle.handle_);
281 bool VirtualPanoramaDisplay::Present(std::vector<HwcLayer *> &source_layers,
282 int32_t *retire_fence,
283 PixelUploaderCallback * /*call_back*/,
284 bool handle_constraints) {
286 if (!hyper_dmabuf_initialized) {
290 std::vector<OverlayLayer> layers;
291 std::vector<HwcRect<int>> layers_rects;
292 std::vector<size_t> index;
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;
299 uint32_t z_order = 0;
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())
307 if (discard_protected_video_) {
308 if (layer->GetNativeHandle() != NULL &&
309 (layer->GetNativeHandle()->meta_data_.usage_ &
310 hwcomposer::kLayerProtected))
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));
321 handle_constraints = true;
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());
336 if (!previous_layer || overlay_layer.HasLayerContentChanged() ||
337 overlay_layer.HasDimensionsChanged()) {
338 layers_changed = true;
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);
356 in_flight_layers_.swap(layers);
359 int32_t fence = *retire_fence;
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));
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());
374 if (resource_manager_->PreparePurgedResources()) {
375 compositor_.FreeResources();
378 #ifdef HYPER_DMABUF_SHARING
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;
392 handler->CreateBuffer(width_, height_, DRM_FORMAT_BGRA8888, &native_handle,
393 usage, &modifier_used);
395 DTRACE("Create Buffer handler :%p", native_handle);
396 SetOutputBuffer(native_handle, -1);
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();
406 handler->ReleaseBuffer(handle_);
407 handler->DestroyHandle(handle_);
410 delete output_handle_;
411 output_handle_ = buffer;
414 if (output_handle_) {
415 handler->CopyHandle(output_handle_, &handle_);
419 if (acquire_fence_ > 0) {
420 close(acquire_fence_);
424 if (acquire_fence > 0) {
425 acquire_fence_ = dup(acquire_fence);
429 bool VirtualPanoramaDisplay::Initialize(
430 NativeBufferHandler * /*buffer_manager*/,
431 FrameBufferManager *frame_buffer_manager) {
435 bool VirtualPanoramaDisplay::GetDisplayAttribute(uint32_t /*config*/,
436 HWCDisplayAttribute attribute,
438 // We always get the values from preferred mode config.
440 case HWCDisplayAttribute::kWidth:
443 case HWCDisplayAttribute::kHeight:
446 case HWCDisplayAttribute::kRefreshRate:
450 case HWCDisplayAttribute::kDpiX:
451 // Dots per 1000 inches
454 case HWCDisplayAttribute::kDpiY:
455 // Dots per 1000 inches
466 bool VirtualPanoramaDisplay::GetDisplayConfigs(uint32_t *num_configs,
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();
487 *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
488 strncpy(name, string.c_str(), *size);
492 int VirtualPanoramaDisplay::GetDisplayPipe() {
496 bool VirtualPanoramaDisplay::SetPowerMode(uint32_t /*power_mode*/) {
500 int VirtualPanoramaDisplay::RegisterVsyncCallback(
501 std::shared_ptr<VsyncCallback> /*callback*/, uint32_t /*display_id*/) {
506 void VirtualPanoramaDisplay::VSyncControl(bool /*enabled*/) {
509 bool VirtualPanoramaDisplay::CheckPlaneFormat(uint32_t /*format*/) {
510 // assuming that virtual display supports the format
513 } // namespace hwcomposer