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 32 Output::Output(const CompositionEngine& compositionEngine) 33 : mCompositionEngine(compositionEngine) {} 34 35 Output::~Output() = default; 36 37 const CompositionEngine& Output::getCompositionEngine() const { 38 return mCompositionEngine; 39 } 40 41 bool Output::isValid() const { 42 return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface && 43 mRenderSurface->isValid(); 44 } 45 46 const std::string& Output::getName() const { 47 return mName; 48 } 49 50 void Output::setName(const std::string& name) { 51 mName = name; 52 } 53 54 void Output::setCompositionEnabled(bool enabled) { 55 if (mState.isEnabled == enabled) { 56 return; 57 } 58 59 mState.isEnabled = enabled; 60 dirtyEntireOutput(); 61 } 62 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. 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 84 void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) { 85 mState.layerStackId = layerStackId; 86 mState.layerStackInternal = isInternal; 87 88 dirtyEntireOutput(); 89 } 90 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 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 126 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 136 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 160 compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const { 161 return mDisplayColorProfile.get(); 162 } 163 164 void Output::setDisplayColorProfile(std::unique_ptr<compositionengine::DisplayColorProfile> mode) { 165 mDisplayColorProfile = std::move(mode); 166 } 167 168 void Output::setDisplayColorProfileForTest( 169 std::unique_ptr<compositionengine::DisplayColorProfile> mode) { 170 mDisplayColorProfile = std::move(mode); 171 } 172 173 compositionengine::RenderSurface* Output::getRenderSurface() const { 174 return mRenderSurface.get(); 175 } 176 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 184 void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> surface) { 185 mRenderSurface = std::move(surface); 186 } 187 188 const OutputCompositionState& Output::getState() const { 189 return mState; 190 } 191 192 OutputCompositionState& Output::editState() { 193 return mState; 194 } 195 196 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 204 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 210 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 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 231 void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) { 232 mOutputLayersOrderedByZ = std::move(layers); 233 } 234 235 const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const { 236 return mOutputLayersOrderedByZ; 237 } 238 239 void Output::dirtyEntireOutput() { 240 mState.dirtyRegion.set(mState.bounds); 241 } 242 243 } // namespace impl 244 } // namespace android::compositionengine 245