/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include namespace android::compositionengine { Output::~Output() = default; namespace impl { Output::Output(const CompositionEngine& compositionEngine) : mCompositionEngine(compositionEngine) {} Output::~Output() = default; const CompositionEngine& Output::getCompositionEngine() const { return mCompositionEngine; } bool Output::isValid() const { return mDisplayColorProfile && mDisplayColorProfile->isValid() && mRenderSurface && mRenderSurface->isValid(); } const std::string& Output::getName() const { return mName; } void Output::setName(const std::string& name) { mName = name; } void Output::setCompositionEnabled(bool enabled) { if (mState.isEnabled == enabled) { return; } mState.isEnabled = enabled; dirtyEntireOutput(); } void Output::setProjection(const ui::Transform& transform, int32_t orientation, const Rect& frame, const Rect& viewport, const Rect& scissor, bool needsFiltering) { mState.transform = transform; mState.orientation = orientation; mState.scissor = scissor; mState.frame = frame; mState.viewport = viewport; mState.needsFiltering = needsFiltering; dirtyEntireOutput(); } // TODO(lpique): Rename setSize() once more is moved. void Output::setBounds(const ui::Size& size) { mRenderSurface->setDisplaySize(size); // TODO(lpique): Rename mState.size once more is moved. mState.bounds = Rect(mRenderSurface->getSize()); dirtyEntireOutput(); } void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) { mState.layerStackId = layerStackId; mState.layerStackInternal = isInternal; dirtyEntireOutput(); } void Output::setColorTransform(const mat4& transform) { if (mState.colorTransformMat == transform) { return; } const bool isIdentity = (transform == mat4()); const auto newColorTransform = isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX; mState.colorTransform = newColorTransform; mState.colorTransformMat = transform; dirtyEntireOutput(); } void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) { if (mState.colorMode == mode && mState.dataspace == dataspace && mState.renderIntent == renderIntent) { return; } mState.colorMode = mode; mState.dataspace = dataspace; mState.renderIntent = renderIntent; mRenderSurface->setBufferDataspace(dataspace); ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)", decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), renderIntent); dirtyEntireOutput(); } void Output::dump(std::string& out) const { using android::base::StringAppendF; StringAppendF(&out, " Composition Output State: [\"%s\"]", mName.c_str()); out.append("\n "); dumpBase(out); } void Output::dumpBase(std::string& out) const { mState.dump(out); if (mDisplayColorProfile) { mDisplayColorProfile->dump(out); } else { out.append(" No display color profile!\n"); } if (mRenderSurface) { mRenderSurface->dump(out); } else { out.append(" No render surface!\n"); } android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size()); for (const auto& outputLayer : mOutputLayersOrderedByZ) { if (!outputLayer) { continue; } outputLayer->dump(out); } } compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const { return mDisplayColorProfile.get(); } void Output::setDisplayColorProfile(std::unique_ptr mode) { mDisplayColorProfile = std::move(mode); } void Output::setDisplayColorProfileForTest( std::unique_ptr mode) { mDisplayColorProfile = std::move(mode); } compositionengine::RenderSurface* Output::getRenderSurface() const { return mRenderSurface.get(); } void Output::setRenderSurface(std::unique_ptr surface) { mRenderSurface = std::move(surface); mState.bounds = Rect(mRenderSurface->getSize()); dirtyEntireOutput(); } void Output::setRenderSurfaceForTest(std::unique_ptr surface) { mRenderSurface = std::move(surface); } const OutputCompositionState& Output::getState() const { return mState; } OutputCompositionState& Output::editState() { return mState; } Region Output::getDirtyRegion(bool repaintEverything) const { Region dirty(mState.viewport); if (!repaintEverything) { dirty.andSelf(mState.dirtyRegion); } return dirty; } bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const { // The layerStackId's must match, and also the layer must not be internal // only when not on an internal output. return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal); } compositionengine::OutputLayer* Output::getOutputLayerForLayer( compositionengine::Layer* layer) const { for (const auto& outputLayer : mOutputLayersOrderedByZ) { if (outputLayer && &outputLayer->getLayer() == layer) { return outputLayer.get(); } } return nullptr; } std::unique_ptr Output::getOrCreateOutputLayer( std::optional displayId, std::shared_ptr layer, sp layerFE) { for (auto& outputLayer : mOutputLayersOrderedByZ) { if (outputLayer && &outputLayer->getLayer() == layer.get()) { return std::move(outputLayer); } } return createOutputLayer(mCompositionEngine, displayId, *this, layer, layerFE); } void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) { mOutputLayersOrderedByZ = std::move(layers); } const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const { return mOutputLayersOrderedByZ; } void Output::dirtyEntireOutput() { mState.dirtyRegion.set(mState.bounds); } } // namespace impl } // namespace android::compositionengine