1 /*
2  * Copyright 2019 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 #include <android-base/stringprintf.h>
18 #include <compositionengine/CompositionEngine.h>
19 #include <compositionengine/DisplayColorProfile.h>
20 #include <compositionengine/LayerFE.h>
21 #include <compositionengine/RenderSurface.h>
22 #include <compositionengine/impl/Output.h>
23 #include <compositionengine/impl/OutputLayer.h>
24 #include <ui/DebugUtils.h>
25 
26 namespace android::compositionengine {
27 
28 Output::~Output() = default;
29 
30 namespace impl {
31 
Output(const CompositionEngine & compositionEngine)32 Output::Output(const CompositionEngine& compositionEngine)
33       : mCompositionEngine(compositionEngine) {}
34 
35 Output::~Output() = default;
36 
getCompositionEngine() const37 const CompositionEngine& Output::getCompositionEngine() const {
38     return mCompositionEngine;
39 }
40 
isValid() const41 bool Output::isValid() const {
42     return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface &&
43             mRenderSurface->isValid();
44 }
45 
getName() const46 const std::string& Output::getName() const {
47     return mName;
48 }
49 
setName(const std::string & name)50 void Output::setName(const std::string& name) {
51     mName = name;
52 }
53 
setCompositionEnabled(bool enabled)54 void Output::setCompositionEnabled(bool enabled) {
55     if (mState.isEnabled == enabled) {
56         return;
57     }
58 
59     mState.isEnabled = enabled;
60     dirtyEntireOutput();
61 }
62 
setProjection(const ui::Transform & transform,int32_t orientation,const Rect & frame,const Rect & viewport,const Rect & scissor,bool needsFiltering)63 void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame,
64                            const Rect& viewport, const Rect& scissor, bool needsFiltering) {
65     mState.transform = transform;
66     mState.orientation = orientation;
67     mState.scissor = scissor;
68     mState.frame = frame;
69     mState.viewport = viewport;
70     mState.needsFiltering = needsFiltering;
71 
72     dirtyEntireOutput();
73 }
74 
75 // TODO(lpique): Rename setSize() once more is moved.
setBounds(const ui::Size & size)76 void Output::setBounds(const ui::Size& size) {
77     mRenderSurface->setDisplaySize(size);
78     // TODO(lpique): Rename mState.size once more is moved.
79     mState.bounds = Rect(mRenderSurface->getSize());
80 
81     dirtyEntireOutput();
82 }
83 
setLayerStackFilter(uint32_t layerStackId,bool isInternal)84 void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
85     mState.layerStackId = layerStackId;
86     mState.layerStackInternal = isInternal;
87 
88     dirtyEntireOutput();
89 }
90 
setColorTransform(const mat4 & transform)91 void Output::setColorTransform(const mat4& transform) {
92     if (mState.colorTransformMat == transform) {
93         return;
94     }
95 
96     const bool isIdentity = (transform == mat4());
97     const auto newColorTransform =
98             isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
99 
100     mState.colorTransform = newColorTransform;
101     mState.colorTransformMat = transform;
102 
103     dirtyEntireOutput();
104 }
105 
setColorMode(ui::ColorMode mode,ui::Dataspace dataspace,ui::RenderIntent renderIntent)106 void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
107                           ui::RenderIntent renderIntent) {
108     if (mState.colorMode == mode && mState.dataspace == dataspace &&
109         mState.renderIntent == renderIntent) {
110         return;
111     }
112 
113     mState.colorMode = mode;
114     mState.dataspace = dataspace;
115     mState.renderIntent = renderIntent;
116 
117     mRenderSurface->setBufferDataspace(dataspace);
118 
119     ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
120           decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
121           renderIntent);
122 
123     dirtyEntireOutput();
124 }
125 
dump(std::string & out) const126 void Output::dump(std::string& out) const {
127     using android::base::StringAppendF;
128 
129     StringAppendF(&out, "   Composition Output State: [\"%s\"]", mName.c_str());
130 
131     out.append("\n   ");
132 
133     dumpBase(out);
134 }
135 
dumpBase(std::string & out) const136 void Output::dumpBase(std::string& out) const {
137     mState.dump(out);
138 
139     if (mDisplayColorProfile) {
140         mDisplayColorProfile->dump(out);
141     } else {
142         out.append("    No display color profile!\n");
143     }
144 
145     if (mRenderSurface) {
146         mRenderSurface->dump(out);
147     } else {
148         out.append("    No render surface!\n");
149     }
150 
151     android::base::StringAppendF(&out, "\n   %zu Layers\b", mOutputLayersOrderedByZ.size());
152     for (const auto& outputLayer : mOutputLayersOrderedByZ) {
153         if (!outputLayer) {
154             continue;
155         }
156         outputLayer->dump(out);
157     }
158 }
159 
getDisplayColorProfile() const160 compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
161     return mDisplayColorProfile.get();
162 }
163 
setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode)164 void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
165     mDisplayColorProfile = std::move(mode);
166 }
167 
setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile> mode)168 void Output::setDisplayColorProfileForTest(
169         std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
170     mDisplayColorProfile = std::move(mode);
171 }
172 
getRenderSurface() const173 compositionengine::RenderSurface* Output::getRenderSurface() const {
174     return mRenderSurface.get();
175 }
176 
setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface)177 void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
178     mRenderSurface = std::move(surface);
179     mState.bounds = Rect(mRenderSurface->getSize());
180 
181     dirtyEntireOutput();
182 }
183 
setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface)184 void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) {
185     mRenderSurface = std::move(surface);
186 }
187 
getState() const188 const OutputCompositionState& Output::getState() const {
189     return mState;
190 }
191 
editState()192 OutputCompositionState& Output::editState() {
193     return mState;
194 }
195 
getDirtyRegion(bool repaintEverything) const196 Region Output::getDirtyRegion(bool repaintEverything) const {
197     Region dirty(mState.viewport);
198     if (!repaintEverything) {
199         dirty.andSelf(mState.dirtyRegion);
200     }
201     return dirty;
202 }
203 
belongsInOutput(uint32_t layerStackId,bool internalOnly) const204 bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
205     // The layerStackId's must match, and also the layer must not be internal
206     // only when not on an internal output.
207     return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
208 }
209 
getOutputLayerForLayer(compositionengine::Layer * layer) const210 compositionengine::OutputLayer* Output::getOutputLayerForLayer(
211         compositionengine::Layer* layer) const {
212     for (const auto& outputLayer : mOutputLayersOrderedByZ) {
213         if (outputLayer && &outputLayer->getLayer() == layer) {
214             return outputLayer.get();
215         }
216     }
217     return nullptr;
218 }
219 
getOrCreateOutputLayer(std::optional<DisplayId> displayId,std::shared_ptr<compositionengine::Layer> layer,sp<compositionengine::LayerFE> layerFE)220 std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
221         std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
222         sp<compositionengine::LayerFE> layerFE) {
223     for (auto& outputLayer : mOutputLayersOrderedByZ) {
224         if (outputLayer && &outputLayer->getLayer() == layer.get()) {
225             return std::move(outputLayer);
226         }
227     }
228     return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE);
229 }
230 
setOutputLayersOrderedByZ(OutputLayers && layers)231 void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
232     mOutputLayersOrderedByZ = std::move(layers);
233 }
234 
getOutputLayersOrderedByZ() const235 const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
236     return mOutputLayersOrderedByZ;
237 }
238 
dirtyEntireOutput()239 void Output::dirtyEntireOutput() {
240     mState.dirtyRegion.set(mState.bounds);
241 }
242 
243 } // namespace impl
244 } // namespace android::compositionengine
245