Add hdr attributes to setSurfaceAttr

Keep original copies of hdr metadata to return to the user if requested.
Scale integer values prior to sending to system.

Test: --deqp-case=dEQP-EGL.functional.hdr_color.*
Bug: 72491459, 72828483

Change-Id: I86ed35cf96d740ac230cc10acde322acbeffe847
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 26ae13d..b00602c 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -479,8 +479,8 @@
 // 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) {
+                                  EGLint format,
+                                  std::vector<EGLint>& stripped_attrib_list) {
     std::vector<EGLint> allowedColorSpaces;
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
@@ -712,7 +712,8 @@
         cta8613 |= s->setCta8613Attribute(attr[0], attr[1]);
     }
     if (smpte2086) {
-        int err = native_window_set_buffers_smpte2086_metadata(window, s->getSmpte2086Metadata());
+        android_smpte2086_metadata metadata = s->getSmpte2086Metadata();
+        int err = native_window_set_buffers_smpte2086_metadata(window, &metadata);
         if (err != 0) {
             ALOGE("error setting native window smpte2086 metadata: %s (%d)",
                   strerror(-err), err);
@@ -721,7 +722,8 @@
         }
     }
     if (cta8613) {
-        int err = native_window_set_buffers_cta861_3_metadata(window, s->getCta8613Metadata());
+        android_cta861_3_metadata metadata = s->getCta8613Metadata();
+        int err = native_window_set_buffers_cta861_3_metadata(window, &metadata);
         if (err != 0) {
             ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
                   strerror(-err), err);
@@ -1578,7 +1580,11 @@
         return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
     }
 
