[CE] Separate framebuffer space from display space
Some devices have limited GPU capabilities and they
cannot perform client composition at the resolution
of the active display mode. For this reason the
framebuffer size can be limited with the sysrops
ro.surface_flinger.max_graphics_height|width.
As the framebuffer size can differ from the display
size, in this CL we separate the concepts for
framebuffer space and display space so we properly
render.
Bug: 161793589
Bug: 168788659
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Test: 1. adb shell service call SurfaceFlinger 1008 i32 1
2. make sure content is rendered properly
3. adb shell service call SurfaceFlinger 1008 i32 0
4. make sure content is rendered properly
Test: play YouTube video
Change-Id: I17d54ef8c85773c072f0c38f576f3f3be504d6ec
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index abb8769..44edb6e 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -69,6 +69,19 @@
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(
@@ -110,9 +123,10 @@
auto& outputState = editState();
outputState.displaySpace.orientation = orientation;
- // outputState.displaySpace.bounds should be already set from setDisplaySpaceSize().
+ LOG_FATAL_IF(outputState.displaySpace.bounds == Rect::INVALID_RECT,
+ "The display bounds are unknown.");
- // Compute the orientedDisplaySpace bounds
+ // Compute orientedDisplaySpace
ui::Size orientedSize = outputState.displaySpace.bounds.getSize();
if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
std::swap(orientedSize.width, orientedSize.height);
@@ -129,17 +143,51 @@
}
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.framebufferSpace.bounds, outputState.displaySpace.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();
}
-void Output::setDisplaySpaceSize(const ui::Size& size) {
+void Output::setDisplaySize(const ui::Size& size) {
mRenderSurface->setDisplaySize(size);
- editState().displaySpace.bounds = Rect(mRenderSurface->getSize());
+
+ auto& state = editState();
+
+ // Update framebuffer space
+ const Rect newBounds(size);
+ ScaleVector scale;
+ scale = getScale(state.framebufferSpace.bounds, newBounds);
+ state.framebufferSpace.bounds = newBounds;
+ state.framebufferSpace.content.scaleSelf(scale.x, scale.y);
+
+ // Update display space
+ scale = getScale(state.displaySpace.bounds, newBounds);
+ state.displaySpace.bounds = newBounds;
+ state.displaySpace.content.scaleSelf(scale.x, scale.y);
+ 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);
+ scale = getScale(state.orientedDisplaySpace.bounds, newOrientedBounds);
+ state.orientedDisplaySpace.bounds = newOrientedBounds;
+ state.orientedDisplaySpace.content.scaleSelf(scale.x, scale.y);
dirtyEntireOutput();
}
@@ -247,8 +295,7 @@
void Output::setRenderSurface(std::unique_ptr<compositionengine::RenderSurface> surface) {
mRenderSurface = std::move(surface);
- editState().displaySpace.bounds = Rect(mRenderSurface->getSize());
-
+ editState().framebufferSpace.bounds = Rect(mRenderSurface->getSize());
dirtyEntireOutput();
}
@@ -877,7 +924,7 @@
ALOGV("hasClientComposition");
renderengine::DisplaySettings clientCompositionDisplay;
- clientCompositionDisplay.physicalDisplay = outputState.displaySpace.content;
+ clientCompositionDisplay.physicalDisplay = outputState.framebufferSpace.content;
clientCompositionDisplay.clip = outputState.layerStackSpace.content;
clientCompositionDisplay.orientation =
ui::Transform::toRotationFlags(outputState.displaySpace.orientation);