blob: 01b57819875c097d767de7fcc94ee113e63e471f [file] [log] [blame]
/*
* 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 <android-base/stringprintf.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/DisplayColorProfile.h>
#include <compositionengine/LayerFE.h>
#include <compositionengine/RenderSurface.h>
#include <compositionengine/impl/Output.h>
#include <compositionengine/impl/OutputLayer.h>
#include <ui/DebugUtils.h>
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<compositionengine::DisplayColorProfile> mode) {
mDisplayColorProfile = std::move(mode);
}
void Output::setDisplayColorProfileForTest(
std::unique_ptr<compositionengine::DisplayColorProfile> mode) {
mDisplayColorProfile = std::move(mode);
}
compositionengine::RenderSurface* Output::getRenderSurface() const {
return mRenderSurface.get();
}
void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
mRenderSurface = std::move(surface);
mState.bounds = Rect(mRenderSurface->getSize());
dirtyEntireOutput();
}
void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface> 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<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
std::optional<DisplayId> displayId, std::shared_ptr<compositionengine::Layer> layer,
sp<compositionengine::LayerFE> 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