Merge "Wire-up colorMode="hdr""
This commit is contained in:
committed by
Android (Google) Code Review
commit
ec37956cb2
@@ -22,6 +22,7 @@ import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.CompatibilityInfo.Translator;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorSpace;
|
||||
@@ -1001,7 +1002,10 @@ public class Surface implements Parcelable {
|
||||
mHardwareRenderer = new HardwareRenderer();
|
||||
mHardwareRenderer.setContentRoot(mRenderNode);
|
||||
mHardwareRenderer.setSurface(Surface.this, true);
|
||||
mHardwareRenderer.setWideGamut(isWideColorGamut);
|
||||
mHardwareRenderer.setColorMode(
|
||||
isWideColorGamut
|
||||
? ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
|
||||
: ActivityInfo.COLOR_MODE_DEFAULT);
|
||||
mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f);
|
||||
mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
@@ -1329,13 +1329,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
|
||||
|| insets.top != 0 || insets.bottom != 0;
|
||||
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
|
||||
final boolean wideGamut =
|
||||
mContext.getResources().getConfiguration().isScreenWideColorGamut()
|
||||
&& attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
|
||||
|
||||
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
|
||||
attrs.getTitle().toString());
|
||||
mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
|
||||
updateColorModeIfNeeded(attrs.getColorMode());
|
||||
updateForceDarkMode();
|
||||
if (mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mHardwareAccelerated =
|
||||
@@ -2648,7 +2644,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
|
||||
final boolean alwaysConsumeSystemBarsChanged =
|
||||
mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
|
||||
final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode());
|
||||
updateColorModeIfNeeded(lp.getColorMode());
|
||||
surfaceCreated = !hadSurface && mSurface.isValid();
|
||||
surfaceDestroyed = hadSurface && !mSurface.isValid();
|
||||
surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId())
|
||||
@@ -2677,10 +2673,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
// hierarchy is measured below.
|
||||
dispatchApplyInsets = true;
|
||||
}
|
||||
if (colorModeChanged && mAttachInfo.mThreadedRenderer != null) {
|
||||
mAttachInfo.mThreadedRenderer.setWideGamut(
|
||||
lp.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
|
||||
}
|
||||
|
||||
if (surfaceCreated) {
|
||||
// If we are creating a new surface, then we need to
|
||||
@@ -2725,7 +2717,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mAttachInfo.mThreadedRenderer.destroy();
|
||||
}
|
||||
} else if ((surfaceReplaced
|
||||
|| surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged)
|
||||
|| surfaceSizeChanged || windowRelayoutWasForced)
|
||||
&& mSurfaceHolder == null
|
||||
&& mAttachInfo.mThreadedRenderer != null
|
||||
&& mSurface.isValid()) {
|
||||
@@ -4557,18 +4549,16 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasColorModeChanged(int colorMode) {
|
||||
private void updateColorModeIfNeeded(int colorMode) {
|
||||
if (mAttachInfo.mThreadedRenderer == null) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
final boolean isWideGamut = colorMode == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
|
||||
if (mAttachInfo.mThreadedRenderer.isWideGamut() == isWideGamut) {
|
||||
return false;
|
||||
// TODO: Centralize this sanitization? Why do we let setting bad modes?
|
||||
// Alternatively, can we just let HWUI figure it out? Do we need to care here?
|
||||
if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
|
||||
colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
|
||||
}
|
||||
if (isWideGamut && !mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.IBinder;
|
||||
@@ -157,7 +158,7 @@ public class HardwareRenderer {
|
||||
protected RenderNode mRootNode;
|
||||
private boolean mOpaque = true;
|
||||
private boolean mForceDark = false;
|
||||
private boolean mIsWideGamut = false;
|
||||
private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT;
|
||||
|
||||
/**
|
||||
* Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
|
||||
@@ -167,7 +168,7 @@ public class HardwareRenderer {
|
||||
ProcessInitializer.sInstance.initDisplayInfo();
|
||||
mRootNode = RenderNode.adopt(nCreateRootRenderNode());
|
||||
mRootNode.setClipToBounds(false);
|
||||
mNativeProxy = nCreateProxy(!mOpaque, mIsWideGamut, mRootNode.mNativeRenderNode);
|
||||
mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
|
||||
if (mNativeProxy == 0) {
|
||||
throw new OutOfMemoryError("Unable to create hardware renderer");
|
||||
}
|
||||
@@ -619,17 +620,17 @@ public class HardwareRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
|
||||
* will be wide gamut depends on the hardware support for such rendering.
|
||||
* Sets the desired color mode on this renderer. Whether or not the actual rendering
|
||||
* will use the requested colorMode depends on the hardware support for such rendering.
|
||||
*
|
||||
* @param wideGamut true if this renderer should render in wide gamut, false if it should
|
||||
* render in sRGB
|
||||
* TODO: Figure out color...
|
||||
* @param colorMode The @{@link ActivityInfo.ColorMode} to request
|
||||
* @hide
|
||||
*/
|
||||
public void setWideGamut(boolean wideGamut) {
|
||||
mIsWideGamut = wideGamut;
|
||||
nSetWideGamut(mNativeProxy, wideGamut);
|
||||
public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
|
||||
if (mColorMode != colorMode) {
|
||||
mColorMode = colorMode;
|
||||
nSetColorMode(mNativeProxy, colorMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -804,11 +805,6 @@ public class HardwareRenderer {
|
||||
nSetPictureCaptureCallback(mNativeProxy, callback);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean isWideGamut() {
|
||||
return mIsWideGamut;
|
||||
}
|
||||
|
||||
/** called by native */
|
||||
static void invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback) {
|
||||
Picture picture = new Picture(picturePtr);
|
||||
@@ -1207,8 +1203,7 @@ public class HardwareRenderer {
|
||||
|
||||
private static native long nCreateRootRenderNode();
|
||||
|
||||
private static native long nCreateProxy(boolean translucent, boolean isWideGamut,
|
||||
long rootRenderNode);
|
||||
private static native long nCreateProxy(boolean translucent, long rootRenderNode);
|
||||
|
||||
private static native void nDeleteProxy(long nativeProxy);
|
||||
|
||||
@@ -1230,7 +1225,7 @@ public class HardwareRenderer {
|
||||
|
||||
private static native void nSetOpaque(long nativeProxy, boolean opaque);
|
||||
|
||||
private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
|
||||
private static native void nSetColorMode(long nativeProxy, int colorMode);
|
||||
|
||||
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
|
||||
|
||||
|
||||
34
libs/hwui/ColorMode.h
Normal file
34
libs/hwui/ColorMode.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace android::uirenderer {
|
||||
|
||||
// Must match the constants in ActivityInfo.java
|
||||
enum class ColorMode {
|
||||
// SRGB means HWUI will produce buffer in SRGB color space.
|
||||
Default = 0,
|
||||
// WideColorGamut selects the most optimal colorspace & format for the device's display
|
||||
// Most commonly DisplayP3 + RGBA_8888 currently.
|
||||
WideColorGamut = 1,
|
||||
// HDR Rec2020 + F16
|
||||
Hdr = 2,
|
||||
// HDR Rec2020 + 1010102
|
||||
Hdr10 = 3,
|
||||
};
|
||||
|
||||
} // namespace android::uirenderer
|
||||
@@ -143,11 +143,10 @@ static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, job
|
||||
}
|
||||
|
||||
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
|
||||
jboolean translucent, jboolean isWideGamut, jlong rootRenderNodePtr) {
|
||||
jboolean translucent, jlong rootRenderNodePtr) {
|
||||
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
|
||||
ContextFactoryImpl factory(rootRenderNode);
|
||||
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
|
||||
proxy->setWideGamut(isWideGamut);
|
||||
return (jlong) proxy;
|
||||
}
|
||||
|
||||
@@ -218,10 +217,10 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
|
||||
proxy->setOpaque(opaque);
|
||||
}
|
||||
|
||||
static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jboolean wideGamut) {
|
||||
static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz,
|
||||
jlong proxyPtr, jint colorMode) {
|
||||
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
|
||||
proxy->setWideGamut(wideGamut);
|
||||
proxy->setColorMode(static_cast<ColorMode>(colorMode));
|
||||
}
|
||||
|
||||
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
|
||||
@@ -659,7 +658,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
(void*)android_view_ThreadedRenderer_setProcessStatsBuffer},
|
||||
{"nGetRenderThreadTid", "(J)I", (void*)android_view_ThreadedRenderer_getRenderThreadTid},
|
||||
{"nCreateRootRenderNode", "()J", (void*)android_view_ThreadedRenderer_createRootRenderNode},
|
||||
{"nCreateProxy", "(ZZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
|
||||
{"nCreateProxy", "(ZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
|
||||
{"nDeleteProxy", "(J)V", (void*)android_view_ThreadedRenderer_deleteProxy},
|
||||
{"nLoadSystemProperties", "(J)Z",
|
||||
(void*)android_view_ThreadedRenderer_loadSystemProperties},
|
||||
@@ -671,7 +670,7 @@ static const JNINativeMethod gMethods[] = {
|
||||
{"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
|
||||
{"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
|
||||
{"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
|
||||
{"nSetWideGamut", "(JZ)V", (void*)android_view_ThreadedRenderer_setWideGamut},
|
||||
{"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
|
||||
{"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
|
||||
{"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
|
||||
{"nRegisterAnimatingRenderNode", "(JJ)V",
|
||||
|
||||
@@ -87,6 +87,8 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
|
||||
// Note: The default preference of pixel format is RGBA_8888, when other
|
||||
// pixel format is available, we should branch out and do more check.
|
||||
fboInfo.fFormat = GL_RGBA8;
|
||||
} else if (colorType == kRGBA_1010102_SkColorType) {
|
||||
fboInfo.fFormat = GL_RGB10_A2;
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unsupported color type.");
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "VectorDrawable.h"
|
||||
#include "thread/CommonPool.h"
|
||||
#include "tools/SkSharingProc.h"
|
||||
#include "utils/Color.h"
|
||||
#include "utils/String8.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
|
||||
@@ -587,14 +588,23 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
|
||||
|
||||
void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
|
||||
mColorMode = colorMode;
|
||||
if (colorMode == ColorMode::SRGB) {
|
||||
mSurfaceColorType = SkColorType::kN32_SkColorType;
|
||||
mSurfaceColorSpace = SkColorSpace::MakeSRGB();
|
||||
} else if (colorMode == ColorMode::WideColorGamut) {
|
||||
mSurfaceColorType = DeviceInfo::get()->getWideColorType();
|
||||
mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unreachable: unsupported color mode.");
|
||||
switch (colorMode) {
|
||||
case ColorMode::Default:
|
||||
mSurfaceColorType = SkColorType::kN32_SkColorType;
|
||||
mSurfaceColorSpace = SkColorSpace::MakeSRGB();
|
||||
break;
|
||||
case ColorMode::WideColorGamut:
|
||||
mSurfaceColorType = DeviceInfo::get()->getWideColorType();
|
||||
mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
|
||||
break;
|
||||
case ColorMode::Hdr:
|
||||
mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
|
||||
mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
|
||||
break;
|
||||
case ColorMode::Hdr10:
|
||||
mSurfaceColorType = SkColorType::kRGBA_1010102_SkColorType;
|
||||
mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
|
||||
ErrorHandler* errorHandler) override;
|
||||
|
||||
void setSurfaceColorProperties(renderthread::ColorMode colorMode) override;
|
||||
void setSurfaceColorProperties(ColorMode colorMode) override;
|
||||
SkColorType getSurfaceColorType() const override { return mSurfaceColorType; }
|
||||
sk_sp<SkColorSpace> getSurfaceColorSpace() override { return mSurfaceColorSpace; }
|
||||
|
||||
@@ -76,7 +76,7 @@ protected:
|
||||
|
||||
renderthread::RenderThread& mRenderThread;
|
||||
|
||||
renderthread::ColorMode mColorMode = renderthread::ColorMode::SRGB;
|
||||
ColorMode mColorMode = ColorMode::Default;
|
||||
SkColorType mSurfaceColorType;
|
||||
sk_sp<SkColorSpace> mSurfaceColorSpace;
|
||||
|
||||
|
||||
@@ -174,7 +174,10 @@ void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
|
||||
} else {
|
||||
mNativeSurface = nullptr;
|
||||
}
|
||||
setupPipelineSurface();
|
||||
}
|
||||
|
||||
void CanvasContext::setupPipelineSurface() {
|
||||
bool hasSurface = mRenderPipeline->setSurface(
|
||||
mNativeSurface ? mNativeSurface->getNativeWindow() : nullptr, mSwapBehavior);
|
||||
|
||||
@@ -184,7 +187,7 @@ void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
|
||||
|
||||
mFrameNumber = -1;
|
||||
|
||||
if (window != nullptr && hasSurface) {
|
||||
if (mNativeSurface != nullptr && hasSurface) {
|
||||
mHaveNewSurface = true;
|
||||
mSwapHistory.clear();
|
||||
// Enable frame stats after the surface has been bound to the appropriate graphics API.
|
||||
@@ -239,9 +242,9 @@ void CanvasContext::setOpaque(bool opaque) {
|
||||
mOpaque = opaque;
|
||||
}
|
||||
|
||||
void CanvasContext::setWideGamut(bool wideGamut) {
|
||||
ColorMode colorMode = wideGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
|
||||
mRenderPipeline->setSurfaceColorProperties(colorMode);
|
||||
void CanvasContext::setColorMode(ColorMode mode) {
|
||||
mRenderPipeline->setSurfaceColorProperties(mode);
|
||||
setupPipelineSurface();
|
||||
}
|
||||
|
||||
bool CanvasContext::makeCurrent() {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "renderthread/RenderTask.h"
|
||||
#include "renderthread/RenderThread.h"
|
||||
#include "utils/RingBuffer.h"
|
||||
#include "ColorMode.h"
|
||||
|
||||
#include <SkBitmap.h>
|
||||
#include <SkRect.h>
|
||||
@@ -119,7 +120,7 @@ public:
|
||||
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
|
||||
void setOpaque(bool opaque);
|
||||
void setWideGamut(bool wideGamut);
|
||||
void setColorMode(ColorMode mode);
|
||||
bool makeCurrent();
|
||||
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
|
||||
void draw();
|
||||
@@ -211,6 +212,7 @@ private:
|
||||
bool isSwapChainStuffed();
|
||||
bool surfaceRequiresRedraw();
|
||||
void setPresentTime();
|
||||
void setupPipelineSurface();
|
||||
|
||||
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ static struct {
|
||||
bool glColorSpace = false;
|
||||
bool scRGB = false;
|
||||
bool displayP3 = false;
|
||||
bool hdr = false;
|
||||
bool contextPriority = false;
|
||||
bool surfacelessContext = false;
|
||||
bool nativeFenceSync = false;
|
||||
@@ -86,7 +87,8 @@ static struct {
|
||||
EglManager::EglManager()
|
||||
: mEglDisplay(EGL_NO_DISPLAY)
|
||||
, mEglConfig(nullptr)
|
||||
, mEglConfigWideGamut(nullptr)
|
||||
, mEglConfigF16(nullptr)
|
||||
, mEglConfig1010102(nullptr)
|
||||
, mEglContext(EGL_NO_CONTEXT)
|
||||
, mPBufferSurface(EGL_NO_SURFACE)
|
||||
, mCurrentSurface(EGL_NO_SURFACE)
|
||||
@@ -143,8 +145,7 @@ void EglManager::initialize() {
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unsupported wide color space.");
|
||||
}
|
||||
mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension &&
|
||||
mEglConfigWideGamut != EGL_NO_CONFIG_KHR;
|
||||
mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension;
|
||||
}
|
||||
|
||||
EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavior swapBehavior) {
|
||||
@@ -177,6 +178,35 @@ EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavi
|
||||
return config;
|
||||
}
|
||||
|
||||
EGLConfig EglManager::load1010102Config(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_RED_SIZE,
|
||||
10,
|
||||
EGL_GREEN_SIZE,
|
||||
10,
|
||||
EGL_BLUE_SIZE,
|
||||
10,
|
||||
EGL_ALPHA_SIZE,
|
||||
2,
|
||||
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;
|
||||
}
|
||||
|
||||
EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior) {
|
||||
EGLint eglSwapBehavior =
|
||||
(swapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
|
||||
@@ -230,6 +260,7 @@ void EglManager::initExtensions() {
|
||||
EglExtensions.pixelFormatFloat = extensions.has("EGL_EXT_pixel_format_float");
|
||||
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
|
||||
EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3_passthrough");
|
||||
EglExtensions.hdr = extensions.has("EGL_EXT_gl_colorspace_bt2020_pq");
|
||||
EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
|
||||
EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
|
||||
EglExtensions.fenceSync = extensions.has("EGL_KHR_fence_sync");
|
||||
@@ -260,18 +291,20 @@ void EglManager::loadConfigs() {
|
||||
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
|
||||
}
|
||||
}
|
||||
SkColorType wideColorType = DeviceInfo::get()->getWideColorType();
|
||||
|
||||
// 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) {
|
||||
if (EglExtensions.pixelFormatFloat) {
|
||||
mEglConfigF16 = loadFP16Config(mEglDisplay, mSwapBehavior);
|
||||
if (mEglConfigF16 == 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);
|
||||
}
|
||||
mEglConfig1010102 = load1010102Config(mEglDisplay, mSwapBehavior);
|
||||
if (mEglConfig1010102 == EGL_NO_CONFIG_KHR) {
|
||||
ALOGW("Failed to initialize 101010-2 format, error = %s",
|
||||
eglErrorString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,8 +344,9 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
|
||||
sk_sp<SkColorSpace> colorSpace) {
|
||||
LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
|
||||
|
||||
bool wideColorGamut = colorMode == ColorMode::WideColorGamut && mHasWideColorGamutSupport &&
|
||||
EglExtensions.noConfigContext;
|
||||
if (!mHasWideColorGamutSupport || !EglExtensions.noConfigContext) {
|
||||
colorMode = ColorMode::Default;
|
||||
}
|
||||
|
||||
// The color space we want to use depends on whether linear blending is turned
|
||||
// on and whether the app has requested wide color gamut rendering. When wide
|
||||
@@ -338,26 +372,47 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
|
||||
// list is considered empty if the first entry is EGL_NONE
|
||||
EGLint attribs[] = {EGL_NONE, EGL_NONE, EGL_NONE};
|
||||
|
||||
EGLConfig config = mEglConfig;
|
||||
if (DeviceInfo::get()->getWideColorType() == kRGBA_F16_SkColorType) {
|
||||
if (mEglConfigF16 == EGL_NO_CONFIG_KHR) {
|
||||
colorMode = ColorMode::Default;
|
||||
} else {
|
||||
config = mEglConfigF16;
|
||||
}
|
||||
}
|
||||
if (EglExtensions.glColorSpace) {
|
||||
attribs[0] = EGL_GL_COLORSPACE_KHR;
|
||||
if (wideColorGamut) {
|
||||
skcms_Matrix3x3 colorGamut;
|
||||
LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
|
||||
"Could not get gamut matrix from color space");
|
||||
if (memcmp(&colorGamut, &SkNamedGamut::kDisplayP3, sizeof(colorGamut)) == 0) {
|
||||
attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
|
||||
} else if (memcmp(&colorGamut, &SkNamedGamut::kSRGB, sizeof(colorGamut)) == 0) {
|
||||
attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
|
||||
switch (colorMode) {
|
||||
case ColorMode::Default:
|
||||
attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
|
||||
break;
|
||||
case ColorMode::WideColorGamut: {
|
||||
skcms_Matrix3x3 colorGamut;
|
||||
LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
|
||||
"Could not get gamut matrix from color space");
|
||||
if (memcmp(&colorGamut, &SkNamedGamut::kDisplayP3, sizeof(colorGamut)) == 0) {
|
||||
attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
|
||||
} else if (memcmp(&colorGamut, &SkNamedGamut::kSRGB, sizeof(colorGamut)) == 0) {
|
||||
attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
|
||||
} else if (memcmp(&colorGamut, &SkNamedGamut::kRec2020, sizeof(colorGamut)) == 0) {
|
||||
attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
|
||||
} else {
|
||||
LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
|
||||
case ColorMode::Hdr:
|
||||
config = mEglConfigF16;
|
||||
attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
|
||||
break;
|
||||
case ColorMode::Hdr10:
|
||||
config = mEglConfig1010102;
|
||||
attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EGLSurface surface = eglCreateWindowSurface(
|
||||
mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
|
||||
EGLSurface surface = eglCreateWindowSurface(mEglDisplay, config, window, attribs);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
return Error<EGLint>{eglGetError()};
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ private:
|
||||
|
||||
static EGLConfig load8BitsConfig(EGLDisplay display, SwapBehavior swapBehavior);
|
||||
static EGLConfig loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior);
|
||||
static EGLConfig load1010102Config(EGLDisplay display, SwapBehavior swapBehavior);
|
||||
|
||||
void initExtensions();
|
||||
void createPBufferSurface();
|
||||
@@ -97,7 +98,8 @@ private:
|
||||
|
||||
EGLDisplay mEglDisplay;
|
||||
EGLConfig mEglConfig;
|
||||
EGLConfig mEglConfigWideGamut;
|
||||
EGLConfig mEglConfigF16;
|
||||
EGLConfig mEglConfig1010102;
|
||||
EGLContext mEglContext;
|
||||
EGLSurface mPBufferSurface;
|
||||
EGLSurface mCurrentSurface;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "Lighting.h"
|
||||
#include "SwapBehavior.h"
|
||||
#include "hwui/Bitmap.h"
|
||||
#include "ColorMode.h"
|
||||
|
||||
#include <SkRect.h>
|
||||
#include <utils/RefBase.h>
|
||||
@@ -42,16 +43,6 @@ namespace renderthread {
|
||||
|
||||
enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
|
||||
|
||||
enum class ColorMode {
|
||||
// SRGB means HWUI will produce buffer in SRGB color space.
|
||||
SRGB,
|
||||
// WideColorGamut means HWUI would support rendering scRGB non-linear into
|
||||
// a signed buffer with enough range to support the wide color gamut of the
|
||||
// display.
|
||||
WideColorGamut,
|
||||
// Hdr
|
||||
};
|
||||
|
||||
class Frame;
|
||||
|
||||
class IRenderPipeline {
|
||||
|
||||
@@ -109,8 +109,8 @@ void RenderProxy::setOpaque(bool opaque) {
|
||||
mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
|
||||
}
|
||||
|
||||
void RenderProxy::setWideGamut(bool wideGamut) {
|
||||
mRenderThread.queue().post([=]() { mContext->setWideGamut(wideGamut); });
|
||||
void RenderProxy::setColorMode(ColorMode mode) {
|
||||
mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
|
||||
}
|
||||
|
||||
int64_t* RenderProxy::frameInfo() {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "../FrameMetricsObserver.h"
|
||||
#include "../IContextFactory.h"
|
||||
#include "ColorMode.h"
|
||||
#include "DrawFrameTask.h"
|
||||
#include "SwapBehavior.h"
|
||||
#include "hwui/Bitmap.h"
|
||||
@@ -77,7 +78,7 @@ public:
|
||||
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
|
||||
void setOpaque(bool opaque);
|
||||
void setWideGamut(bool wideGamut);
|
||||
void setColorMode(ColorMode mode);
|
||||
int64_t* frameInfo();
|
||||
int syncAndDrawFrame();
|
||||
void destroy();
|
||||
|
||||
@@ -344,5 +344,27 @@ SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) {
|
||||
static_cast<uint8_t>(rgb.b * 255));
|
||||
}
|
||||
|
||||
// Note that SkColorSpace doesn't have the notion of an unspecified SDR white
|
||||
// level.
|
||||
static constexpr float kDefaultSDRWhiteLevel = 150.f;
|
||||
|
||||
skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) {
|
||||
if (sdr_white_level <= 0.f) {
|
||||
sdr_white_level = kDefaultSDRWhiteLevel;
|
||||
}
|
||||
// The generic PQ transfer function produces normalized luminance values i.e.
|
||||
// the range 0-1 represents 0-10000 nits for the reference display, but we
|
||||
// want to map 1.0 to |sdr_white_level| nits so we need to scale accordingly.
|
||||
const double w = 10000. / sdr_white_level;
|
||||
// Distribute scaling factor W by scaling A and B with X ^ (1/F):
|
||||
// ((A + Bx^C) / (D + Ex^C))^F * W = ((A + Bx^C) / (D + Ex^C) * W^(1/F))^F
|
||||
// See https://crbug.com/1058580#c32 for discussion.
|
||||
skcms_TransferFunction fn = SkNamedTransferFn::kPQ;
|
||||
const double ws = pow(w, 1. / fn.f);
|
||||
fn.a = ws * fn.a;
|
||||
fn.b = ws * fn.b;
|
||||
return fn;
|
||||
}
|
||||
|
||||
} // namespace uirenderer
|
||||
} // namespace android
|
||||
|
||||
@@ -126,6 +126,7 @@ struct Lab {
|
||||
|
||||
Lab sRGBToLab(SkColor color);
|
||||
SkColor LabToSRGB(const Lab& lab, SkAlpha alpha);
|
||||
skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level = 0.f);
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
Reference in New Issue
Block a user