OSDN Git Service

Merge "drm_hwcomposer: Add Dump() to the Compositor interface" into mnc-dev
[android-x86/external-drm_hwcomposer.git] / drmcomposition.cpp
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
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 #define LOG_TAG "hwc-drm-composition"
18
19 #include "drmcomposition.h"
20 #include "drmcrtc.h"
21 #include "drmplane.h"
22 #include "drmresources.h"
23
24 #include <stdlib.h>
25
26 #include <cutils/log.h>
27 #include <sw_sync.h>
28 #include <sync/sync.h>
29
30 namespace android {
31
32 static const bool kUseOverlayPlanes = false;
33
34 DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) {
35   memset(&layer, 0, sizeof(layer));
36   layer.acquireFenceFd = -1;
37   memset(&bo, 0, sizeof(bo));
38 }
39
40 DrmCompositionLayer::~DrmCompositionLayer() {
41 }
42
43 DrmComposition::DrmComposition(DrmResources *drm, Importer *importer,
44                                uint64_t frame_no)
45     : drm_(drm),
46       importer_(importer),
47       frame_no_(frame_no),
48       timeline_fd_(-1),
49       timeline_(0) {
50   for (DrmResources::PlaneIter iter = drm_->begin_planes();
51        iter != drm_->end_planes(); ++iter) {
52     if ((*iter)->type() == DRM_PLANE_TYPE_PRIMARY)
53       primary_planes_.push_back(*iter);
54     else if (kUseOverlayPlanes && (*iter)->type() == DRM_PLANE_TYPE_OVERLAY)
55       overlay_planes_.push_back(*iter);
56   }
57 }
58
59 DrmComposition::~DrmComposition() {
60   for (DrmCompositionLayerMap_t::iterator iter = composition_map_.begin();
61        iter != composition_map_.end(); ++iter) {
62     importer_->ReleaseBuffer(&iter->second.bo);
63
64     if (iter->second.layer.acquireFenceFd >= 0)
65       close(iter->second.layer.acquireFenceFd);
66   }
67
68   if (timeline_fd_ >= 0)
69     close(timeline_fd_);
70 }
71
72 int DrmComposition::Init() {
73   int ret = sw_sync_timeline_create();
74   if (ret < 0) {
75     ALOGE("Failed to create sw sync timeline %d", ret);
76     return ret;
77   }
78   timeline_fd_ = ret;
79   return 0;
80 }
81
82 unsigned DrmComposition::GetRemainingLayers(int display,
83                                             unsigned num_needed) const {
84   DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
85   if (!crtc) {
86     ALOGW("Failed to find crtc for display %d", display);
87     return 0;
88   }
89
90   unsigned num_planes = 0;
91   for (std::vector<DrmPlane *>::const_iterator iter = primary_planes_.begin();
92        iter != primary_planes_.end(); ++iter) {
93     if ((*iter)->GetCrtcSupported(*crtc))
94       ++num_planes;
95   }
96   for (std::deque<DrmPlane *>::const_iterator iter = overlay_planes_.begin();
97        iter != overlay_planes_.end(); ++iter) {
98     if ((*iter)->GetCrtcSupported(*crtc))
99       ++num_planes;
100   }
101   return std::min(num_planes, num_needed);
102 }
103
104 int DrmComposition::AddLayer(int display, hwc_layer_1_t *layer,
105                              hwc_drm_bo *bo) {
106   if (layer->transform != 0)
107     return -EINVAL;
108
109   DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
110   if (!crtc) {
111     ALOGE("Could not find crtc for display %d", display);
112     return -ENODEV;
113   }
114
115   ++timeline_;
116   layer->releaseFenceFd =
117       sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
118   if (layer->releaseFenceFd < 0) {
119     ALOGE("Could not create release fence %d", layer->releaseFenceFd);
120     return layer->releaseFenceFd;
121   }
122
123   DrmCompositionLayer_t c_layer;
124   c_layer.layer = *layer;
125   c_layer.bo = *bo;
126   c_layer.crtc = crtc;
127
128   // First try to find a primary plane for the layer, then fallback on overlays
129   for (std::vector<DrmPlane *>::iterator iter = primary_planes_.begin();
130        iter != primary_planes_.end(); ++iter) {
131     if ((*iter)->GetCrtcSupported(*crtc)) {
132       c_layer.plane = (*iter);
133       primary_planes_.erase(iter);
134       break;
135     }
136   }
137   for (std::deque<DrmPlane *>::iterator iter = overlay_planes_.begin();
138        !c_layer.plane && iter != overlay_planes_.end(); ++iter) {
139     if ((*iter)->GetCrtcSupported(*crtc)) {
140       c_layer.plane = (*iter);
141       overlay_planes_.erase(iter);
142       break;
143     }
144   }
145   if (!c_layer.plane) {
146     close(layer->releaseFenceFd);
147     layer->releaseFenceFd = -1;
148     return -ENOENT;
149   }
150
151   layer->acquireFenceFd = -1;  // We own this now
152   composition_map_.insert(DrmCompositionLayerPair_t(display, c_layer));
153   return 0;
154 }
155
156 int DrmComposition::FinishComposition() {
157   int ret = sw_sync_timeline_inc(timeline_fd_, timeline_);
158   if (ret)
159     ALOGE("Failed to increment sync timeline %d", ret);
160
161   return ret;
162 }
163
164 DrmCompositionLayerMap_t *DrmComposition::GetCompositionMap() {
165   return &composition_map_;
166 }
167 }