summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/CompositionEngine/src/Output.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/CompositionEngine/src/Output.cpp')
-rw-r--r--services/surfaceflinger/CompositionEngine/src/Output.cpp366
1 files changed, 297 insertions, 69 deletions
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e8f54f57b1..cafcb40e80 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#include <thread>
-
+#include <SurfaceFlingerProperties.sysprop.h>
#include <android-base/stringprintf.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/CompositionRefreshArgs.h>
@@ -27,6 +26,11 @@
#include <compositionengine/impl/OutputCompositionState.h>
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <compositionengine/impl/planner/Planner.h>
+
+#include <thread>
+
+#include "renderengine/ExternalTexture.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
@@ -38,6 +42,7 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+#include <android-base/properties.h>
#include <ui/DebugUtils.h>
#include <ui/HdrCapabilities.h>
#include <utils/Trace.h>
@@ -69,6 +74,19 @@ Reversed<T> reversed(const T& c) {
return Reversed<T>(c);
}
+struct ScaleVector {
+ float x;
+ float y;
+};
+
+// Returns a ScaleVector (x, y) such that from.scale(x, y) = to',
+// where to' will have the same size as "to". In the case where "from" and "to"
+// start at the origin to'=to.
+ScaleVector getScale(const Rect& from, const Rect& to) {
+ return {.x = static_cast<float>(to.width()) / from.width(),
+ .y = static_cast<float>(to.height()) / from.height()};
+}
+
} // namespace
std::shared_ptr<Output> createOutput(
@@ -105,30 +123,104 @@ void Output::setCompositionEnabled(bool enabled) {
dirtyEntireOutput();
}
-void Output::setProjection(const ui::Transform& transform, uint32_t orientation, const Rect& frame,
- const Rect& viewport, const Rect& sourceClip,
- const Rect& destinationClip, bool needsFiltering) {
+void Output::setLayerCachingEnabled(bool enabled) {
+ if (enabled == (mPlanner != nullptr)) {
+ return;
+ }
+
+ if (enabled) {
+ mPlanner = std::make_unique<planner::Planner>(getCompositionEngine().getRenderEngine());
+ if (mRenderSurface) {
+ mPlanner->setDisplaySize(mRenderSurface->getSize());
+ }
+ } else {
+ mPlanner.reset();
+ }
+
+ for (auto* outputLayer : getOutputLayersOrderedByZ()) {
+ if (!outputLayer) {
+ continue;
+ }
+
+ outputLayer->editState().overrideInfo = {};
+ }
+}
+
+void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
+ const Rect& orientedDisplaySpaceRect) {
auto& outputState = editState();
- outputState.transform = transform;
- outputState.orientation = orientation;
- outputState.sourceClip = sourceClip;
- outputState.destinationClip = destinationClip;
- outputState.frame = frame;
- outputState.viewport = viewport;
- outputState.needsFiltering = needsFiltering;
+ outputState.displaySpace.orientation = orientation;
+ LOG_FATAL_IF(outputState.displaySpace.bounds == Rect::INVALID_RECT,
+ "The display bounds are unknown.");
+
+ // Compute orientedDisplaySpace
+ ui::Size orientedSize = outputState.displaySpace.bounds.getSize();
+ if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
+ std::swap(orientedSize.width, orientedSize.height);
+ }
+ outputState.orientedDisplaySpace.bounds = Rect(orientedSize);
+ outputState.orientedDisplaySpace.content = orientedDisplaySpaceRect;
+
+ // Compute displaySpace.content
+ const uint32_t transformOrientationFlags = ui::Transform::toRotationFlags(orientation);
+ ui::Transform rotation;
+ if (transformOrientationFlags != ui::Transform::ROT_INVALID) {
+ const auto displaySize = outputState.displaySpace.bounds;
+ rotation.set(transformOrientationFlags, displaySize.width(), displaySize.height());
+ }
+ outputState.displaySpace.content = rotation.transform(orientedDisplaySpaceRect);
+
+ // Compute framebufferSpace
+ outputState.framebufferSpace.orientation = orientation;
+ LOG_FATAL_IF(outputState.framebufferSpace.bounds == Rect::INVALID_RECT,
+ "The framebuffer bounds are unknown.");
+ const auto scale =
+ getScale(outputState.displaySpace.bounds, outputState.framebufferSpace.bounds);
+ outputState.framebufferSpace.content = outputState.displaySpace.content.scale(scale.x, scale.y);
+
+ // Compute layerStackSpace
+ outputState.layerStackSpace.content = layerStackSpaceRect;
+ outputState.layerStackSpace.bounds = layerStackSpaceRect;
+
+ outputState.transform = outputState.layerStackSpace.getTransform(outputState.displaySpace);
+ outputState.needsFiltering = outputState.transform.needsBilinearFiltering();
dirtyEntireOutput();
}
-// TODO(b/121291683): Rename setSize() once more is moved.
-void Output::setBounds(const ui::Size& size) {
+void Output::setDisplaySize(const ui::Size& size) {
mRenderSurface->setDisplaySize(size);
- // TODO(b/121291683): Rename outputState.size once more is moved.
- editState().bounds = Rect(mRenderSurface->getSize());
+
+ auto& state = editState();
+
+ // Update framebuffer space
+ const Rect newBounds(size);
+ state.framebufferSpace.bounds = newBounds;
+
+ // Update display space
+ state.displaySpace.bounds = newBounds;
+ state.transform = state.layerStackSpace.getTransform(state.displaySpace);
+
+ // Update oriented display space
+ const auto orientation = state.displaySpace.orientation;
+ ui::Size orientedSize = size;
+ if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
+ std::swap(orientedSize.width, orientedSize.height);
+ }
+ const Rect newOrientedBounds(orientedSize);
+ state.orientedDisplaySpace.bounds = newOrientedBounds;
+
+ if (mPlanner) {
+ mPlanner->setDisplaySize(size);
+ }
dirtyEntireOutput();
}
+ui::Transform::RotationFlags Output::getTransformHint() const {
+ return static_cast<ui::Transform::RotationFlags>(getState().transform.getOrientation());
+}
+
void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
auto& outputState = editState();
outputState.layerStackId = layerStackId;
@@ -175,6 +267,18 @@ void Output::setColorProfile(const ColorProfile& colorProfile) {
dirtyEntireOutput();
}
+void Output::setDisplayBrightness(float sdrWhitePointNits, float displayBrightnessNits) {
+ auto& outputState = editState();
+ if (outputState.sdrWhitePointNits == sdrWhitePointNits &&
+ outputState.displayBrightnessNits == displayBrightnessNits) {
+ // Nothing changed
+ return;
+ }
+ outputState.sdrWhitePointNits = sdrWhitePointNits;
+ outputState.displayBrightnessNits = displayBrightnessNits;
+ dirtyEntireOutput();
+}
+
void Output::dump(std::string& out) const {
using android::base::StringAppendF;
@@ -209,6 +313,15 @@ void Output::dumpBase(std::string& out) const {
}
}
+void Output::dumpPlannerInfo(const Vector<String16>& args, std::string& out) const {
+ if (!mPlanner) {
+ base::StringAppendF(&out, "Planner is disabled\n");
+ return;
+ }
+ base::StringAppendF(&out, "Planner info for display [%s]\n", mName.c_str());
+ mPlanner->dump(args, out);
+}
+
compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
return mDisplayColorProfile.get();
}
@@ -232,8 +345,11 @@ compositionengine::RenderSurface* Output::getRenderSurface() const {
void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
mRenderSurface = std::move(surface);
- editState().bounds = Rect(mRenderSurface->getSize());
-
+ const auto size = mRenderSurface->getSize();
+ editState().framebufferSpace.bounds = Rect(size);
+ if (mPlanner) {
+ mPlanner->setDisplaySize(size);
+ }
dirtyEntireOutput();
}
@@ -251,7 +367,7 @@ void Output::setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSu
Region Output::getDirtyRegion(bool repaintEverything) const {
const auto& outputState = getState();
- Region dirty(outputState.viewport);
+ Region dirty(outputState.layerStackSpace.content);
if (!repaintEverything) {
dirty.andSelf(outputState.dirtyRegion);
}
@@ -309,13 +425,16 @@ void Output::present(const compositionengine::CompositionRefreshArgs& refreshArg
ALOGV(__FUNCTION__);
updateColorProfile(refreshArgs);
- updateAndWriteCompositionState(refreshArgs);
+ updateCompositionState(refreshArgs);
+ planComposition();
+ writeCompositionState(refreshArgs);
setColorTransform(refreshArgs);
beginFrame();
prepareFrame();
devOptRepaintFlash(refreshArgs);
finishFrame(refreshArgs);
postFramebuffer();
+ renderCachedSets(refreshArgs);
}
void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs,
@@ -336,7 +455,7 @@ void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs&
// Compute the resulting coverage for this output, and store it for later
const ui::Transform& tr = outputState.transform;
- Region undefinedRegion{outputState.bounds};
+ Region undefinedRegion{outputState.displaySpace.bounds};
undefinedRegion.subtractSelf(tr.transform(coverage.aboveOpaqueLayers));
outputState.undefinedRegion = undefinedRegion;
@@ -359,12 +478,6 @@ void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArg
setReleasedLayers(refreshArgs);
finalizePendingOutputLayers();
-
- // Generate a simple Z-order values to each visible output layer
- uint32_t zOrder = 0;
- for (auto* outputLayer : getOutputLayersOrderedByZ()) {
- outputLayer->editState().z = zOrder++;
- }
}
void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
@@ -539,7 +652,7 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
// TODO(b/121291683): Why does this not use visibleRegion? (see outputSpaceVisibleRegion below)
const auto& outputState = getState();
Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
- drawRegion.andSelf(outputState.bounds);
+ drawRegion.andSelf(outputState.displaySpace.bounds);
if (drawRegion.isEmpty()) {
return;
}
@@ -556,8 +669,8 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE,
outputLayerState.visibleRegion = visibleRegion;
outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion;
outputLayerState.coveredRegion = coveredRegion;
- outputLayerState.outputSpaceVisibleRegion =
- outputState.transform.transform(visibleNonShadowRegion.intersect(outputState.viewport));
+ outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
+ visibleNonShadowRegion.intersect(outputState.layerStackSpace.content));
outputLayerState.shadowRegion = shadowRegion;
}
@@ -573,8 +686,7 @@ void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
}
}
-void Output::updateAndWriteCompositionState(
- const compositionengine::CompositionRefreshArgs& refreshArgs) {
+void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -594,16 +706,84 @@ void Output::updateAndWriteCompositionState(
if (mLayerRequestingBackgroundBlur == layer) {
forceClientComposition = false;
}
+ }
+}
- // Send the updated state to the HWC, if appropriate.
- layer->writeStateToHWC(refreshArgs.updatingGeometryThisFrame);
+void Output::planComposition() {
+ if (!mPlanner || !getState().isEnabled) {
+ return;
+ }
+
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
+ mPlanner->plan(getOutputLayersOrderedByZ());
+}
+
+void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) {
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
+ if (!getState().isEnabled) {
+ return;
+ }
+
+ editState().earliestPresentTime = refreshArgs.earliestPresentTime;
+ editState().previousPresentFence = refreshArgs.previousPresentFence;
+
+ compositionengine::OutputLayer* peekThroughLayer = nullptr;
+ sp<GraphicBuffer> previousOverride = nullptr;
+ bool includeGeometry = refreshArgs.updatingGeometryThisFrame;
+ uint32_t z = 0;
+ bool overrideZ = false;
+ for (auto* layer : getOutputLayersOrderedByZ()) {
+ if (layer == peekThroughLayer) {
+ // No longer needed, although it should not show up again, so
+ // resetting it is not truly needed either.
+ peekThroughLayer = nullptr;
+
+ // peekThroughLayer was already drawn ahead of its z order.
+ continue;
+ }
+ bool skipLayer = false;
+ const auto& overrideInfo = layer->getState().overrideInfo;
+ if (overrideInfo.buffer != nullptr) {
+ if (previousOverride && overrideInfo.buffer->getBuffer() == previousOverride) {
+ ALOGV("Skipping redundant buffer");
+ skipLayer = true;
+ } else {
+ // First layer with the override buffer.
+ if (overrideInfo.peekThroughLayer) {
+ peekThroughLayer = overrideInfo.peekThroughLayer;
+
+ // Draw peekThroughLayer first.
+ overrideZ = true;
+ includeGeometry = true;
+ constexpr bool isPeekingThrough = true;
+ peekThroughLayer->writeStateToHWC(includeGeometry, false, z++, overrideZ,
+ isPeekingThrough);
+ }
+
+ previousOverride = overrideInfo.buffer->getBuffer();
+ }
+ }
+
+ constexpr bool isPeekingThrough = false;
+ layer->writeStateToHWC(includeGeometry, skipLayer, z++, overrideZ, isPeekingThrough);
}
}
compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
for (auto* layer : getOutputLayersOrderedByZ()) {
- if (layer->getLayerFE().getCompositionState()->backgroundBlurRadius > 0) {
+ auto* compState = layer->getLayerFE().getCompositionState();
+
+ // If any layer has a sideband stream, we will disable blurs. In that case, we don't
+ // want to force client composition because of the blur.
+ if (compState->sidebandStream != nullptr) {
+ return nullptr;
+ }
+ if (compState->backgroundBlurRadius > 0 || compState->blurRegions.size() > 0) {
layerRequestingBgComposition = layer;
}
}
@@ -760,6 +940,10 @@ void Output::prepareFrame() {
chooseCompositionStrategy();
+ if (mPlanner) {
+ mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
+ }
+
mRenderSurface->prepareFrame(outputState.usesClientComposition,
outputState.usesDeviceComposition);
}
@@ -835,17 +1019,20 @@ std::optional<base::unique_fd> Output::composeSurfaces(
needsProtected == renderEngine.isProtected()) {
mRenderSurface->setProtected(needsProtected);
}
+ } else if (!outputState.isSecure && renderEngine.isProtected()) {
+ renderEngine.useProtectedContext(false);
}
base::unique_fd fd;
- sp<GraphicBuffer> buf;
+
+ std::shared_ptr<renderengine::ExternalTexture> tex;
// If we aren't doing client composition on this output, but do have a
// flipClientTarget request for this frame on this output, we still need to
// dequeue a buffer.
if (hasClientComposition || outputState.flipClientTarget) {
- buf = mRenderSurface->dequeueBuffer(&fd);
- if (buf == nullptr) {
+ tex = mRenderSurface->dequeueBuffer(&fd);
+ if (tex == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
"client composition for this frame",
mName.c_str());
@@ -862,14 +1049,20 @@ std::optional<base::unique_fd> Output::composeSurfaces(
ALOGV("hasClientComposition");
renderengine::DisplaySettings clientCompositionDisplay;
- clientCompositionDisplay.physicalDisplay = outputState.destinationClip;
- clientCompositionDisplay.clip = outputState.sourceClip;
- clientCompositionDisplay.orientation = outputState.orientation;
+ clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.content;
+ clientCompositionDisplay.clip = outputState.layerStackSpace.content;
+ clientCompositionDisplay.orientation =
+ ui::Transform::toRotationFlags(outputState.displaySpace.orientation);
clientCompositionDisplay.outputDataspace = mDisplayColorProfile->hasWideColorGamut()
? outputState.dataspace
: ui::Dataspace::UNKNOWN;
- clientCompositionDisplay.maxLuminance =
- mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+
+ // If we have a valid current display brightness use that, otherwise fall back to the
+ // display's max desired
+ clientCompositionDisplay.maxLuminance = outputState.displayBrightnessNits > 0.f
+ ? outputState.displayBrightnessNits
+ : mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
+ clientCompositionDisplay.sdrWhitePointNits = outputState.sdrWhitePointNits;
// Compute the global color transform matrix.
if (!outputState.usesDeviceComposition && !getSkipColorTransform()) {
@@ -889,13 +1082,14 @@ std::optional<base::unique_fd> Output::composeSurfaces(
// Check if the client composition requests were rendered into the provided graphic buffer. If
// so, we can reuse the buffer and avoid client composition.
if (mClientCompositionRequestCache) {
- if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay,
+ if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(),
+ clientCompositionDisplay,
clientCompositionLayers)) {
outputCompositionState.reusedClientComposition = true;
setExpensiveRenderingExpected(false);
return readyFence;
}
- mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay,
+ mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay,
clientCompositionLayers);
}
@@ -920,14 +1114,20 @@ std::optional<base::unique_fd> Output::composeSurfaces(
});
const nsecs_t renderEngineStart = systemTime();
+ // Only use the framebuffer cache when rendering to an internal display
+ // TODO(b/173560331): This is only to help mitigate memory leaks from virtual displays because
+ // right now we don't have a concrete eviction policy for output buffers: GLESRenderEngine
+ // bounds its framebuffer cache but Skia RenderEngine has no current policy. The best fix is
+ // probably to encapsulate the output buffer into a structure that dispatches resource cleanup
+ // over to RenderEngine, in which case this flag can be removed from the drawLayers interface.
+ const bool useFramebufferCache = outputState.layerStackInternal;
status_t status =
- renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers,
- buf->getNativeBuffer(), /*useFramebufferCache=*/true,
- std::move(fd), &readyFence);
+ renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex,
+ useFramebufferCache, std::move(fd), &readyFence);
if (status != NO_ERROR && mClientCompositionRequestCache) {
// If rendering was not successful, remove the request from the cache.
- mClientCompositionRequestCache->remove(buf->getId());
+ mClientCompositionRequestCache->remove(tex->getBuffer()->getId());
}
auto& timeStats = getCompositionEngine().getTimeStats();
@@ -948,11 +1148,13 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
ALOGV("Rendering client layers");
const auto& outputState = getState();
- const Region viewportRegion(outputState.viewport);
- const bool useIdentityTransform = false;
+ const Region viewportRegion(outputState.layerStackSpace.content);
bool firstLayer = true;
// Used when a layer clears part of the buffer.
- Region dummyRegion;
+ Region stubRegion;
+
+ bool disableBlurs = false;
+ sp<GraphicBuffer> previousOverrideBuffer = nullptr;
for (auto* layer : getOutputLayersOrderedByZ()) {
const auto& layerState = layer->getState();
@@ -967,6 +1169,8 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
continue;
}
+ disableBlurs |= layerFEState->sidebandStream != nullptr;
+
const bool clientComposition = layer->requiresClientComposition();
// We clear the client target for non-client composed layers if
@@ -985,22 +1189,40 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests(
!layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty();
if (clientComposition || clearClientComposition) {
- compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
- clip,
- useIdentityTransform,
- layer->needsFiltering() || outputState.needsFiltering,
- outputState.isSecure,
- supportsProtectedContent,
- clientComposition ? clearRegion : dummyRegion,
- outputState.viewport,
- outputDataspace,
- realContentIsVisible,
- !clientComposition, /* clearContent */
- };
- std::vector<LayerFE::LayerSettings> results =
- layerFE.prepareClientCompositionList(targetSettings);
- if (realContentIsVisible && !results.empty()) {
- layer->editState().clientCompositionTimestamp = systemTime();
+ std::vector<LayerFE::LayerSettings> results;
+ if (layer->getState().overrideInfo.buffer != nullptr) {
+ if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) {
+ results = layer->getOverrideCompositionList();
+ previousOverrideBuffer = layer->getState().overrideInfo.buffer->getBuffer();
+ ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName());
+ } else {
+ ALOGV("Skipping redundant override buffer for [%s] in RE",
+ layer->getLayerFE().getDebugName());
+ }
+ } else {
+ LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs
+ ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled
+ : (layer->getState().overrideInfo.disableBackgroundBlur
+ ? LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ BlurRegionsOnly
+ : LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ Enabled);
+ compositionengine::LayerFE::ClientCompositionTargetSettings
+ targetSettings{.clip = clip,
+ .needsFiltering = layer->needsFiltering() ||
+ outputState.needsFiltering,
+ .isSecure = outputState.isSecure,
+ .supportsProtectedContent = supportsProtectedContent,
+ .clearRegion = clientComposition ? clearRegion : stubRegion,
+ .viewport = outputState.layerStackSpace.content,
+ .dataspace = outputDataspace,
+ .realContentIsVisible = realContentIsVisible,
+ .clearContent = !clientComposition,
+ .blurSetting = blurSetting};
+ results = layerFE.prepareClientCompositionList(targetSettings);
+ if (realContentIsVisible && !results.empty()) {
+ layer->editState().clientCompositionTimestamp = systemTime();
+ }
}
clientCompositionLayers.insert(clientCompositionLayers.end(),
@@ -1091,9 +1313,15 @@ void Output::postFramebuffer() {
mReleasedLayers.clear();
}
+void Output::renderCachedSets(const CompositionRefreshArgs& refreshArgs) {
+ if (mPlanner) {
+ mPlanner->renderCachedSets(getState(), refreshArgs.nextInvalidateTime);
+ }
+}
+
void Output::dirtyEntireOutput() {
auto& outputState = editState();
- outputState.dirtyRegion.set(outputState.bounds);
+ outputState.dirtyRegion.set(outputState.displaySpace.bounds);
}
void Output::chooseCompositionStrategy() {