Merge "hdr: rename OMX format for 10-bit YUV to Y410"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ef5064c..cce0579 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1463,10 +1463,8 @@
printf("========================================================\n");
}
-// This method collects dumpsys for telephony debugging only
-static void DumpstateTelephonyOnly() {
- DurationReporter duration_reporter("DUMPSTATE");
-
+// This method collects common dumpsys for telephony and wifi
+static void DumpstateRadioCommon() {
DumpIpTablesAsRoot();
if (!DropRootUser()) {
@@ -1482,6 +1480,13 @@
RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
CommandOptions::WithTimeout(10).Build());
+}
+
+// This method collects dumpsys for telephony debugging only
+static void DumpstateTelephonyOnly() {
+ DurationReporter duration_reporter("DUMPSTATE");
+
+ DumpstateRadioCommon();
RunCommand("SYSTEM PROPERTIES", {"getprop"});
@@ -1505,6 +1510,26 @@
printf("========================================================\n");
}
+// This method collects dumpsys for wifi debugging only
+static void DumpstateWifiOnly() {
+ DurationReporter duration_reporter("DUMPSTATE");
+
+ DumpstateRadioCommon();
+
+ printf("========================================================\n");
+ printf("== Android Framework Services\n");
+ printf("========================================================\n");
+
+ RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
+
+ printf("========================================================\n");
+ printf("== dumpstate: done (id %d)\n", ds.id_);
+ printf("========================================================\n");
+}
+
void Dumpstate::DumpstateBoard() {
DurationReporter duration_reporter("dumpstate_board()");
printf("========================================================\n");
@@ -1751,6 +1776,7 @@
bool show_header_only = false;
bool do_start_service = false;
bool telephony_only = false;
+ bool wifi_only = false;
int dup_stdout_fd;
int dup_stderr_fd;
@@ -1823,6 +1849,9 @@
do_zip_file = 1;
} else if (ds.extra_options_ == "bugreporttelephony") {
telephony_only = true;
+ } else if (ds.extra_options_ == "bugreportwifi") {
+ wifi_only = true;
+ do_zip_file = 1;
} else {
MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
}
@@ -1943,6 +1972,8 @@
if (telephony_only) {
ds.base_name_ += "-telephony";
+ } else if (wifi_only) {
+ ds.base_name_ += "-wifi";
}
if (do_fb) {
@@ -2052,6 +2083,8 @@
if (telephony_only) {
DumpstateTelephonyOnly();
ds.DumpstateBoard();
+ } else if (wifi_only) {
+ DumpstateWifiOnly();
} else {
// Dumps systrace right away, otherwise it will be filled with unnecessary events.
// First try to dump anrd trace if the daemon is running. Otherwise, dump
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 0653af6..950c9a0 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -2396,7 +2396,7 @@
// TODO(71871109): Validate filePath.
// 1. Seek to the next page boundary beyond the end of the file.
- ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY | O_APPEND));
+ ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY));
if (wfd.get() < 0) {
return error("Failed to open " + filePath + ": " + strerror(errno));
}
@@ -2405,7 +2405,11 @@
return error("Failed to stat " + filePath + ": " + strerror(errno));
}
// fsverity starts from the block boundary.
- if (lseek(wfd.get(), (st.st_size + kVerityPageSize - 1) / kVerityPageSize, SEEK_SET) < 0) {
+ off_t padding = kVerityPageSize - st.st_size % kVerityPageSize;
+ if (padding == kVerityPageSize) {
+ padding = 0;
+ }
+ if (lseek(wfd.get(), st.st_size + padding, SEEK_SET) < 0) {
return error("Failed to lseek " + filePath + ": " + strerror(errno));
}
@@ -2414,18 +2418,20 @@
if (size < 0) {
return error("Failed to get ashmem size: " + std::to_string(size));
}
- void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, wfd.get(), 0);
+ void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0);
if (data == MAP_FAILED) {
return error("Failed to mmap the ashmem: " + std::string(strerror(errno)));
}
+ char* cursor = reinterpret_cast<char*>(data);
int remaining = size;
while (remaining > 0) {
- int ret = TEMP_FAILURE_RETRY(write(wfd.get(), data, remaining));
+ int ret = TEMP_FAILURE_RETRY(write(wfd.get(), cursor, remaining));
if (ret < 0) {
munmap(data, size);
return error("Failed to write to " + filePath + " (" + std::to_string(remaining) +
+ "/" + std::to_string(size) + "): " + strerror(errno));
}
+ cursor += ret;
remaining -= ret;
}
munmap(data, size);
diff --git a/data/etc/android.hardware.camera.ar.xml b/data/etc/android.hardware.camera.ar.xml
new file mode 100644
index 0000000..2fc3280
--- /dev/null
+++ b/data/etc/android.hardware.camera.ar.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<!-- This is the set of features required for a camera2 device that supports the motion tracking
+ feature -->
+<permissions>
+ <feature name="android.hardware.camera.any" />
+ <feature name="android.hardware.camera.ar" />
+</permissions>
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index 76efac9..dc5cdab 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -240,6 +240,7 @@
OMX_Video_ControlRateConstant,
OMX_Video_ControlRateVariableSkipFrames,
OMX_Video_ControlRateConstantSkipFrames,
+ OMX_Video_ControlRateConstantQuality,
OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_Video_ControlRateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_Video_ControlRateMax = 0x7FFFFFFF
@@ -254,14 +255,20 @@
* nVersion : OMX spec version info
* nPortIndex : Port that this struct applies to
* eControlRate : Control rate type enum
- * nTargetBitrate : Target bitrate to encode with
+ * nTargetBitrate : Target bitrate to encode with (used when eControlRate is
+ * not OMX_Video_ControlRateConstantQuality)
+ * nQualityFactor : Quality to encode with (used when eControlRate is
+ * OMX_Video_ControlRateConstantQuality only)
*/
typedef struct OMX_VIDEO_PARAM_BITRATETYPE {
OMX_U32 nSize;
OMX_VERSIONTYPE nVersion;
OMX_U32 nPortIndex;
OMX_VIDEO_CONTROLRATETYPE eControlRate;
- OMX_U32 nTargetBitrate;
+ union {
+ OMX_U32 nTargetBitrate;
+ OMX_U32 nQualityFactor;
+ };
} OMX_VIDEO_PARAM_BITRATETYPE;
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 60ec38c..153d35a 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -57,8 +57,7 @@
for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
bits = bits | bit;
}
- // Return only the overlapping bits.
- return bits & ~getValid10UsageBits();
+ return bits;
}();
return valid11UsageBits;
}
@@ -71,7 +70,7 @@
Mapper::Mapper()
{
- mMapper = IMapper::getService();
+ mMapper = hardware::graphics::mapper::V2_0::IMapper::getService();
if (mMapper == nullptr) {
LOG_ALWAYS_FATAL("gralloc-mapper is missing");
}
@@ -80,7 +79,7 @@
}
// IMapper 2.1 is optional
- mMapperV2_1 = hardware::graphics::mapper::V2_1::IMapper::castFrom(mMapper);
+ mMapperV2_1 = IMapper::castFrom(mMapper);
}
Gralloc2::Error Mapper::validateBufferDescriptorInfo(
@@ -102,30 +101,34 @@
const IMapper::BufferDescriptorInfo& descriptorInfo,
BufferDescriptor* outDescriptor) const
{
- Error error;
-
- if (descriptorInfo.usage & getValid11UsageBits()) {
- // TODO(b/66900669): Use mMapperV2_1->createDescriptorV2_1().
- ALOGW("full support for new usage bits is unimplemented 0x%" PRIx64,
- descriptorInfo.usage & getValid11UsageBits());
- return Error::BAD_VALUE;
- }
-
- error = validateBufferDescriptorInfo(descriptorInfo);
+ Error error = validateBufferDescriptorInfo(descriptorInfo);
if (error != Error::NONE) {
return error;
}
- auto ret = mMapper->createDescriptor(descriptorInfo,
- [&](const auto& tmpError, const auto& tmpDescriptor)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
+ auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
- *outDescriptor = tmpDescriptor;
- });
+ *outDescriptor = tmpDescriptor;
+ };
+
+ hardware::Return<void> ret;
+ if (mMapperV2_1 != nullptr) {
+ ret = mMapperV2_1->createDescriptor_2_1(descriptorInfo, hidl_cb);
+ } else {
+ const hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo info = {
+ descriptorInfo.width,
+ descriptorInfo.height,
+ descriptorInfo.layerCount,
+ static_cast<hardware::graphics::common::V1_0::PixelFormat>(descriptorInfo.format),
+ descriptorInfo.usage,
+ };
+ ret = mMapper->createDescriptor(info, hidl_cb);
+ }
return (ret.isOk()) ? error : kTransactionError;
}
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index db3f10a..5a8dbda 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -30,11 +30,11 @@
namespace Gralloc2 {
using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::common::V1_0::PixelFormat;
using hardware::graphics::common::V1_1::BufferUsage;
+using hardware::graphics::common::V1_1::PixelFormat;
+using hardware::graphics::mapper::V2_1::IMapper;
using hardware::graphics::mapper::V2_0::BufferDescriptor;
using hardware::graphics::mapper::V2_0::Error;
-using hardware::graphics::mapper::V2_0::IMapper;
using hardware::graphics::mapper::V2_0::YCbCrLayout;
// A wrapper to IMapper
@@ -85,8 +85,8 @@
Error validateBufferDescriptorInfo(
const IMapper::BufferDescriptorInfo& descriptorInfo) const;
- sp<IMapper> mMapper;
- sp<hardware::graphics::mapper::V2_1::IMapper> mMapperV2_1;
+ sp<hardware::graphics::mapper::V2_0::IMapper> mMapper;
+ sp<IMapper> mMapperV2_1;
};
// A wrapper to IAllocator
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 94dfe6a..484e0ba 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -468,12 +468,17 @@
return HAL_DATASPACE_V0_SCRGB;
} else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
return HAL_DATASPACE_V0_SCRGB_LINEAR;
+ } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) {
+ return HAL_DATASPACE_BT2020_LINEAR;
+ } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) {
+ return HAL_DATASPACE_BT2020_PQ;
}
return dataSpace;
}
-// Return true if we stripped any EGL_GL_COLORSPACE_KHR attributes.
-static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
+// Return true if we stripped any EGL_GL_COLORSPACE_KHR or HDR metadata attributes.
+// Protect devices from attributes they don't recognize that are managed by Android
+static EGLBoolean stripAttributes(egl_display_ptr dp, const EGLint* attrib_list,
EGLint format,
std::vector<EGLint>& stripped_attrib_list) {
std::vector<EGLint> allowedColorSpaces;
@@ -494,33 +499,64 @@
break;
}
+ if (!attrib_list) return false;
+
bool stripped = false;
- if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
- for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
- if (attr[0] == EGL_GL_COLORSPACE_KHR) {
- EGLint colorSpace = attr[1];
- bool found = false;
- // Verify that color space is allowed
- for (auto it : allowedColorSpaces) {
- if (colorSpace == it) {
- found = true;
+ for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
+ switch (attr[0]) {
+ case EGL_GL_COLORSPACE_KHR: {
+ EGLint colorSpace = attr[1];
+ bool found = false;
+ // Verify that color space is allowed
+ for (auto it : allowedColorSpaces) {
+ if (colorSpace == it) {
+ found = true;
+ }
+ }
+ if (found && dp->haveExtension("EGL_KHR_gl_colorspace")) {
+ stripped = true;
+ } else {
+ stripped_attrib_list.push_back(attr[0]);
+ stripped_attrib_list.push_back(attr[1]);
}
}
- if (!found) {
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
+ case EGL_SMPTE2086_WHITE_POINT_X_EXT:
+ case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
+ case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
+ case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
+ if (dp->haveExtension("EGL_EXT_surface_SMPTE2086_metadata")) {
stripped = true;
} else {
stripped_attrib_list.push_back(attr[0]);
stripped_attrib_list.push_back(attr[1]);
}
- } else {
+ break;
+ case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
+ case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
+ if (dp->haveExtension("EGL_EXT_surface_CTA861_3_metadata")) {
+ stripped = true;
+ } else {
+ stripped_attrib_list.push_back(attr[0]);
+ stripped_attrib_list.push_back(attr[1]);
+ }
+ break;
+ default:
stripped_attrib_list.push_back(attr[0]);
stripped_attrib_list.push_back(attr[1]);
- }
+ break;
}
}
+
+ // Make sure there is at least one attribute
if (stripped) {
stripped_attrib_list.push_back(EGL_NONE);
- stripped_attrib_list.push_back(EGL_NONE);
}
return stripped;
}
@@ -544,10 +580,10 @@
// is available, so no need to verify.
found = true;
verify = false;
- } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear &&
+ } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT &&
dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
found = true;
- } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq &&
+ } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_PQ_EXT &&
dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
found = true;
} else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT &&
@@ -664,10 +700,43 @@
}
}
+EGLBoolean setSurfaceMetadata(egl_surface_t* s, NativeWindowType window,
+ const EGLint *attrib_list) {
+ // set any HDR metadata
+ bool smpte2086 = false;
+ bool cta8613 = false;
+ if (attrib_list == nullptr) return EGL_TRUE;
+
+ for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
+ smpte2086 |= s->setSmpte2086Attribute(attr[0], attr[1]);
+ cta8613 |= s->setCta8613Attribute(attr[0], attr[1]);
+ }
+ if (smpte2086) {
+ int err = native_window_set_buffers_smpte2086_metadata(window, s->getSmpte2086Metadata());
+ if (err != 0) {
+ ALOGE("error setting native window smpte2086 metadata: %s (%d)",
+ strerror(-err), err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return EGL_FALSE;
+ }
+ }
+ if (cta8613) {
+ int err = native_window_set_buffers_cta861_3_metadata(window, s->getCta8613Metadata());
+ if (err != 0) {
+ ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
+ strerror(-err), err);
+ native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+ return EGL_FALSE;
+ }
+ }
+ return EGL_TRUE;
+}
+
EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
NativeWindowType window,
const EGLint *attrib_list)
{
+ const EGLint *origAttribList = attrib_list;
clearError();
egl_connection_t* cnx = NULL;
@@ -705,7 +774,7 @@
}
std::vector<EGLint> strippedAttribList;
- if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
+ if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
// Had to modify the attribute list due to use of color space.
// Use modified list from here on.
attrib_list = strippedAttribList.data();
@@ -741,7 +810,11 @@
if (surface != EGL_NO_SURFACE) {
egl_surface_t* s =
new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
- return s;
+
+ if (setSurfaceMetadata(s, window, origAttribList)) {
+ return s;
+ }
+ eglDestroySurface(dpy, s);
}
// EGLSurface creation failed
@@ -802,7 +875,7 @@
// colorspace. We do need to filter out color spaces the
// driver doesn't know how to process.
std::vector<EGLint> strippedAttribList;
- if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) {
+ if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
// Had to modify the attribute list due to use of color space.
// Use modified list from here on.
attrib_list = strippedAttribList.data();
@@ -850,12 +923,14 @@
return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
egl_surface_t const * const s = get_surface(surface);
- if (attribute == EGL_GL_COLORSPACE_KHR) {
- *value = s->getColorSpace();
+ if (s->getColorSpaceAttribute(attribute, value)) {
+ return EGL_TRUE;
+ } else if (s->getSmpte2086Attribute(attribute, value)) {
+ return EGL_TRUE;
+ } else if (s->getCta8613Attribute(attribute, value)) {
return EGL_TRUE;
}
- return s->cnx->egl.eglQuerySurface(
- dp->disp.dpy, s->surface, attribute, value);
+ return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
}
void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 3c1edd1..0f36614 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -214,6 +214,23 @@
"EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 ");
}
+ bool hasHdrBoardConfig =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+
+ if (hasHdrBoardConfig) {
+ // hasHDRBoardConfig indicates the system is capable of supporting HDR content.
+ // Typically that means there is an HDR capable display attached, but could be
+ // support for attaching an HDR display. In either case, advertise support for
+ // HDR color spaces.
+ mExtensionString.append(
+ "EGL_EXT_gl_colorspace_bt2020_linear EGL_EXT_gl_colorspace_bt2020_pq ");
+ }
+
+ // Always advertise HDR metadata extensions since it's okay for an application
+ // to specify such information even though it may not be used by the system.
+ mExtensionString.append(
+ "EGL_EXT_surface_SMPTE2086_metadata EGL_EXT_surface_CTA861_3_metadata ");
+
char const* start = gExtensionString;
do {
// length of the extension name
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 72b4823..13b94b6 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -63,7 +63,9 @@
win(win),
cnx(cnx),
connected(true),
- colorSpace(colorSpace) {
+ colorSpace(colorSpace),
+ smpte2086_metadata({}),
+ cta861_3_metadata({}) {
if (win) {
win->incStrong(this);
}
@@ -86,6 +88,123 @@
}
}
+EGLBoolean egl_surface_t::setSmpte2086Attribute(EGLint attribute, EGLint value) {
+ switch (attribute) {
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
+ smpte2086_metadata.displayPrimaryRed.x = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
+ smpte2086_metadata.displayPrimaryRed.y = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
+ smpte2086_metadata.displayPrimaryGreen.x = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
+ smpte2086_metadata.displayPrimaryGreen.y = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
+ smpte2086_metadata.displayPrimaryBlue.x = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
+ smpte2086_metadata.displayPrimaryBlue.y = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_WHITE_POINT_X_EXT:
+ smpte2086_metadata.whitePoint.x = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
+ smpte2086_metadata.whitePoint.y = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
+ smpte2086_metadata.maxLuminance = value;
+ return EGL_TRUE;
+ case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
+ smpte2086_metadata.minLuminance = value;
+ return EGL_TRUE;
+ }
+ return EGL_FALSE;
+}
+
+EGLBoolean egl_surface_t::setCta8613Attribute(EGLint attribute, EGLint value) {
+ switch (attribute) {
+ case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
+ cta861_3_metadata.maxContentLightLevel = value;
+ return EGL_TRUE;
+ case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
+ cta861_3_metadata.maxFrameAverageLightLevel = value;
+ return EGL_TRUE;
+ }
+ return EGL_FALSE;
+}
+
+EGLBoolean egl_surface_t::getColorSpaceAttribute(EGLint attribute, EGLint* value) const {
+ if (attribute == EGL_GL_COLORSPACE_KHR) {
+ *value = colorSpace;
+ return EGL_TRUE;
+ }
+ return EGL_FALSE;
+}
+
+EGLBoolean egl_surface_t::getSmpte2086Attribute(EGLint attribute, EGLint *value) const {
+ switch (attribute) {
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryRed.x);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryRed.y);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.x);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.y);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.x);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.y);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_WHITE_POINT_X_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.x);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.y);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.maxLuminance);
+ return EGL_TRUE;
+ break;
+ case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
+ *value = *reinterpret_cast<const int*>(&smpte2086_metadata.minLuminance);
+ return EGL_TRUE;
+ break;
+ }
+ return EGL_FALSE;
+}
+
+EGLBoolean egl_surface_t::getCta8613Attribute(EGLint attribute, EGLint *value) const {
+ switch (attribute) {
+ case EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT:
+ *value = *reinterpret_cast<const int*>(&cta861_3_metadata.maxContentLightLevel);
+ return EGL_TRUE;
+ break;
+ case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
+ *value = *reinterpret_cast<const int*>(&cta861_3_metadata.maxFrameAverageLightLevel);
+ return EGL_TRUE;
+ break;
+ }
+ return EGL_FALSE;
+}
+
void egl_surface_t::terminate() {
disconnect();
egl_object_t::terminate();
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 7c3075c..a9020a1 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -137,6 +137,13 @@
ANativeWindow* getNativeWindow() { return win; }
ANativeWindow* getNativeWindow() const { return win; }
EGLint getColorSpace() const { return colorSpace; }
+ EGLBoolean setSmpte2086Attribute(EGLint attribute, EGLint value);
+ EGLBoolean setCta8613Attribute(EGLint attribute, EGLint value);
+ EGLBoolean getColorSpaceAttribute(EGLint attribute, EGLint* value) const;
+ EGLBoolean getSmpte2086Attribute(EGLint attribute, EGLint* value) const;
+ EGLBoolean getCta8613Attribute(EGLint attribute, EGLint* value) const;
+ const android_smpte2086_metadata* getSmpte2086Metadata() const { return &smpte2086_metadata; }
+ const android_cta861_3_metadata* getCta8613Metadata() const { return &cta861_3_metadata; }
// Try to keep the order of these fields and size unchanged. It's not public API, but
// it's not hard to imagine native games accessing them.
@@ -150,6 +157,8 @@
bool connected;
void disconnect();
EGLint colorSpace;
+ android_smpte2086_metadata smpte2086_metadata;
+ android_cta861_3_metadata cta861_3_metadata;
};
class egl_context_t: public egl_object_t {
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index b67a053..8bb74a2 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -53,7 +53,20 @@
static bool hasWideColorDisplay =
getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+static bool hasHdrDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+
+union FlexAttribute {
+ EGLint uint_value;
+ float float_value;
+};
+
class EGLTest : public ::testing::Test {
+public:
+ void get8BitConfig(EGLConfig& config);
+ void addOptionalWindowMetadata(std::vector<EGLint>& attrs);
+ void checkOptionalWindowMetadata(EGLSurface eglSurface);
+
protected:
EGLDisplay mEglDisplay;
@@ -365,6 +378,261 @@
EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}
+void EGLTest::get8BitConfig(EGLConfig& config) {
+ EGLint numConfigs;
+ EGLBoolean success;
+
+ // Use 8-bit to keep focus on colorspace aspect
+ const EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ EGLint components[4];
+ EGLint value;
+ eglGetConfigAttrib(mEglDisplay, config, EGL_CONFIG_ID, &value);
+
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+ // Verify component sizes on config match what was asked for.
+ EXPECT_EQ(components[0], 8);
+ EXPECT_EQ(components[1], 8);
+ EXPECT_EQ(components[2], 8);
+ EXPECT_EQ(components[3], 8);
+}
+
+void EGLTest::addOptionalWindowMetadata(std::vector<EGLint>& attrs) {
+ FlexAttribute data;
+ if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT);
+ data.float_value = 0.640;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT);
+ data.float_value = 0.330;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT);
+ data.float_value = 0.290;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT);
+ data.float_value = 0.600;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT);
+ data.float_value = 0.150;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT);
+ data.float_value = 0.060;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_WHITE_POINT_X_EXT);
+ data.float_value = 0.3127;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_WHITE_POINT_Y_EXT);
+ data.float_value = 0.3290;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_MAX_LUMINANCE_EXT);
+ data.float_value = 300.0;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_SMPTE2086_MIN_LUMINANCE_EXT);
+ data.float_value = 0.7;
+ attrs.push_back(data.uint_value);
+ }
+
+ if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
+ attrs.push_back(EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT);
+ data.float_value = 300.0;
+ attrs.push_back(data.uint_value);
+ attrs.push_back(EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT);
+ data.float_value = 75.0;
+ attrs.push_back(data.uint_value);
+ }
+}
+
+void EGLTest::checkOptionalWindowMetadata(EGLSurface eglSurface) {
+ EGLBoolean success;
+ EGLint value;
+ FlexAttribute expected;
+
+ if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_SMPTE2086_metadata")) {
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.640;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.330;
+ ASSERT_EQ(expected.uint_value, value);
+ ASSERT_EQ(0, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.290;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.600;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.150;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.060;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_X_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.3127;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_WHITE_POINT_Y_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.3290;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MAX_LUMINANCE_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 300.0;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_SMPTE2086_MIN_LUMINANCE_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 0.7;
+ ASSERT_EQ(expected.uint_value, value);
+ }
+
+ if (hasEglExtension(mEglDisplay, "EGL_EXT_surface_CTA861_3_metadata")) {
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 300.0;
+ ASSERT_EQ(expected.uint_value, value);
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ expected.float_value = 75.0;
+ ASSERT_EQ(expected.uint_value, value);
+ }
+}
+
+TEST_F(EGLTest, EGLBT2020Linear) {
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasHdrDisplay) {
+ // skip this test if device does not have HDR display
+ RecordProperty("hasHdrDisplay", false);
+ return;
+ }
+
+ // Test that bt2020 linear extension exists
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
+ << "EGL_EXT_gl_colorspace_bt2020_linear extension not available";
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ std::vector<EGLint> winAttrs;
+ winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
+ winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
+
+ ASSERT_NO_FATAL_FAILURE(addOptionalWindowMetadata(winAttrs));
+
+ winAttrs.push_back(EGL_NONE);
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ EGLint value;
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
+
+ ASSERT_NO_FATAL_FAILURE(checkOptionalWindowMetadata(eglSurface));
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLBT2020PQ) {
+ EGLConfig config;
+ EGLBoolean success;
+
+ if (!hasHdrDisplay) {
+ // skip this test if device does not have HDR display
+ RecordProperty("hasHdrDisplay", false);
+ return;
+ }
+
+ // Test that bt2020-pq extension exists
+ ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
+ << "EGL_EXT_gl_colorspace_bt2020_pq extension not available";
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+ std::vector<EGLint> winAttrs;
+ winAttrs.push_back(EGL_GL_COLORSPACE_KHR);
+ winAttrs.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
+
+ ASSERT_NO_FATAL_FAILURE(addOptionalWindowMetadata(winAttrs));
+
+ winAttrs.push_back(EGL_NONE);
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs.data());
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ EGLint value;
+ success = eglQuerySurface(mEglDisplay, eglSurface, EGL_GL_COLORSPACE_KHR, &value);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(EGL_GL_COLORSPACE_BT2020_PQ_EXT, value);
+
+ ASSERT_NO_FATAL_FAILURE(checkOptionalWindowMetadata(eglSurface));
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
TEST_F(EGLTest, EGLConfigFP16) {
EGLint numConfigs;
EGLConfig config;
@@ -372,13 +640,13 @@
if (!hasWideColorDisplay) {
// skip this test if device does not have wide-color display
- std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
+ RecordProperty("hasWideColorDisplay", false);
return;
}
ASSERT_TRUE(hasEglExtension(mEglDisplay, "EGL_EXT_pixel_format_float"));
- EGLint attrs[] = {
+ const EGLint attrs[] = {
// clang-format off
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
@@ -387,7 +655,7 @@
EGL_BLUE_SIZE, 16,
EGL_ALPHA_SIZE, 16,
EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
- EGL_NONE, EGL_NONE
+ EGL_NONE,
// clang-format on
};
success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
@@ -437,7 +705,7 @@
TEST_F(EGLTest, EGLNoConfigContext) {
if (!hasWideColorDisplay) {
// skip this test if device does not have wide-color display
- std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
+ RecordProperty("hasWideColorDisplay", false);
return;
}
@@ -475,11 +743,11 @@
if (!hasWideColorDisplay) {
// skip this test if device does not have wide-color display
- std::cerr << "[ ] Device does not support wide-color, test skipped" << std::endl;
+ RecordProperty("hasWideColorDisplay", false);
return;
}
- EGLint attrs[] = {
+ const EGLint attrs[] = {
// clang-format off
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index ba9eaf6..4d4c9fc 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -822,7 +822,7 @@
getColor());
engine.setSourceDataSpace(mCurrentState.dataSpace);
- if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_PQ &&
+ if (mCurrentState.dataSpace == HAL_DATASPACE_BT2020_ITU_PQ &&
mConsumer->getCurrentApi() == NATIVE_WINDOW_API_MEDIA &&
getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102) {
engine.setSourceY410BT2020(true);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 323cec7..5133bac 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -326,11 +326,12 @@
if (usesWideColor()) {
Description wideColorState = mState;
- switch (mDataSpace) {
+ switch (int(mDataSpace)) {
case HAL_DATASPACE_DISPLAY_P3:
// input matches output
break;
case HAL_DATASPACE_BT2020_PQ:
+ case HAL_DATASPACE_BT2020_ITU_PQ:
wideColorState.setColorMatrix(mState.getColorMatrix() * mBt2020ToDisplayP3);
wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084);
wideColorState.setOutputTransferFunction(Description::TransferFunction::SRGB);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 974a261..d8740d9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1816,8 +1816,13 @@
if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
return HAL_DATASPACE_DISPLAY_P3;
}
- if (!hasHdr && (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ)) {
- return HAL_DATASPACE_DISPLAY_P3;
+ if (!hasHdr) {
+ if (a == HAL_DATASPACE_BT2020_PQ || b == HAL_DATASPACE_BT2020_PQ) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+ if (a == HAL_DATASPACE_BT2020_ITU_PQ || b == HAL_DATASPACE_BT2020_ITU_PQ) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
}
return HAL_DATASPACE_V0_SRGB;
@@ -1900,7 +1905,8 @@
"display %zd: %d", displayId, result);
}
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- if (layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ &&
+ if ((layer->getDataSpace() == HAL_DATASPACE_BT2020_PQ ||
+ layer->getDataSpace() == HAL_DATASPACE_BT2020_ITU_PQ) &&
!displayDevice->getHdrSupport()) {
layer->forceClientComposition(hwcId);
}
diff --git a/services/vr/hardware_composer/vr_hwc.rc b/services/vr/hardware_composer/vr_hwc.rc
index 52d4da8..6f930a8 100644
--- a/services/vr/hardware_composer/vr_hwc.rc
+++ b/services/vr/hardware_composer/vr_hwc.rc
@@ -1,5 +1,5 @@
service vr_hwc /system/bin/vr_hwc
- class hal
+ class hal animation
user system
group system graphics
onrestart restart surfaceflinger
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index c9faf28..7f4f2c4 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -68,10 +68,14 @@
"vulkan_headers",
],
shared_libs: [
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore-utils",
"libziparchive",
"libhardware",
"libsync",
"libbase",
+ "libhidlbase",
+ "libhidltransport",
"liblog",
"libui",
"libgraphicsenv",
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b27d1b7..c8e7bd9 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -27,6 +27,8 @@
#include <log/log.h>
#include <android/dlext.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
#include <cutils/properties.h>
#include <graphicsenv/GraphicsEnv.h>
#include <utils/Vector.h>
@@ -36,6 +38,9 @@
#include "driver.h"
#include "stubhal.h"
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+
// TODO(b/37049319) Get this from a header once one exists
extern "C" {
android_namespace_t* android_get_exported_namespace(const char*);
@@ -826,6 +831,14 @@
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
+ bool hdrBoardConfig =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(
+ false);
+ if (hdrBoardConfig) {
+ loader_extensions.push_back({VK_EXT_HDR_METADATA_EXTENSION_NAME,
+ VK_EXT_HDR_METADATA_SPEC_VERSION});
+ }
+
VkPhysicalDevicePresentationPropertiesANDROID presentation_properties;
if (QueryPresentationProperties(physicalDevice, &presentation_properties) &&
presentation_properties.sharedImage) {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 03e6ee0..9fbde8c 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1650,15 +1650,39 @@
}
VKAPI_ATTR void SetHdrMetadataEXT(
- VkDevice device,
+ VkDevice,
uint32_t swapchainCount,
const VkSwapchainKHR* pSwapchains,
const VkHdrMetadataEXT* pHdrMetadataEXTs) {
- // TODO: courtneygo: implement actual function
- (void)device;
- (void)swapchainCount;
- (void)pSwapchains;
- (void)pHdrMetadataEXTs;
+
+ for (uint32_t idx = 0; idx < swapchainCount; idx++) {
+ Swapchain* swapchain = SwapchainFromHandle(pSwapchains[idx]);
+ if (!swapchain)
+ continue;
+
+ if (swapchain->surface.swapchain_handle != pSwapchains[idx]) continue;
+
+ ANativeWindow* window = swapchain->surface.window.get();
+
+ VkHdrMetadataEXT vulkanMetadata = pHdrMetadataEXTs[idx];
+ const android_smpte2086_metadata smpteMetdata = {
+ {vulkanMetadata.displayPrimaryRed.x,
+ vulkanMetadata.displayPrimaryRed.y},
+ {vulkanMetadata.displayPrimaryGreen.x,
+ vulkanMetadata.displayPrimaryGreen.y},
+ {vulkanMetadata.displayPrimaryBlue.x,
+ vulkanMetadata.displayPrimaryBlue.y},
+ {vulkanMetadata.whitePoint.x, vulkanMetadata.whitePoint.y},
+ vulkanMetadata.maxLuminance,
+ vulkanMetadata.minLuminance};
+ native_window_set_buffers_smpte2086_metadata(window, &smpteMetdata);
+
+ const android_cta861_3_metadata cta8613Metadata = {
+ vulkanMetadata.maxContentLightLevel,
+ vulkanMetadata.maxFrameAverageLightLevel};
+ native_window_set_buffers_cta861_3_metadata(window, &cta8613Metadata);
+ }
+
return;
}