2 * Copyright (C) 2015 The Android Open Source Project
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 #define LOG_TAG "hwc-drm-compositor"
19 #include "drmcompositor.h"
22 #include "drmresources.h"
27 #include <cutils/log.h>
28 #include <sync/sync.h>
32 DrmCompositor::DrmCompositor(DrmResources *drm)
35 active_composition_(NULL),
40 DrmCompositor::~DrmCompositor() {
42 pthread_mutex_destroy(&lock_);
45 int DrmCompositor::Init() {
46 int ret = pthread_mutex_init(&lock_, NULL);
48 ALOGE("Failed to initialize drm compositor lock %d\n", ret);
53 pthread_mutex_destroy(&lock_);
54 ALOGE("Failed to initialize compositor worker %d\n", ret);
62 Composition *DrmCompositor::CreateComposition(Importer *importer) {
63 DrmComposition *composition = new DrmComposition(drm_, importer, frame_no_++);
65 ALOGE("Failed to allocate drm composition");
68 int ret = composition->Init();
70 ALOGE("Failed to initialize drm composition %d", ret);
77 int DrmCompositor::QueueComposition(Composition *composition) {
78 int ret = pthread_mutex_lock(&lock_);
80 ALOGE("Failed to acquire compositor lock %d", ret);
84 composite_queue_.push((DrmComposition *)composition);
86 ret = pthread_mutex_unlock(&lock_);
88 ALOGE("Failed to release compositor lock %d", ret);
96 int DrmCompositor::PerformModeset(DrmCompositionLayerMap_t::iterator begin,
97 DrmCompositionLayerMap_t::iterator end) {
98 DrmCompositionLayer *layer = NULL;
99 for (DrmCompositionLayerMap_t::iterator iter = begin; iter != end; ++iter) {
100 if (iter->second.layer.compositionType == HWC_FRAMEBUFFER_TARGET) {
101 layer = &iter->second;
105 int display = begin->first;
107 ALOGE("Could not find target framebuffer for display %d", display);
112 DrmConnector *connector = drm_->GetConnectorForDisplay(display);
113 connector->active_mode().ToModeModeInfo(&m);
115 uint32_t connectors = connector->id();
116 int ret = drmModeSetCrtc(drm_->fd(), layer->crtc->id(), layer->bo.fb_id, 0, 0,
119 ALOGE("Failed set crtc for disp %d/%d", display, ret);
121 layer->crtc->set_requires_modeset(false);
126 int DrmCompositor::CompositeDisplay(DrmCompositionLayerMap_t::iterator begin,
127 DrmCompositionLayerMap_t::iterator end) {
129 // Wait for all acquire fences to signal
130 for (DrmCompositionLayerMap_t::iterator iter = begin; iter != end; ++iter) {
131 hwc_layer_1_t *layer = &iter->second.layer;
133 if (layer->acquireFenceFd < 0)
136 ret = sync_wait(layer->acquireFenceFd, -1);
138 ALOGE("Failed to wait for acquire %d/%d", layer->acquireFenceFd, ret);
141 close(layer->acquireFenceFd);
142 layer->acquireFenceFd = -1;
145 DrmCrtc *crtc = begin->second.crtc;
146 if (crtc->requires_modeset()) {
147 ret = PerformModeset(begin, end);
149 ALOGE("Failed modeset on display %d", begin->first);
153 drmModePropertySetPtr pset = drmModePropertySetAlloc();
155 ALOGE("Failed to allocate property set");
159 for (DrmCompositionLayerMap_t::iterator iter = begin; iter != end; ++iter) {
160 DrmCompositionLayer_t *comp = &iter->second;
161 hwc_layer_1_t *layer = &comp->layer;
162 DrmPlane *plane = comp->plane;
165 drmModePropertySetAdd(pset, plane->id(), plane->crtc_property().id(),
167 drmModePropertySetAdd(pset, plane->id(), plane->fb_property().id(),
169 drmModePropertySetAdd(pset, plane->id(), plane->crtc_x_property().id(),
170 layer->displayFrame.left) ||
171 drmModePropertySetAdd(pset, plane->id(), plane->crtc_y_property().id(),
172 layer->displayFrame.top) ||
173 drmModePropertySetAdd(
174 pset, plane->id(), plane->crtc_w_property().id(),
175 layer->displayFrame.right - layer->displayFrame.left) ||
176 drmModePropertySetAdd(
177 pset, plane->id(), plane->crtc_h_property().id(),
178 layer->displayFrame.bottom - layer->displayFrame.top) ||
179 drmModePropertySetAdd(pset, plane->id(), plane->src_x_property().id(),
180 layer->sourceCropf.left) ||
181 drmModePropertySetAdd(pset, plane->id(), plane->src_y_property().id(),
182 layer->sourceCropf.top) ||
183 drmModePropertySetAdd(
184 pset, plane->id(), plane->src_w_property().id(),
185 (int)(layer->sourceCropf.right - layer->sourceCropf.left) << 16) ||
186 drmModePropertySetAdd(
187 pset, plane->id(), plane->src_h_property().id(),
188 (int)(layer->sourceCropf.bottom - layer->sourceCropf.top) << 16);
190 ALOGE("Failed to add plane %d to set", plane->id());
196 ret = drmModePropertySetCommit(drm_->fd(), 0, drm_, pset);
198 ALOGE("Failed to commit pset ret=%d\n", ret);
201 drmModePropertySetFree(pset);
206 int DrmCompositor::Composite() {
207 int ret = pthread_mutex_lock(&lock_);
209 ALOGE("Failed to acquire compositor lock %d", ret);
212 if (composite_queue_.empty()) {
213 ret = pthread_mutex_unlock(&lock_);
215 ALOGE("Failed to release compositor lock %d", ret);
219 DrmComposition *composition = composite_queue_.front();
220 composite_queue_.pop();
222 ret = pthread_mutex_unlock(&lock_);
224 ALOGE("Failed to release compositor lock %d", ret);
228 DrmCompositionLayerMap_t *map = composition->GetCompositionMap();
229 for (DrmResources::ConnectorIter iter = drm_->begin_connectors();
230 iter != drm_->end_connectors(); ++iter) {
231 int display = (*iter)->display();
232 std::pair<DrmCompositionLayerMap_t::iterator,
233 DrmCompositionLayerMap_t::iterator> layer_iters =
234 map->equal_range(display);
236 if (layer_iters.first != layer_iters.second) {
237 ret = CompositeDisplay(layer_iters.first, layer_iters.second);
239 ALOGE("Composite failed for display %d:", display);
245 if (active_composition_) {
246 active_composition_->FinishComposition();
247 delete active_composition_;
249 active_composition_ = composition;
253 bool DrmCompositor::HaveQueuedComposites() const {
254 int ret = pthread_mutex_lock(&lock_);
256 ALOGE("Failed to acquire compositor lock %d", ret);
260 bool empty_ret = !composite_queue_.empty();
262 ret = pthread_mutex_unlock(&lock_);
264 ALOGE("Failed to release compositor lock %d", ret);