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-display-composition" 18 19 #include "drmdisplaycomposition.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 #include <xf86drmMode.h> 30 31 namespace android { 32 33 DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) { 34 memset(&layer, 0, sizeof(layer)); 35 layer.acquireFenceFd = -1; 36 memset(&bo, 0, sizeof(bo)); 37 } 38 39 DrmCompositionLayer::~DrmCompositionLayer() { 40 } 41 42 DrmDisplayComposition::DrmDisplayComposition() 43 : drm_(NULL), 44 importer_(NULL), 45 type_(DRM_COMPOSITION_TYPE_EMPTY), 46 timeline_fd_(-1), 47 timeline_(0), 48 dpms_mode_(DRM_MODE_DPMS_ON) { 49 } 50 51 DrmDisplayComposition::~DrmDisplayComposition() { 52 for (DrmCompositionLayerVector_t::iterator iter = layers_.begin(); 53 iter != layers_.end(); ++iter) { 54 if (importer_) 55 importer_->ReleaseBuffer(&iter->bo); 56 57 if (iter->layer.acquireFenceFd >= 0) 58 close(iter->layer.acquireFenceFd); 59 } 60 61 if (timeline_fd_ >= 0) 62 close(timeline_fd_); 63 } 64 65 int DrmDisplayComposition::Init(DrmResources *drm, Importer *importer) { 66 drm_ = drm; 67 importer_ = importer; 68 69 int ret = sw_sync_timeline_create(); 70 if (ret < 0) { 71 ALOGE("Failed to create sw sync timeline %d", ret); 72 return ret; 73 } 74 timeline_fd_ = ret; 75 return 0; 76 } 77 78 DrmCompositionType DrmDisplayComposition::type() const { 79 return type_; 80 } 81 82 bool DrmDisplayComposition::validate_composition_type(DrmCompositionType des) { 83 return type_ == DRM_COMPOSITION_TYPE_EMPTY || type_ == des; 84 } 85 86 int DrmDisplayComposition::AddLayer(hwc_layer_1_t *layer, hwc_drm_bo_t *bo, 87 DrmCrtc *crtc, DrmPlane *plane) { 88 if (layer->transform != 0) 89 return -EINVAL; 90 91 if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME)) 92 return -EINVAL; 93 94 ++timeline_; 95 layer->releaseFenceFd = 96 sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_); 97 if (layer->releaseFenceFd < 0) { 98 ALOGE("Could not create release fence %d", layer->releaseFenceFd); 99 return layer->releaseFenceFd; 100 } 101 102 DrmCompositionLayer_t c_layer; 103 c_layer.layer = *layer; 104 c_layer.bo = *bo; 105 c_layer.crtc = crtc; 106 c_layer.plane = plane; 107 108 layer->acquireFenceFd = -1; // We own this now 109 layers_.push_back(c_layer); 110 type_ = DRM_COMPOSITION_TYPE_FRAME; 111 return 0; 112 } 113 114 int DrmDisplayComposition::AddDpmsMode(uint32_t dpms_mode) { 115 if (!validate_composition_type(DRM_COMPOSITION_TYPE_DPMS)) 116 return -EINVAL; 117 dpms_mode_ = dpms_mode; 118 type_ = DRM_COMPOSITION_TYPE_DPMS; 119 return 0; 120 } 121 122 int DrmDisplayComposition::FinishComposition() { 123 int ret = sw_sync_timeline_inc(timeline_fd_, timeline_); 124 if (ret) 125 ALOGE("Failed to increment sync timeline %d", ret); 126 127 return ret; 128 } 129 130 DrmCompositionLayerVector_t *DrmDisplayComposition::GetCompositionLayers() { 131 return &layers_; 132 } 133 134 uint32_t DrmDisplayComposition::dpms_mode() const { 135 return dpms_mode_; 136 } 137 } 138