-    if (s->cnx->egl.eglSurfaceAttrib) {
+    if (s->setSmpte2086Attribute(attribute, value)) {
+        return EGL_TRUE;
+    } else if (s->setCta8613Attribute(attribute, value)) {
+        return EGL_TRUE;
+    } else if (s->cnx->egl.eglSurfaceAttrib) {
         return s->cnx->egl.eglSurfaceAttrib(
                 dp->disp.dpy, s->surface, attribute, value);
     }
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 13b94b6..b68fd61 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -64,8 +64,8 @@
         cnx(cnx),
         connected(true),
         colorSpace(colorSpace),
-        smpte2086_metadata({}),
-        cta861_3_metadata({}) {
+        egl_smpte2086_metadata({}),
+        egl_cta861_3_metadata({}) {
     if (win) {
         win->incStrong(this);
     }
@@ -90,36 +90,35 @@
 
 EGLBoolean egl_surface_t::setSmpte2086Attribute(EGLint attribute, EGLint value) {
     switch (attribute) {
-            break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT:
-            smpte2086_metadata.displayPrimaryRed.x = value;
+            egl_smpte2086_metadata.displayPrimaryRed.x = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
-            smpte2086_metadata.displayPrimaryRed.y = value;
+            egl_smpte2086_metadata.displayPrimaryRed.y = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
-            smpte2086_metadata.displayPrimaryGreen.x = value;
+            egl_smpte2086_metadata.displayPrimaryGreen.x = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
-            smpte2086_metadata.displayPrimaryGreen.y = value;
+            egl_smpte2086_metadata.displayPrimaryGreen.y = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
-            smpte2086_metadata.displayPrimaryBlue.x = value;
+            egl_smpte2086_metadata.displayPrimaryBlue.x = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
-            smpte2086_metadata.displayPrimaryBlue.y = value;
+            egl_smpte2086_metadata.displayPrimaryBlue.y = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_WHITE_POINT_X_EXT:
-            smpte2086_metadata.whitePoint.x = value;
+            egl_smpte2086_metadata.whitePoint.x = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
-            smpte2086_metadata.whitePoint.y = value;
+            egl_smpte2086_metadata.whitePoint.y = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
-            smpte2086_metadata.maxLuminance = value;
+            egl_smpte2086_metadata.maxLuminance = value;
             return EGL_TRUE;
         case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
-            smpte2086_metadata.minLuminance = value;
+            egl_smpte2086_metadata.minLuminance = value;
             return EGL_TRUE;
     }
     return EGL_FALSE;
@@ -128,15 +127,39 @@
 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;
+            egl_cta861_3_metadata.maxContentLightLevel = value;
             return EGL_TRUE;
         case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
-            cta861_3_metadata.maxFrameAverageLightLevel = value;
+            egl_cta861_3_metadata.maxFrameAverageLightLevel = value;
             return EGL_TRUE;
     }
     return EGL_FALSE;
 }
 
+const android_smpte2086_metadata egl_surface_t::getSmpte2086Metadata() {
+    android_smpte2086_metadata metadata;
+    metadata.displayPrimaryRed.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.x) / EGL_METADATA_SCALING_EXT;
+    metadata.displayPrimaryRed.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryRed.y) / EGL_METADATA_SCALING_EXT;
+    metadata.displayPrimaryGreen.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.x) / EGL_METADATA_SCALING_EXT;
+    metadata.displayPrimaryGreen.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryGreen.y) / EGL_METADATA_SCALING_EXT;
+    metadata.displayPrimaryBlue.x = static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.x) / EGL_METADATA_SCALING_EXT;
+    metadata.displayPrimaryBlue.y = static_cast<float>(egl_smpte2086_metadata.displayPrimaryBlue.y) / EGL_METADATA_SCALING_EXT;
+    metadata.whitePoint.x = static_cast<float>(egl_smpte2086_metadata.whitePoint.x) / EGL_METADATA_SCALING_EXT;
+    metadata.whitePoint.y = static_cast<float>(egl_smpte2086_metadata.whitePoint.y) / EGL_METADATA_SCALING_EXT;
+    metadata.maxLuminance = static_cast<float>(egl_smpte2086_metadata.maxLuminance) / EGL_METADATA_SCALING_EXT;
+    metadata.minLuminance = static_cast<float>(egl_smpte2086_metadata.minLuminance) / EGL_METADATA_SCALING_EXT;
+
+    return metadata;
+}
+
+const android_cta861_3_metadata egl_surface_t::getCta8613Metadata() {
+    android_cta861_3_metadata metadata;
+    metadata.maxContentLightLevel = static_cast<float>(egl_cta861_3_metadata.maxContentLightLevel) / EGL_METADATA_SCALING_EXT;
+    metadata.maxFrameAverageLightLevel = static_cast<float>(egl_cta861_3_metadata.maxFrameAverageLightLevel) / EGL_METADATA_SCALING_EXT;
+    return metadata;
+}
+
+
 EGLBoolean egl_surface_t::getColorSpaceAttribute(EGLint attribute, EGLint* value) const {
     if (attribute == EGL_GL_COLORSPACE_KHR) {
         *value = colorSpace;
@@ -148,43 +171,43 @@
 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);
+            *value = egl_smpte2086_metadata.displayPrimaryRed.x;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryRed.y);
+            *value = egl_smpte2086_metadata.displayPrimaryRed.y;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.x);
+            *value = egl_smpte2086_metadata.displayPrimaryGreen.x;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryGreen.y);
+            *value = egl_smpte2086_metadata.displayPrimaryGreen.y;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.x);
+            *value = egl_smpte2086_metadata.displayPrimaryBlue.x;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.displayPrimaryBlue.y);
+            *value = egl_smpte2086_metadata.displayPrimaryBlue.y;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_WHITE_POINT_X_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.x);
+            *value = egl_smpte2086_metadata.whitePoint.x;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_WHITE_POINT_Y_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.whitePoint.y);
+            *value = egl_smpte2086_metadata.whitePoint.y;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_MAX_LUMINANCE_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.maxLuminance);
+            *value = egl_smpte2086_metadata.maxLuminance;
             return EGL_TRUE;
             break;
         case EGL_SMPTE2086_MIN_LUMINANCE_EXT:
