1 /*
2 * Copyright Samsung Electronics Co.,LTD.
3 * Copyright (C) 2016 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <algorithm>
19
20 #include <log/log.h>
21
22 #include <hardware/exynos/acryl.h>
23
24 #include "acrylic_internal.h"
25
Acrylic(const HW2DCapability & capability)26 Acrylic::Acrylic(const HW2DCapability &capability)
27 : mCapability(capability), mHasBackgroundColor(false),
28 mMaxTargetLuminance(100), mMinTargetLuminance(0), mTargetDisplayInfo(nullptr),
29 mCanvas(this, AcrylicCanvas::CANVAS_TARGET)
30 {
31 ALOGD_TEST("Created a new Acrylic on %p", this);
32 }
33
~Acrylic()34 Acrylic::~Acrylic()
35 {
36 mCanvas.disconnectLayer();
37
38 for (auto layer: mLayers) {
39 layer->disconnectLayer();
40 removeTransitData(layer);
41 }
42
43 ALOGD_TEST("Destroyed Acrylic on %p", this);
44 }
45
createLayer()46 AcrylicLayer *Acrylic::createLayer()
47 {
48 if (mLayers.size() >= getCapabilities().maxLayerCount()) {
49 ALOGE("Full of composit layer: current %zu, max %u",
50 mLayers.size() , getCapabilities().maxLayerCount());
51 return NULL;
52 }
53
54 auto *layer = new AcrylicLayer(this);
55 if (!layer) {
56 ALOGE("Failed to create a new compositing layer");
57 return NULL;
58 }
59
60 mLayers.push_back(layer);
61
62 ALOGD_TEST("A new Acrylic layer is created. Total %zd layers", mLayers.size());
63
64 return layer;
65 }
66
removeLayer(AcrylicLayer * layer)67 void Acrylic::removeLayer(AcrylicLayer *layer)
68 {
69 auto it = find(std::begin(mLayers), std::end(mLayers), layer);
70
71 if (it == std::end(mLayers)) {
72 ALOGE("Deleting an unregistered layer");
73 } else {
74 removeTransitData(*it);
75 mLayers.erase(it);
76 }
77 }
78
prioritize(int priority)79 int Acrylic::prioritize(int priority)
80 {
81 if ((priority < -1) || (priority > 15)) {
82 ALOGE("Invalid priority %d", priority);
83 return -1;
84 }
85
86 return 0;
87 }
88
requestPerformanceQoS(AcrylicPerformanceRequest __unused * request)89 bool Acrylic::requestPerformanceQoS(AcrylicPerformanceRequest __unused *request)
90 {
91 return true;
92 }
93
setHDRToneMapCoefficients(uint32_t __unused * matrix[2],int __unused num_elements)94 bool Acrylic::setHDRToneMapCoefficients(uint32_t __unused *matrix[2], int __unused num_elements)
95 {
96 return true;
97 }
98
validateAllLayers()99 bool Acrylic::validateAllLayers()
100 {
101 const HW2DCapability &cap = getCapabilities();
102
103 if (!mCanvas.isSettingOkay()) {
104 ALOGE("Incomplete settting (flags: %#x) on the target layer",
105 mCanvas.getSettingFlags());
106 return false;
107 }
108
109 if (mCanvas.isCompressed() && !cap.isFeatureSupported(HW2DCapability::FEATURE_AFBC_ENCODE)) {
110 ALOGE("AFBC encoding is not supported");
111 return false;
112 }
113
114 if (mCanvas.isUOrder() && !cap.isFeatureSupported(HW2DCapability::FEATURE_UORDER_WRITE)) {
115 ALOGE("Writing in U-Order is not supported");
116 return false;
117 }
118
119 bool prot = false;
120 hw2d_rect_t rect;
121 hw2d_coord_t xy = mCanvas.getImageDimension();
122
123 for (auto layer: mLayers) {
124 if (!layer->isSettingOkay()) {
125 ALOGE("Incomplete settting (flags: %#x) on a layer of %zu layers",
126 layer->getSettingFlags(), mLayers.size());
127 return false;
128 }
129
130 if (layer->isCompressed() && !cap.isFeatureSupported(HW2DCapability::FEATURE_AFBC_DECODE)) {
131 ALOGE("AFBC decoding is not supported");
132 return false;
133 }
134
135 if (layer->isUOrder() && !cap.isFeatureSupported(HW2DCapability::FEATURE_UORDER_READ)) {
136 ALOGE("Reading a texture in U-Order is not supported");
137 return false;
138 }
139
140 if ((layer->getPlaneAlpha() != 255) && !cap.isFeatureSupported(HW2DCapability::FEATURE_PLANE_ALPHA)) {
141 ALOGE("Plane alpha is not supported but given %u for plane alpha", layer->getPlaneAlpha());
142 return false;
143 }
144
145 rect = layer->getTargetRect();
146 if (area_is_zero(rect)) {
147 // If no target area is specified to a source layer,
148 // the entire region of the target image becomes the target area.
149 // Then, check the scaling capability
150 hw2d_rect_t ir = layer->getImageRect();
151 if (!!(layer->getCompositAttr() & AcrylicLayer::ATTR_NORESAMPLING)) {
152 if (!cap.supportedResizing(ir.size, xy, layer->getTransform())) {
153 ALOGE("Unsupported resizing from %dx%d@(%d,%d) --> Target %dx%d with transform %d",
154 ir.size.hori, ir.size.vert, ir.pos.hori, ir.pos.vert,
155 xy.hori, xy.vert, layer->getTransform());
156 return false;
157 }
158 } else {
159 if (!cap.supportedResampling(ir.size, xy, layer->getTransform())) {
160 ALOGE("Unsupported scaling from %dx%d@(%d,%d) --> Target %dx%d with transform %d",
161 ir.size.hori, ir.size.vert, ir.pos.hori, ir.pos.vert,
162 xy.hori, xy.vert, layer->getTransform());
163 return false;
164 }
165 }
166 } else if (rect > xy) {
167 ALOGE("Target area %dx%d@(%d,%d) of a layer of %zu layers is out of bound (%dx%d)",
168 rect.size.hori, rect.size.vert, rect.pos.hori, rect.pos.vert,
169 mLayers.size(), xy.hori, xy.vert);
170 return false;
171 }
172
173 prot = prot || layer->isProtected();
174 }
175
176 if (prot && !mCanvas.isProtected()) {
177 ALOGE("Target image is not protected while a source layer is protected");
178 return false;
179 }
180
181 return true;
182 }
183
sortLayers()184 void Acrylic::sortLayers()
185 {
186 std::sort(std::begin(mLayers), std::end(mLayers), [] (auto l1, auto l2) { return l1->getZOrder() < l2->getZOrder(); });
187 }
188