Fix the source crop for screenshots for notch hide
* Orientation transform needs to be applied after the device transform
* Source crop needs to have a transform applied to it so that the
clipping window is in the right spot.
Bug: 129362302
Test: screenshots
Change-Id: I675be4d1fb2386f24ead69a77b08bec65d2f5d47
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index c80925e..0067b50 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -288,16 +288,21 @@
}
Rect getSourceCrop() const override {
- // use the (projected) logical display viewport by default
+ // use the projected display viewport by default.
if (mSourceCrop.isEmpty()) {
return mDevice->getScissor();
}
- const int orientation = mDevice->getInstallOrientation();
- if (orientation == DisplayState::eOrientationDefault) {
- return mSourceCrop;
- }
+ // Recompute the device transformation for the source crop.
+ ui::Transform rotation;
+ ui::Transform translatePhysical;
+ ui::Transform translateLogical;
+ ui::Transform scale;
+ const Rect& viewport = mDevice->getViewport();
+ const Rect& scissor = mDevice->getScissor();
+ const Rect& frame = mDevice->getFrame();
+ const int orientation = mDevice->getInstallOrientation();
// Install orientation is transparent to the callers. Apply it now.
uint32_t flags = 0x00;
switch (orientation) {
@@ -310,10 +315,17 @@
case DisplayState::eOrientation270:
flags = ui::Transform::ROT_270;
break;
+ default:
+ break;
}
- ui::Transform tr;
- tr.set(flags, getWidth(), getHeight());
- return tr.transform(mSourceCrop);
+ rotation.set(flags, getWidth(), getHeight());
+ translateLogical.set(-viewport.left, -viewport.top);
+ translatePhysical.set(scissor.left, scissor.top);
+ scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0,
+ frame.getHeight() / float(viewport.getHeight()));
+ const ui::Transform finalTransform =
+ rotation * translatePhysical * scale * translateLogical;
+ return finalTransform.transform(mSourceCrop);
}
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 0345baf..93a5b57 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5671,8 +5671,9 @@
const auto reqWidth = renderArea.getReqWidth();
const auto reqHeight = renderArea.getReqHeight();
- const auto sourceCrop = renderArea.getSourceCrop();
const auto rotation = renderArea.getRotationFlags();
+ const auto transform = renderArea.getTransform();
+ const auto sourceCrop = renderArea.getSourceCrop();
renderengine::DisplaySettings clientCompositionDisplay;
std::vector<renderengine::LayerSettings> clientCompositionLayers;
@@ -5680,31 +5681,34 @@
// assume that bounds are never offset, and that they are the same as the
// buffer bounds.
clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
- ui::Transform transform = renderArea.getTransform();
+ clientCompositionDisplay.clip = sourceCrop;
clientCompositionDisplay.globalTransform = transform.asMatrix4();
+
+ // Now take into account the rotation flag. We append a transform that
+ // rotates the layer stack about the origin, then translate by buffer
+ // boundaries to be in the right quadrant.
mat4 rotMatrix;
- // Displacement for repositioning the clipping rectangle after rotating it
- // with the rotation hint.
int displacementX = 0;
int displacementY = 0;
float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
switch (rotation) {
case ui::Transform::ROT_90:
rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
- displacementX = reqWidth;
+ displacementX = renderArea.getBounds().getHeight();
break;
case ui::Transform::ROT_180:
rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
- displacementX = reqWidth;
- displacementY = reqHeight;
+ displacementY = renderArea.getBounds().getWidth();
+ displacementX = renderArea.getBounds().getHeight();
break;
case ui::Transform::ROT_270:
rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
- displacementY = reqHeight;
+ displacementY = renderArea.getBounds().getWidth();
break;
default:
break;
}
+
// We need to transform the clipping window into the right spot.
// First, rotate the clipping rectangle by the rotation hint to get the
// right orientation
@@ -5720,15 +5724,14 @@
// Now reposition the clipping rectangle with the displacement vector
// computed above.
const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-
clientCompositionDisplay.clip =
Rect(newClipLeft + displacementX, newClipTop + displacementY,
newClipRight + displacementX, newClipBottom + displacementY);
- // We need to perform the same transformation in layer space, so propagate
- // it to the global transform.
mat4 clipTransform = displacementMat * rotMatrix;
- clientCompositionDisplay.globalTransform *= clipTransform;
+ clientCompositionDisplay.globalTransform =
+ clipTransform * clientCompositionDisplay.globalTransform;
+
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;