SF: adapt region sampling to display orientation
Pass in the orientation flags of SF to RenderEngine when conducting the
sampling composition. This resulted mis-sampled areas, especially when
the region was outside of the clip of the 0-degree rotated display.
Bug: 132394665
Test: manual verification with 90, 270, 0 rotations
Test: new tests in libsurfaceflinger_unittest#RegionSamplingTest.*
Change-Id: I2869ef191572dbcc9170df8d3ed17414ab053ca4
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 3684260..7fa33f5 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -26,6 +26,8 @@
#include <utils/Trace.h>
#include <string>
+#include <compositionengine/Display.h>
+#include <compositionengine/impl/OutputCompositionState.h>
#include "DisplayDevice.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
@@ -264,7 +266,22 @@
}
} // anonymous namespace
-float sampleArea(const uint32_t* data, int32_t stride, const Rect& area) {
+float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride,
+ uint32_t orientation, const Rect& sample_area) {
+ if (!sample_area.isValid() || (sample_area.getWidth() > width) ||
+ (sample_area.getHeight() > height)) {
+ ALOGE("invalid sampling region requested");
+ return 0.0f;
+ }
+
+ // (b/133849373) ROT_90 screencap images produced upside down
+ auto area = sample_area;
+ if (orientation & ui::Transform::ROT_90) {
+ area.top = height - area.top;
+ area.bottom = height - area.bottom;
+ std::swap(area.top, area.bottom);
+ }
+
std::array<int32_t, 256> brightnessBuckets = {};
const int32_t majoritySampleNum = area.getWidth() * area.getHeight() / 2;
@@ -293,18 +310,21 @@
std::vector<float> RegionSamplingThread::sampleBuffer(
const sp<GraphicBuffer>& buffer, const Point& leftTop,
- const std::vector<RegionSamplingThread::Descriptor>& descriptors) {
+ const std::vector<RegionSamplingThread::Descriptor>& descriptors, uint32_t orientation) {
void* data_raw = nullptr;
buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, &data_raw);
std::shared_ptr<uint32_t> data(reinterpret_cast<uint32_t*>(data_raw),
[&buffer](auto) { buffer->unlock(); });
if (!data) return {};
+ const int32_t width = buffer->getWidth();
+ const int32_t height = buffer->getHeight();
const int32_t stride = buffer->getStride();
std::vector<float> lumas(descriptors.size());
std::transform(descriptors.begin(), descriptors.end(), lumas.begin(),
[&](auto const& descriptor) {
- return sampleArea(data.get(), stride, descriptor.area - leftTop);
+ return sampleArea(data.get(), width, height, stride, orientation,
+ descriptor.area - leftTop);
});
return lumas;
}
@@ -317,6 +337,11 @@
return;
}
+ const auto device = mFlinger.getDefaultDisplayDevice();
+ const auto display = device->getCompositionDisplay();
+ const auto state = display->getState();
+ const auto orientation = static_cast<ui::Transform::orientation_flags>(state.orientation);
+
std::vector<RegionSamplingThread::Descriptor> descriptors;
Region sampleRegion;
for (const auto& [listener, descriptor] : mDescriptors) {
@@ -326,10 +351,28 @@
const Rect sampledArea = sampleRegion.bounds();
- sp<const DisplayDevice> device = mFlinger.getDefaultDisplayDevice();
- DisplayRenderArea renderArea(device, sampledArea, sampledArea.getWidth(),
- sampledArea.getHeight(), ui::Dataspace::V0_SRGB,
- ui::Transform::ROT_0);
+ auto dx = 0;
+ auto dy = 0;
+ switch (orientation) {
+ case ui::Transform::ROT_90:
+ dx = device->getWidth();
+ break;
+ case ui::Transform::ROT_180:
+ dx = device->getWidth();
+ dy = device->getHeight();
+ break;
+ case ui::Transform::ROT_270:
+ dy = device->getHeight();
+ break;
+ default:
+ break;
+ }
+
+ ui::Transform t(orientation);
+ auto screencapRegion = t.transform(sampleRegion);
+ screencapRegion = screencapRegion.translate(dx, dy);
+ DisplayRenderArea renderArea(device, screencapRegion.bounds(), sampledArea.getWidth(),
+ sampledArea.getHeight(), ui::Dataspace::V0_SRGB, orientation);
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
@@ -395,8 +438,8 @@
}
ALOGV("Sampling %zu descriptors", activeDescriptors.size());
- std::vector<float> lumas = sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors);
-
+ std::vector<float> lumas =
+ sampleBuffer(buffer, sampledArea.leftTop(), activeDescriptors, orientation);
if (lumas.size() != activeDescriptors.size()) {
ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(),
activeDescriptors.size());