summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Peiyong Lin <lpy@google.com> 2018-12-11 07:56:07 -0800
committer Peiyong Lin <lpy@google.com> 2018-12-15 09:35:25 -0800
commit3bff13550380f02e30f1ae77f2497d9ec89b0ec4 (patch)
tree75b2fb1ce48d7a93fa4d5e0bf5a0db31f9ab8d64
parent78c2a0de5793fd997ee716de7f4845bfa7c6a7c3 (diff)
[HWUI] Remove hardcoding around wide color gamut.
Previously we hardcode wide color gamut in HWUI as scRGB color space with FP16 pixel format. However, the hardware composer doesn't support this combination. This patch plumbs wide color gamut composition preference from composer API to HWUI such that HWUI can now pick the combination of color space and pixel format for the surface. BUG: 111436479 Test: Build, flash and boot, verify with a demo app. Change-Id: I7a8b4d8deca72ef40069dba9d23a3f5e90dbfe5a
-rw-r--r--libs/hwui/DeviceInfo.cpp46
-rw-r--r--libs/hwui/DeviceInfo.h7
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp11
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp15
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp11
-rw-r--r--libs/hwui/renderthread/EglManager.cpp178
-rw-r--r--libs/hwui/renderthread/EglManager.h18
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp28
-rw-r--r--libs/hwui/renderthread/VulkanManager.h12
-rw-r--r--libs/hwui/tests/unit/RenderNodeTests.cpp1
11 files changed, 223 insertions, 106 deletions
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index 0b9d82b105a3..ed167e57158e 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -20,6 +20,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
+#include <ui/GraphicTypes.h>
#include <mutex>
#include <thread>
@@ -61,6 +62,50 @@ DisplayInfo QueryDisplayInfo() {
return displayInfo;
}
+static void queryWideColorGamutPreference(SkColorSpace::Gamut* colorGamut,
+ sk_sp<SkColorSpace>* colorSpace, SkColorType* colorType) {
+ if (Properties::isolatedProcess) {
+ *colorGamut = SkColorSpace::Gamut::kSRGB_Gamut;
+ *colorSpace = SkColorSpace::MakeSRGB();
+ *colorType = SkColorType::kN32_SkColorType;
+ return;
+ }
+ ui::Dataspace defaultDataspace, wcgDataspace;
+ ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
+ status_t status =
+ SurfaceComposerClient::getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
+ &wcgDataspace, &wcgPixelFormat);
+ LOG_ALWAYS_FATAL_IF(status, "Failed to get composition preference, error %d", status);
+ switch (wcgDataspace) {
+ case ui::Dataspace::DISPLAY_P3:
+ *colorGamut = SkColorSpace::Gamut::kDCIP3_D65_Gamut;
+ *colorSpace = SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::Gamut::kDCIP3_D65_Gamut);
+ break;
+ case ui::Dataspace::V0_SCRGB:
+ *colorGamut = SkColorSpace::Gamut::kSRGB_Gamut;
+ *colorSpace = SkColorSpace::MakeSRGB();
+ break;
+ case ui::Dataspace::V0_SRGB:
+ // when sRGB is returned, it means wide color gamut is not supported.
+ *colorGamut = SkColorSpace::Gamut::kSRGB_Gamut;
+ *colorSpace = SkColorSpace::MakeSRGB();
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
+ switch (wcgPixelFormat) {
+ case ui::PixelFormat::RGBA_8888:
+ *colorType = SkColorType::kN32_SkColorType;
+ break;
+ case ui::PixelFormat::RGBA_FP16:
+ *colorType = SkColorType::kRGBA_F16_SkColorType;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unreachable: unsupported pixel format.");
+ }
+}
+
DeviceInfo::DeviceInfo() {
#if HWUI_NULL_GPU
mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
@@ -68,6 +113,7 @@ DeviceInfo::DeviceInfo() {
mMaxTextureSize = -1;
#endif
mDisplayInfo = QueryDisplayInfo();
+ queryWideColorGamutPreference(&mWideColorGamut, &mWideColorSpace, &mWideColorType);
}
int DeviceInfo::maxTextureSize() const {
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 595621573e6e..9bcc8e8a3dbe 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -16,6 +16,7 @@
#ifndef DEVICEINFO_H
#define DEVICEINFO_H
+#include <SkImageInfo.h>
#include <ui/DisplayInfo.h>
#include "utils/Macros.h"
@@ -37,6 +38,9 @@ public:
// context or if you are using the HWUI_NULL_GPU
int maxTextureSize() const;
const DisplayInfo& displayInfo() const { return mDisplayInfo; }
+ SkColorSpace::Gamut getWideColorGamut() const { return mWideColorGamut; }
+ sk_sp<SkColorSpace> getWideColorSpace() const { return mWideColorSpace; }
+ SkColorType getWideColorType() const { return mWideColorType; }
private:
friend class renderthread::RenderThread;
@@ -46,6 +50,9 @@ private:
int mMaxTextureSize;
DisplayInfo mDisplayInfo;
+ SkColorSpace::Gamut mWideColorGamut;
+ sk_sp<SkColorSpace> mWideColorSpace;
+ SkColorType mWideColorType;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 07979a22c988..4338b1cc2a21 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -162,22 +162,17 @@ bool SkiaOpenGLPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
mEglSurface = EGL_NO_SURFACE;
}
+ setSurfaceColorProperties(colorMode);
+
if (surface) {
mRenderThread.requireGlContext();
- auto newSurface = mEglManager.createSurface(surface, colorMode);
+ auto newSurface = mEglManager.createSurface(surface, colorMode, mSurfaceColorGamut);
if (!newSurface) {
return false;
}
mEglSurface = newSurface.unwrap();
}
- if (colorMode == ColorMode::SRGB) {
- mSurfaceColorType = SkColorType::kN32_SkColorType;
- } else if (colorMode == ColorMode::WideColorGamut) {
- mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
- }
- mSurfaceColorSpace = SkColorSpace::MakeSRGB();
-
if (mEglSurface != EGL_NO_SURFACE) {
const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer);
mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 7a255c15bf5f..7f62ab5abb7d 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -17,6 +17,7 @@
#include "SkiaPipeline.h"
#include <SkImageEncoder.h>
+#include <SkImageInfo.h>
#include <SkImagePriv.h>
#include <SkOverdrawCanvas.h>
#include <SkOverdrawColorFilter.h>
@@ -453,6 +454,20 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
ALOGD("%s", log.c_str());
}
+void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
+ if (colorMode == ColorMode::SRGB) {
+ mSurfaceColorType = SkColorType::kN32_SkColorType;
+ mSurfaceColorGamut = SkColorSpace::Gamut::kSRGB_Gamut;
+ mSurfaceColorSpace = SkColorSpace::MakeSRGB();
+ } else if (colorMode == ColorMode::WideColorGamut) {
+ mSurfaceColorType = DeviceInfo::get()->getWideColorType();
+ mSurfaceColorGamut = DeviceInfo::get()->getWideColorGamut();
+ mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
+ } else {
+ LOG_ALWAYS_FATAL("Unreachable: unsupported color mode.");
+ }
+}
+
// Overdraw debugging
// These colors should be kept in sync with Caches::getOverdrawColor() with a few differences.
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 42a411a6808c..af58f634ecd0 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -107,9 +107,11 @@ public:
protected:
void dumpResourceCacheUsage() const;
+ void setSurfaceColorProperties(renderthread::ColorMode colorMode);
renderthread::RenderThread& mRenderThread;
SkColorType mSurfaceColorType;
+ SkColorSpace::Gamut mSurfaceColorGamut;
sk_sp<SkColorSpace> mSurfaceColorSpace;
private:
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 437b5dc83f58..65ae0ddeccf3 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -122,15 +122,10 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBeh
mVkSurface = nullptr;
}
- mSurfaceColorSpace = SkColorSpace::MakeSRGB();
+ setSurfaceColorProperties(colorMode);
if (surface) {
- mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace);
- }
-
- if (colorMode == ColorMode::SRGB) {
- mSurfaceColorType = SkColorType::kN32_SkColorType;
- } else if (colorMode == ColorMode::WideColorGamut) {
- mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
+ mVkSurface = mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace,
+ mSurfaceColorGamut, mSurfaceColorType);
}
return mVkSurface != nullptr;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 8230dfd44f9a..56eedff4a6e6 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -89,7 +89,8 @@ EglManager::EglManager()
, mEglConfigWideGamut(nullptr)
, mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE)
- , mCurrentSurface(EGL_NO_SURFACE) {}
+ , mCurrentSurface(EGL_NO_SURFACE)
+ , mHasWideColorGamutSupport(false) {}
EglManager::~EglManager() {
destroy();
@@ -128,6 +129,81 @@ void EglManager::initialize() {
createContext();
createPBufferSurface();
makeCurrent(mPBufferSurface, nullptr, /* force */ true);
+
+ SkColorSpace::Gamut wideColorGamut = DeviceInfo::get()->getWideColorGamut();
+ bool hasWideColorSpaceExtension = false;
+ if (wideColorGamut == SkColorSpace::Gamut::kDCIP3_D65_Gamut) {
+ hasWideColorSpaceExtension = EglExtensions.displayP3;
+ } else if (wideColorGamut == SkColorSpace::Gamut::kSRGB_Gamut) {
+ hasWideColorSpaceExtension = EglExtensions.scRGB;
+ } else {
+ LOG_ALWAYS_FATAL("Unsupported wide color space.");
+ }
+ mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension &&
+ mEglConfigWideGamut != EGL_NO_CONFIG_KHR;
+}
+
+EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavior swapBehavior) {
+ EGLint eglSwapBehavior =
+ (swapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ EGLint attribs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_CONFIG_CAVEAT,
+ EGL_NONE,
+ EGL_STENCIL_SIZE,
+ STENCIL_BUFFER_SIZE,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | eglSwapBehavior,
+ EGL_NONE};
+ EGLConfig config = EGL_NO_CONFIG_KHR;
+ EGLint numConfigs = 1;
+ if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
+ numConfigs != 1) {
+ return EGL_NO_CONFIG_KHR;
+ }
+ return config;
+}
+
+EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior) {
+ EGLint eglSwapBehavior =
+ (swapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ // If we reached this point, we have a valid swap behavior
+ EGLint attribs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_COLOR_COMPONENT_TYPE_EXT,
+ EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_RED_SIZE,
+ 16,
+ EGL_GREEN_SIZE,
+ 16,
+ EGL_BLUE_SIZE,
+ 16,
+ EGL_ALPHA_SIZE,
+ 16,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_STENCIL_SIZE,
+ STENCIL_BUFFER_SIZE,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | eglSwapBehavior,
+ EGL_NONE};
+ EGLConfig config = EGL_NO_CONFIG_KHR;
+ EGLint numConfigs = 1;
+ if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) ||
+ numConfigs != 1) {
+ return EGL_NO_CONFIG_KHR;
+ }
+ return config;
}
void EglManager::initExtensions() {
@@ -146,12 +222,8 @@ void EglManager::initExtensions() {
EglExtensions.glColorSpace = extensions.has("EGL_KHR_gl_colorspace");
EglExtensions.noConfigContext = extensions.has("EGL_KHR_no_config_context");
EglExtensions.pixelFormatFloat = extensions.has("EGL_EXT_pixel_format_float");
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb_linear");
-#else
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
-#endif
- EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3");
+ EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3_passthrough");
EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
}
@@ -162,77 +234,35 @@ bool EglManager::hasEglContext() {
void EglManager::loadConfigs() {
ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
- EGLint swapBehavior =
- (mSwapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
// Note: The default pixel format is RGBA_8888, when other formats are
// available, we should check the target pixel format and configure the
// attributes list properly.
- EGLint attribs[] = {EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_BLUE_SIZE,
- 8,
- EGL_ALPHA_SIZE,
- 8,
- EGL_DEPTH_SIZE,
- 0,
- EGL_CONFIG_CAVEAT,
- EGL_NONE,
- EGL_STENCIL_SIZE,
- STENCIL_BUFFER_SIZE,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE};
-
- EGLint numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, numConfigs, &numConfigs) ||
- numConfigs != 1) {
+ mEglConfig = load8BitsConfig(mEglDisplay, mSwapBehavior);
+ if (mEglConfig == EGL_NO_CONFIG_KHR) {
if (mSwapBehavior == SwapBehavior::Preserved) {
// Try again without dirty regions enabled
ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
mSwapBehavior = SwapBehavior::Discard;
- loadConfigs();
- return; // the call to loadConfigs() we just made picks the wide gamut config
+ ALOGD("Swap behavior %d", static_cast<int>(mSwapBehavior));
+ mEglConfig = load8BitsConfig(mEglDisplay, mSwapBehavior);
} else {
// Failed to get a valid config
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
}
}
+ SkColorType wideColorType = DeviceInfo::get()->getWideColorType();
- if (EglExtensions.pixelFormatFloat) {
- // If we reached this point, we have a valid swap behavior
- EGLint attribs16F[] = {EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_COLOR_COMPONENT_TYPE_EXT,
- EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
- EGL_RED_SIZE,
- 16,
- EGL_GREEN_SIZE,
- 16,
- EGL_BLUE_SIZE,
- 16,
- EGL_ALPHA_SIZE,
- 16,
- EGL_DEPTH_SIZE,
- 0,
- EGL_STENCIL_SIZE,
- STENCIL_BUFFER_SIZE,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE};
-
- numConfigs = 1;
- if (!eglChooseConfig(mEglDisplay, attribs16F, &mEglConfigWideGamut, numConfigs,
- &numConfigs) ||
- numConfigs != 1) {
+ // When we reach this point, we have a valid swap behavior
+ if (wideColorType == SkColorType::kRGBA_F16_SkColorType && EglExtensions.pixelFormatFloat) {
+ mEglConfigWideGamut = loadFP16Config(mEglDisplay, mSwapBehavior);
+ if (mEglConfigWideGamut == EGL_NO_CONFIG_KHR) {
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
eglErrorString());
EglExtensions.pixelFormatFloat = false;
}
+ } else if (wideColorType == SkColorType::kN32_SkColorType) {
+ mEglConfigWideGamut = load8BitsConfig(mEglDisplay, mSwapBehavior);
}
}
@@ -263,11 +293,12 @@ void EglManager::createPBufferSurface() {
}
}
-Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
+Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
+ ColorMode colorMode,
+ SkColorSpace::Gamut colorGamut) {
LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
- bool wideColorGamut = colorMode == ColorMode::WideColorGamut && EglExtensions.glColorSpace &&
- EglExtensions.scRGB && EglExtensions.pixelFormatFloat &&
+ bool wideColorGamut = colorMode == ColorMode::WideColorGamut && mHasWideColorGamutSupport &&
EglExtensions.noConfigContext;
// The color space we want to use depends on whether linear blending is turned
@@ -285,8 +316,8 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
// When wide gamut rendering is on we cannot rely on the GPU performing
// linear blending for us. We use two different color spaces to tag the
// surface appropriately for SurfaceFlinger:
- // - Gamma blending (default) requires the use of the scRGB-nl color space
- // - Linear blending requires the use of the scRGB color space
+ // - Gamma blending (default) requires the use of the non-linear color space
+ // - Linear blending requires the use of the linear color space
// Not all Android targets support the EGL_GL_COLORSPACE_KHR extension
// We insert to placeholders to set EGL_GL_COLORSPACE_KHR and its value.
@@ -296,19 +327,20 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
if (EglExtensions.glColorSpace) {
attribs[0] = EGL_GL_COLORSPACE_KHR;
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
- if (wideColorGamut) {
- attribs[1] = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
- } else {
- attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
- }
-#else
if (wideColorGamut) {
- attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
+ switch (colorGamut) {
+ case SkColorSpace::Gamut::kDCIP3_D65_Gamut:
+ attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
+ break;
+ case SkColorSpace::Gamut::kSRGB_Gamut:
+ attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
} else {
attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
}
-#endif
}
EGLSurface surface = eglCreateWindowSurface(
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 2a44f7e10b80..4dd90961b4f7 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -48,7 +48,8 @@ public:
bool hasEglContext();
- Result<EGLSurface, EGLint> createSurface(EGLNativeWindowType window, ColorMode colorMode);
+ Result<EGLSurface, EGLint> createSurface(EGLNativeWindowType window, ColorMode colorMode,
+ SkColorSpace::Gamut colorGamut);
void destroySurface(EGLSurface surface);
void destroy();
@@ -80,6 +81,14 @@ public:
status_t createReleaseFence(bool useFenceSync, EGLSyncKHR* eglFence, sp<Fence>& nativeFence);
private:
+ enum class SwapBehavior {
+ Discard,
+ Preserved,
+ BufferAge,
+ };
+
+ static EGLConfig load8BitsConfig(EGLDisplay display, SwapBehavior swapBehavior);
+ static EGLConfig loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior);
void initExtensions();
void createPBufferSurface();
@@ -93,12 +102,7 @@ private:
EGLContext mEglContext;
EGLSurface mPBufferSurface;
EGLSurface mCurrentSurface;
-
- enum class SwapBehavior {
- Discard,
- Preserved,
- BufferAge,
- };
+ bool mHasWideColorGamutSupport;
SwapBehavior mSwapBehavior = SwapBehavior::Discard;
};
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4be8bd9a863e..aa7a141f6da3 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -473,8 +473,10 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
ColorMode colorMode = surface->mColorMode;
sk_sp<SkColorSpace> colorSpace = surface->mColorSpace;
+ SkColorSpace::Gamut colorGamut = surface->mColorGamut;
+ SkColorType colorType = surface->mColorType;
destroySurface(surface);
- *surfaceOut = createSurface(window, colorMode, colorSpace);
+ *surfaceOut = createSurface(window, colorMode, colorSpace, colorGamut, colorType);
surface = *surfaceOut;
}
@@ -647,8 +649,7 @@ void VulkanManager::createBuffers(VulkanSurface* surface, VkFormat format, VkExt
VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin,
- surface->mColorMode == ColorMode::WideColorGamut ? kRGBA_F16_SkColorType
- : kRGBA_8888_SkColorType, surface->mColorSpace, &props);
+ surface->mColorType, surface->mColorSpace, &props);
}
SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -767,10 +768,20 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
VkFormat surfaceFormat = VK_FORMAT_R8G8B8A8_UNORM;
VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- if (surface->mColorMode == ColorMode::WideColorGamut) {
+ if (surface->mColorType == SkColorType::kRGBA_F16_SkColorType) {
surfaceFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
- colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
}
+
+ if (surface->mColorMode == ColorMode::WideColorGamut) {
+ if (surface->mColorGamut == SkColorSpace::Gamut::kSRGB_Gamut) {
+ colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
+ } else if (surface->mColorGamut == SkColorSpace::Gamut::kDCIP3_D65_Gamut) {
+ colorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT;
+ } else {
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
+ }
+
bool foundSurfaceFormat = false;
for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
if (surfaceFormat == surfaceFormats[i].format
@@ -840,14 +851,17 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) {
}
VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
- sk_sp<SkColorSpace> surfaceColorSpace) {
+ sk_sp<SkColorSpace> surfaceColorSpace,
+ SkColorSpace::Gamut surfaceColorGamut,
+ SkColorType surfaceColorType) {
initialize();
if (!window) {
return nullptr;
}
- VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace);
+ VulkanSurface* surface = new VulkanSurface(colorMode, window, surfaceColorSpace,
+ surfaceColorGamut, surfaceColorType);
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index d67d2c81e95c..69ca23acb1fd 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -38,8 +38,10 @@ class RenderThread;
class VulkanSurface {
public:
- VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace)
- : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace) {}
+ VulkanSurface(ColorMode colorMode, ANativeWindow* window, sk_sp<SkColorSpace> colorSpace,
+ SkColorSpace::Gamut colorGamut, SkColorType colorType)
+ : mColorMode(colorMode), mNativeWindow(window), mColorSpace(colorSpace),
+ mColorGamut(colorGamut), mColorType(colorType) {}
sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
@@ -80,6 +82,8 @@ private:
int mWindowWidth = 0;
int mWindowHeight = 0;
sk_sp<SkColorSpace> mColorSpace;
+ SkColorSpace::Gamut mColorGamut;
+ SkColorType mColorType;
};
// This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -98,7 +102,9 @@ public:
// Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new
// VulkanSurface object which is returned.
VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
- sk_sp<SkColorSpace> surfaceColorSpace);
+ sk_sp<SkColorSpace> surfaceColorSpace,
+ SkColorSpace::Gamut surfaceColorGamut,
+ SkColorType surfaceColorType);
// Destroy the VulkanSurface and all associated vulkan objects.
void destroySurface(VulkanSurface* surface);
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index a6073ebb5c74..75fb0ef0acc1 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -306,6 +306,7 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
ContextFactory contextFactory;
std::unique_ptr<CanvasContext> canvasContext(
CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
+ canvasContext->setSurface(nullptr);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
DamageAccumulator damageAccumulator;
LayerUpdateQueue layerUpdateQueue;