[Screenshot] Accept data space and pixel format for screenshot.
Previously we always take screenshot in SRGB data space. It's been working well since the screen only has sRGB color. However, since we are moving towards wider color, we can't make this assumption any more. Thus we need to pass the data space and pixel format of the screenshot buffer into SurfaceFlinger and render screenshot in the desired data space and pixel format. BUG: 111436479 BUG: 116112787 Test: Build, flash, boot and take screenshot, observe there's no color shift. Test: Take screenshot, verified the color profile is correct of the png. Change-Id: I9b1a1c878f8099715c2a2c296aaf3419ca6e9bd5
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include <gui/ISurfaceComposer.h>
|
||||
|
||||
#include <ui/DisplayInfo.h>
|
||||
#include <ui/GraphicTypes.h>
|
||||
#include <ui/PixelFormat.h>
|
||||
|
||||
#include <system/graphics.h>
|
||||
@@ -74,12 +75,12 @@ static SkColorType flinger2skia(PixelFormat f)
|
||||
}
|
||||
}
|
||||
|
||||
static sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d)
|
||||
static sk_sp<SkColorSpace> dataSpaceToColorSpace(ui::Dataspace d)
|
||||
{
|
||||
switch (d) {
|
||||
case HAL_DATASPACE_V0_SRGB:
|
||||
case ui::Dataspace::V0_SRGB:
|
||||
return SkColorSpace::MakeSRGB();
|
||||
case HAL_DATASPACE_DISPLAY_P3:
|
||||
case ui::Dataspace::DISPLAY_P3:
|
||||
return SkColorSpace::MakeRGB(
|
||||
SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
|
||||
default:
|
||||
@@ -87,12 +88,26 @@ static sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d)
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dataSpaceToInt(android_dataspace d)
|
||||
static ui::Dataspace pickBestDataspace(ui::ColorMode colorMode)
|
||||
{
|
||||
switch (colorMode) {
|
||||
case ui::ColorMode::SRGB:
|
||||
return ui::Dataspace::V0_SRGB;
|
||||
case ui::ColorMode::DISPLAY_P3:
|
||||
case ui::ColorMode::BT2100_PQ:
|
||||
case ui::ColorMode::BT2100_HLG:
|
||||
return ui::Dataspace::DISPLAY_P3;
|
||||
default:
|
||||
return ui::Dataspace::V0_SRGB;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dataSpaceToInt(ui::Dataspace d)
|
||||
{
|
||||
switch (d) {
|
||||
case HAL_DATASPACE_V0_SRGB:
|
||||
case ui::Dataspace::V0_SRGB:
|
||||
return COLORSPACE_SRGB;
|
||||
case HAL_DATASPACE_DISPLAY_P3:
|
||||
case ui::Dataspace::DISPLAY_P3:
|
||||
return COLORSPACE_DISPLAY_P3;
|
||||
default:
|
||||
return COLORSPACE_UNKNOWN;
|
||||
@@ -161,7 +176,6 @@ int main(int argc, char** argv)
|
||||
|
||||
void* base = NULL;
|
||||
uint32_t w, s, h, f;
|
||||
android_dataspace d;
|
||||
size_t size = 0;
|
||||
|
||||
// Maps orientations from DisplayInfo to ISurfaceComposer
|
||||
@@ -197,8 +211,15 @@ int main(int argc, char** argv)
|
||||
uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
|
||||
|
||||
sp<GraphicBuffer> outBuffer;
|
||||
status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
|
||||
0 /* reqHeight */, false, captureOrientation, &outBuffer);
|
||||
ui::Dataspace reqDataspace =
|
||||
pickBestDataspace(SurfaceComposerClient::getActiveColorMode(display));
|
||||
|
||||
// Due to the fact that we hard code the way we write pixels into screenshot,
|
||||
// we hard code RGBA_8888 here.
|
||||
ui::PixelFormat reqPixelFormat = ui::PixelFormat::RGBA_8888;
|
||||
status_t result = ScreenshotClient::capture(display, reqDataspace, reqPixelFormat, Rect(),
|
||||
0 /* reqWidth */, 0 /* reqHeight */, false,
|
||||
captureOrientation, &outBuffer);
|
||||
if (result != NO_ERROR) {
|
||||
close(fd);
|
||||
return 1;
|
||||
@@ -222,12 +243,12 @@ int main(int argc, char** argv)
|
||||
h = outBuffer->getHeight();
|
||||
s = outBuffer->getStride();
|
||||
f = outBuffer->getPixelFormat();
|
||||
d = HAL_DATASPACE_UNKNOWN;
|
||||
size = s * h * bytesPerPixel(f);
|
||||
|
||||
if (png) {
|
||||
const SkImageInfo info =
|
||||
SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
|
||||
SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
|
||||
dataSpaceToColorSpace(reqDataspace));
|
||||
SkPixmap pixmap(info, base, s * bytesPerPixel(f));
|
||||
struct FDWStream final : public SkWStream {
|
||||
size_t fBytesWritten = 0;
|
||||
@@ -244,7 +265,7 @@ int main(int argc, char** argv)
|
||||
notifyMediaScanner(fn);
|
||||
}
|
||||
} else {
|
||||
uint32_t c = dataSpaceToInt(d);
|
||||
uint32_t c = dataSpaceToInt(reqDataspace);
|
||||
write(fd, &w, 4);
|
||||
write(fd, &h, 4);
|
||||
write(fd, &f, 4);
|
||||
@@ -261,4 +282,4 @@ int main(int argc, char** argv)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,8 +166,10 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
|
||||
}
|
||||
Rect sourceCrop = rectFromObj(env, sourceCropObj);
|
||||
sp<GraphicBuffer> buffer;
|
||||
status_t res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
|
||||
useIdentityTransform, rotation, &buffer);
|
||||
status_t res = ScreenshotClient::capture(displayToken, ui::Dataspace::V0_SRGB,
|
||||
ui::PixelFormat::RGBA_8888,
|
||||
sourceCrop, width, height,
|
||||
useIdentityTransform, rotation, &buffer);
|
||||
if (res != NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -195,7 +197,9 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandl
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> buffer;
|
||||
status_t res = ScreenshotClient::captureChildLayers(layerHandle, sourceCrop, frameScale, &buffer);
|
||||
status_t res = ScreenshotClient::captureChildLayers(layerHandle, ui::Dataspace::V0_SRGB,
|
||||
ui::PixelFormat::RGBA_8888, sourceCrop,
|
||||
frameScale, &buffer);
|
||||
if (res != NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user