-            *value = *reinterpret_cast<const int*>(&smpte2086_metadata.minLuminance);
+            *value = egl_smpte2086_metadata.minLuminance;
             return EGL_TRUE;
             break;
     }
@@ -194,11 +217,11 @@
 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);
+            *value = egl_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);
+            *value = egl_cta861_3_metadata.maxFrameAverageLightLevel;
             return EGL_TRUE;
             break;
     }
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index a9020a1..bda91bb 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -142,8 +142,8 @@
     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; }
+    const android_smpte2086_metadata getSmpte2086Metadata();
+    const android_cta861_3_metadata getCta8613Metadata();
 
     // 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.
@@ -157,8 +157,27 @@
     bool connected;
     void disconnect();
     EGLint colorSpace;
-    android_smpte2086_metadata smpte2086_metadata;
-    android_cta861_3_metadata cta861_3_metadata;
+
+    struct egl_xy_color {
+        EGLint x;
+        EGLint y;
+    };
+
+    struct egl_smpte2086_metadata {
+        struct egl_xy_color displayPrimaryRed;
+        struct egl_xy_color displayPrimaryGreen;
+        struct egl_xy_color displayPrimaryBlue;
+        struct egl_xy_color whitePoint;
+        EGLint maxLuminance;
+        EGLint minLuminance;
+    };
+
+    struct egl_cta861_3_metadata {
+        EGLint maxContentLightLevel;
+        EGLint maxFrameAverageLightLevel;
+    };
+    egl_smpte2086_metadata egl_smpte2086_metadata;
+    egl_cta861_3_metadata egl_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 8bb74a2..9ffe036 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -50,17 +50,14 @@
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 
+#define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
+
 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);
@@ -425,108 +422,81 @@
 }
 
 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(METADATA_SCALE(0.640));
         attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT);
-        data.float_value = 0.330;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.330));
         attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT);
-        data.float_value = 0.290;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.290));
         attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT);
-        data.float_value = 0.600;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.600));
         attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT);
-        data.float_value = 0.150;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.150));
         attrs.push_back(EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT);
-        data.float_value = 0.060;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.060));
         attrs.push_back(EGL_SMPTE2086_WHITE_POINT_X_EXT);
-        data.float_value = 0.3127;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.3127));
         attrs.push_back(EGL_SMPTE2086_WHITE_POINT_Y_EXT);
-        data.float_value = 0.3290;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.3290));
         attrs.push_back(EGL_SMPTE2086_MAX_LUMINANCE_EXT);
-        data.float_value = 300.0;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(300));
         attrs.push_back(EGL_SMPTE2086_MIN_LUMINANCE_EXT);
-        data.float_value = 0.7;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(0.7));
     }
 
     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(METADATA_SCALE(300));
         attrs.push_back(EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT);
-        data.float_value = 75.0;
-        attrs.push_back(data.uint_value);
+        attrs.push_back(METADATA_SCALE(75));
     }
 }
 
 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);
+        ASSERT_EQ(METADATA_SCALE(0.640), 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);
+        ASSERT_EQ(METADATA_SCALE(0.330), 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);
+        ASSERT_EQ(METADATA_SCALE(0.290), 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);
+        ASSERT_EQ(METADATA_SCALE(0.600), 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);
+        ASSERT_EQ(METADATA_SCALE(0.150), 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);
+        ASSERT_EQ(METADATA_SCALE(0.060), 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);
+        ASSERT_EQ(METADATA_SCALE(0.3127), 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);
+        ASSERT_EQ(METADATA_SCALE(0.3290), 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);
+        ASSERT_EQ(METADATA_SCALE(300.0), 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);
+        ASSERT_EQ(METADATA_SCALE(0.7), 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);
+        ASSERT_EQ(METADATA_SCALE(300.0), 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);
+        ASSERT_EQ(METADATA_SCALE(75.0), value);
     }
 }