Merge "Add dump of hdr event history" into main
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index b302f52..e2a2927 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <fts.h>
 #include <inttypes.h>
+#include <linux/fsverity.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,6 +52,7 @@
 #include <android-base/unique_fd.h>
 #include <cutils/ashmem.h>
 #include <cutils/fs.h>
+#include <cutils/misc.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <linux/quota.h>
@@ -84,6 +86,8 @@
 using android::base::ParseUint;
 using android::base::Split;
 using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::os::ParcelFileDescriptor;
 using std::endl;
 
 namespace android {
@@ -229,6 +233,14 @@
     return ok();
 }
 
+binder::Status checkUidInAppRange(int32_t appUid) {
+    if (FIRST_APPLICATION_UID <= appUid && appUid <= LAST_APPLICATION_UID) {
+        return ok();
+    }
+    return exception(binder::Status::EX_ILLEGAL_ARGUMENT,
+                     StringPrintf("UID %d is outside of the range", appUid));
+}
+
 #define ENFORCE_UID(uid) {                                  \
     binder::Status status = checkUid((uid));                \
     if (!status.isOk()) {                                   \
@@ -283,6 +295,14 @@
         }                                                      \
     }
 
+#define CHECK_ARGUMENT_UID_IN_APP_RANGE(uid)               \
+    {                                                      \
+        binder::Status status = checkUidInAppRange((uid)); \
+        if (!status.isOk()) {                              \
+            return status;                                 \
+        }                                                  \
+    }
+
 #ifdef GRANULAR_LOCKS
 
 /**
@@ -383,6 +403,33 @@
 
 }  // namespace
 
+binder::Status InstalldNativeService::FsveritySetupAuthToken::authenticate(
+        const ParcelFileDescriptor& authFd, int32_t appUid, int32_t userId) {
+    int open_flags = fcntl(authFd.get(), F_GETFL);
+    if (open_flags < 0) {
+        return exception(binder::Status::EX_SERVICE_SPECIFIC, "fcntl failed");
+    }
+    if ((open_flags & O_ACCMODE) != O_WRONLY && (open_flags & O_ACCMODE) != O_RDWR) {
+        return exception(binder::Status::EX_SECURITY, "Received FD with unexpected open flag");
+    }
+    if (fstat(authFd.get(), &this->mStatFromAuthFd) < 0) {
+        return exception(binder::Status::EX_SERVICE_SPECIFIC, "fstat failed");
+    }
+    if (!S_ISREG(this->mStatFromAuthFd.st_mode)) {
+        return exception(binder::Status::EX_SECURITY, "Not a regular file");
+    }
+    // Don't accept a file owned by a different app.
+    uid_t uid = multiuser_get_uid(userId, appUid);
+    if (this->mStatFromAuthFd.st_uid != uid) {
+        return exception(binder::Status::EX_SERVICE_SPECIFIC, "File not owned by appUid");
+    }
+    return ok();
+}
+
+bool InstalldNativeService::FsveritySetupAuthToken::isSameStat(const struct stat& st) const {
+    return memcmp(&st, &mStatFromAuthFd, sizeof(st)) == 0;
+}
+
 status_t InstalldNativeService::start() {
     IPCThreadState::self()->disableBackgroundScheduling(true);
     status_t ret = BinderService<InstalldNativeService>::publish();
@@ -3857,5 +3904,84 @@
     return *_aidl_return == -1 ? error() : ok();
 }
 
+// Creates an auth token to be used in enableFsverity. This token is really to store a proof that
+// the caller can write to a file, represented by the authFd. Effectively, system_server as the
+// attacker-in-the-middle cannot enable fs-verity on arbitrary app files. If the FD is not writable,
+// return null.
+//
+// appUid and userId are passed for additional ownership check, such that one app can not be
+// authenticated for another app's file. These parameters are assumed trusted for this purpose of
+// consistency check.
+//
+// Notably, creating the token allows us to manage the writable FD easily during enableFsverity.
+// Since enabling fs-verity to a file requires no outstanding writable FD, passing the authFd to the
+// server allows the server to hold the only reference (as long as the client app doesn't).
+binder::Status InstalldNativeService::createFsveritySetupAuthToken(
+        const ParcelFileDescriptor& authFd, int32_t appUid, int32_t userId,
+        sp<IFsveritySetupAuthToken>* _aidl_return) {
+    CHECK_ARGUMENT_UID_IN_APP_RANGE(appUid);
+    ENFORCE_VALID_USER(userId);
+
+    auto token = sp<FsveritySetupAuthToken>::make();
+    binder::Status status = token->authenticate(authFd, appUid, userId);
+    if (!status.isOk()) {
+        return status;
+    }
+    *_aidl_return = token;
+    return ok();
+}
+
+// Enables fs-verity for filePath, which must be an absolute path and the same inode as in the auth
+// token previously returned from createFsveritySetupAuthToken, and owned by the app uid. As
+// installd is more privileged than its client / system server, we attempt to limit what a
+// (compromised) client can do.
+//
+// The reason for this app request to go through installd is to avoid exposing a risky area (PKCS#7
+// signature verification) in the kernel to the app as an attack surface (it can't be system server
+// because it can't override DAC and manipulate app files). Note that we should be able to drop
+// these hops and simply the app calls the ioctl, once all upgrading devices run with a kernel
+// without fs-verity built-in signature (https://r.android.com/2650402).
+binder::Status InstalldNativeService::enableFsverity(const sp<IFsveritySetupAuthToken>& authToken,
+                                                     const std::string& filePath,
+                                                     const std::string& packageName,
+                                                     int32_t* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_PATH(filePath);
+    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+    LOCK_PACKAGE();
+    if (authToken == nullptr) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Received a null auth token");
+    }
+
+    // Authenticate to check the targeting file is the same inode as the authFd.
+    sp<IBinder> authTokenBinder = IInterface::asBinder(authToken)->localBinder();
+    if (authTokenBinder == nullptr) {
+        return exception(binder::Status::EX_SECURITY, "Received a non-local auth token");
+    }
+    auto authTokenInstance = sp<FsveritySetupAuthToken>::cast(authTokenBinder);
+    unique_fd rfd(open(filePath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    struct stat stFromPath;
+    if (fstat(rfd.get(), &stFromPath) < 0) {
+        *_aidl_return = errno;
+        return ok();
+    }
+    if (!authTokenInstance->isSameStat(stFromPath)) {
+        LOG(DEBUG) << "FD authentication failed";
+        *_aidl_return = EPERM;
+        return ok();
+    }
+
+    fsverity_enable_arg arg = {};
+    arg.version = 1;
+    arg.hash_algorithm = FS_VERITY_HASH_ALG_SHA256;
+    arg.block_size = 4096;
+    if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, &arg) < 0) {
+        *_aidl_return = errno;
+    } else {
+        *_aidl_return = 0;
+    }
+    return ok();
+}
+
 }  // namespace installd
 }  // namespace android
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 521afc3..0f28234 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -19,6 +19,7 @@
 #define COMMANDS_H_
 
 #include <inttypes.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include <shared_mutex>
@@ -35,8 +36,26 @@
 namespace android {
 namespace installd {
 
+using IFsveritySetupAuthToken = android::os::IInstalld::IFsveritySetupAuthToken;
+
 class InstalldNativeService : public BinderService<InstalldNativeService>, public os::BnInstalld {
 public:
+    class FsveritySetupAuthToken : public os::IInstalld::BnFsveritySetupAuthToken {
+    public:
+        FsveritySetupAuthToken() : mStatFromAuthFd() {}
+
+        binder::Status authenticate(const android::os::ParcelFileDescriptor& authFd, int32_t appUid,
+                                    int32_t userId);
+        bool isSameStat(const struct stat& st) const;
+
+    private:
+        // Not copyable or movable
+        FsveritySetupAuthToken(const FsveritySetupAuthToken&) = delete;
+        FsveritySetupAuthToken& operator=(const FsveritySetupAuthToken&) = delete;
+
+        struct stat mStatFromAuthFd;
+    };
+
     static status_t start();
     static char const* getServiceName() { return "installd"; }
     virtual status_t dump(int fd, const Vector<String16> &args) override;
@@ -192,6 +211,13 @@
                                      const std::optional<std::string>& outputPath,
                                      int32_t* _aidl_return);
 
+    binder::Status createFsveritySetupAuthToken(const android::os::ParcelFileDescriptor& authFd,
+                                                int32_t appUid, int32_t userId,
+                                                android::sp<IFsveritySetupAuthToken>* _aidl_return);
+    binder::Status enableFsverity(const android::sp<IFsveritySetupAuthToken>& authToken,
+                                  const std::string& filePath, const std::string& packageName,
+                                  int32_t* _aidl_return);
+
 private:
     std::recursive_mutex mLock;
     std::unordered_map<userid_t, std::weak_ptr<std::shared_mutex>> mUserIdLock;
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 9ad853b..8893e38 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -134,6 +134,22 @@
     int getOdexVisibility(@utf8InCpp String packageName, @utf8InCpp String apkPath,
             @utf8InCpp String instructionSet, @nullable @utf8InCpp String outputPath);
 
+    interface IFsveritySetupAuthToken {
+        // Using an interface here is an easy way to create and maintain an IBinder object across
+        // the processes. When installd creates this binder object, it stores the file stat
+        // privately for later authentication, and only returns the reference to the caller process.
+        // Once the binder object has no reference count, it gets destructed automatically
+        // (alternatively, installd can maintain an internal mapping, but it is more error prone
+        // because the app may crash and not finish the fs-verity setup, keeping the memory unused
+        // forever).
+        //
+        // We don't necessarily need a method here, so it's left blank intentionally.
+    }
+    IFsveritySetupAuthToken createFsveritySetupAuthToken(in ParcelFileDescriptor authFd, int appUid,
+            int userId);
+    int enableFsverity(in IFsveritySetupAuthToken authToken, @utf8InCpp String filePath,
+            @utf8InCpp String packageName);
+
     const int FLAG_STORAGE_DE = 0x1;
     const int FLAG_STORAGE_CE = 0x2;
     const int FLAG_STORAGE_EXTERNAL = 0x4;
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 858a92c..4bc92af 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -42,9 +42,12 @@
 #include "binder_test_utils.h"
 #include "dexopt.h"
 #include "globals.h"
+#include "unique_file.h"
 #include "utils.h"
 
 using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::os::ParcelFileDescriptor;
 using std::filesystem::is_empty;
 
 namespace android {
@@ -136,6 +139,16 @@
     return fd;
 }
 
+static void create_with_content(const std::string& path, uid_t owner, gid_t group, mode_t mode,
+                                const std::string& content) {
+    int fd = ::open(path.c_str(), O_RDWR | O_CREAT, mode);
+    EXPECT_NE(fd, -1);
+    EXPECT_TRUE(android::base::WriteStringToFd(content, fd));
+    EXPECT_EQ(::fchown(fd, owner, group), 0);
+    EXPECT_EQ(::fchmod(fd, mode), 0);
+    close(fd);
+}
+
 static void touch(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
     EXPECT_EQ(::close(create(path.c_str(), owner, group, mode)), 0);
 }
@@ -527,6 +540,94 @@
                                            externalStorageAppId, ceDataInodes, codePaths,
                                            &externalStorageSize));
 }
+
+class FsverityTest : public ServiceTest {
+protected:
+    binder::Status createFsveritySetupAuthToken(const std::string& path, int open_mode,
+                                                sp<IFsveritySetupAuthToken>* _aidl_return) {
+        unique_fd ufd(open(path.c_str(), open_mode));
+        EXPECT_GE(ufd.get(), 0) << "open failed: " << strerror(errno);
+        ParcelFileDescriptor rfd(std::move(ufd));
+        return service->createFsveritySetupAuthToken(std::move(rfd), kTestAppId, kTestUserId,
+                                                     _aidl_return);
+    }
+};
+
+TEST_F(FsverityTest, enableFsverity) {
+    const std::string path = kTestPath + "/foo";
+    create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+
+    // Expect to fs-verity setup to succeed
+    sp<IFsveritySetupAuthToken> authToken;
+    binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(authToken != nullptr);
+
+    // Verity auth token works to enable fs-verity
+    int32_t errno_local;
+    status = service->enableFsverity(authToken, path, "fake.package.name", &errno_local);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_EQ(errno_local, 0);
+}
+
+TEST_F(FsverityTest, enableFsverity_nullAuthToken) {
+    const std::string path = kTestPath + "/foo";
+    create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+
+    // Verity null auth token fails
+    sp<IFsveritySetupAuthToken> authToken;
+    int32_t errno_local;
+    binder::Status status =
+            service->enableFsverity(authToken, path, "fake.package.name", &errno_local);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(FsverityTest, enableFsverity_differentFile) {
+    const std::string path = kTestPath + "/foo";
+    create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+
+    // Expect to fs-verity setup to succeed
+    sp<IFsveritySetupAuthToken> authToken;
+    binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_TRUE(authToken != nullptr);
+
+    // Verity auth token does not work for a different file
+    const std::string anotherPath = kTestPath + "/bar";
+    ASSERT_TRUE(android::base::WriteStringToFile("content", anotherPath));
+    UniqueFile raii2(/*fd=*/-1, anotherPath, [](const std::string& path) { unlink(path.c_str()); });
+    int32_t errno_local;
+    status = service->enableFsverity(authToken, anotherPath, "fake.package.name", &errno_local);
+    EXPECT_TRUE(status.isOk());
+    EXPECT_NE(errno_local, 0);
+}
+
+TEST_F(FsverityTest, createFsveritySetupAuthToken_ReadonlyFdDoesNotAuthenticate) {
+    const std::string path = kTestPath + "/foo";
+    create_with_content(path, kTestAppUid, kTestAppUid, 0600, "content");
+    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+
+    // Expect the fs-verity setup to fail
+    sp<IFsveritySetupAuthToken> authToken;
+    binder::Status status = createFsveritySetupAuthToken(path, O_RDONLY, &authToken);
+    EXPECT_FALSE(status.isOk());
+}
+
+TEST_F(FsverityTest, createFsveritySetupAuthToken_UnownedFile) {
+    const std::string path = kTestPath + "/foo";
+    // Simulate world-writable file owned by another app
+    create_with_content(path, kTestAppUid + 1, kTestAppUid + 1, 0666, "content");
+    UniqueFile raii(/*fd=*/-1, path, [](const std::string& path) { unlink(path.c_str()); });
+
+    // Expect the fs-verity setup to fail
+    sp<IFsveritySetupAuthToken> authToken;
+    binder::Status status = createFsveritySetupAuthToken(path, O_RDWR, &authToken);
+    EXPECT_FALSE(status.isOk());
+}
+
 static bool mkdirs(const std::string& path, mode_t mode) {
     struct stat sb;
     if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index f2b4a6e..7d6ae00 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -193,8 +193,7 @@
         status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply,
                                           IBinder::FLAG_ONEWAY);
         if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
-            ALOGD("FGS Logger Transaction failed");
-            ALOGD("%d", err);
+            ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
             return err;
         }
         return NO_ERROR;
@@ -209,8 +208,7 @@
         status_t err =
                 remote()->transact(LOG_FGS_API_END_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
         if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
-            ALOGD("FGS Logger Transaction failed");
-            ALOGD("%d", err);
+            ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
             return err;
         }
         return NO_ERROR;
@@ -224,11 +222,10 @@
         data.writeInt32(state);
         data.writeInt32(appUid);
         data.writeInt32(appPid);
-        status_t err = remote()->transact(LOG_FGS_API_BEGIN_TRANSACTION, data, &reply,
+        status_t err = remote()->transact(LOG_FGS_API_STATE_CHANGED_TRANSACTION, data, &reply,
                                           IBinder::FLAG_ONEWAY);
         if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
-            ALOGD("FGS Logger Transaction failed");
-            ALOGD("%d", err);
+            ALOGD("%s: FGS Logger Transaction failed, %d", __func__, err);
             return err;
         }
         return NO_ERROR;
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 672d6cf..57a38dc 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -11,9 +11,6 @@
     name: "libbinder_rs",
     crate_name: "binder",
     srcs: ["src/lib.rs"],
-    shared_libs: [
-        "libutils",
-    ],
     rustlibs: [
         "libbinder_ndk_sys",
         "libdowncast_rs",
diff --git a/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
index ba1a6a1..d2fa581 100644
--- a/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
+++ b/libs/binder/tests/parcel_fuzzer/test_fuzzer/TestServiceFuzzer.cpp
@@ -35,6 +35,7 @@
     ON_ROOT_AID,
     ON_DUMP_TRANSACT,
     ON_SHELL_CMD_TRANSACT,
+    CRASH_ALWAYS,
 };
 
 // This service is to verify that fuzzService is functioning properly
@@ -112,8 +113,10 @@
 
 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
     if (*argc < 2) {
-        printf("You must specify at least one argument\n");
-        exit(0); // success because this is a crash test
+        // This fuzzer is also used as test fuzzer to check infra pipeline.
+        // It should always run and find a crash in TestService.
+        gCrashType = CrashType::CRASH_ALWAYS;
+        return 0;
     }
 
     std::string arg = std::string((*argv)[1]);
@@ -146,6 +149,9 @@
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (gCrashType == CrashType::CRASH_ALWAYS) {
+        LOG_ALWAYS_FATAL("Expected crash, This fuzzer will always crash.");
+    }
     auto service = sp<TestService>::make(gCrashType);
     fuzzService(service, FuzzedDataProvider(data, size));
     return 0;
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 12c9e53..d571917 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -140,7 +140,7 @@
 #if DEBUG_PARSER_PERFORMANCE
     nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
     ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
-          tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0);
+          tokenizer->getFilename().c_str(), tokenizer->getLineNumber(), elapsedTime / 1000000.0);
 #endif
     if (status != OK) {
         ALOGE("Loading KeyCharacterMap failed with status %s", statusToString(status).c_str());
@@ -297,7 +297,7 @@
         if (!findKey(ch, &keyCode, &metaState)) {
 #if DEBUG_MAPPING
             ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.",
-                    deviceId, toString(chars, numChars).string(), ch);
+                  deviceId, toString(chars, numChars).c_str(), ch);
 #endif
             return false;
         }
@@ -309,8 +309,8 @@
         addMetaKeys(outEvents, deviceId, metaState, false, now, &currentMetaState);
     }
 #if DEBUG_MAPPING
-    ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
-            deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
+    ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.", deviceId,
+          toString(chars, numChars).c_str(), int32_t(outEvents.size()));
     for (size_t i = 0; i < outEvents.size(); i++) {
         ALOGD("  Key: keyCode=%d, metaState=0x%08x, %s.",
                 outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
@@ -756,8 +756,8 @@
 status_t KeyCharacterMap::Parser::parse() {
     while (!mTokenizer->isEof()) {
 #if DEBUG_PARSER
-        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
-                mTokenizer->peekRemainderOfLine().string());
+        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().c_str(),
+              mTokenizer->peekRemainderOfLine().c_str());
 #endif
 
         mTokenizer->skipDelimiters(WHITESPACE);
@@ -779,8 +779,8 @@
                     status_t status = parseKey();
                     if (status) return status;
                 } else {
-                    ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
-                            keywordToken.string());
+                    ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().c_str(),
+                          keywordToken.c_str());
                     return BAD_VALUE;
                 }
                 break;
@@ -795,10 +795,9 @@
 
             mTokenizer->skipDelimiters(WHITESPACE);
             if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
-                ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
-                        mTokenizer->getLocation().string(),
-                        mTokenizer->peekRemainderOfLine().string());
-                return BAD_VALUE;
+            ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
+                  mTokenizer->getLocation().c_str(), mTokenizer->peekRemainderOfLine().c_str());
+            return BAD_VALUE;
             }
         }
 
@@ -807,27 +806,27 @@
 
     if (mState != STATE_TOP) {
         ALOGE("%s: Unterminated key description at end of file.",
-                mTokenizer->getLocation().string());
+              mTokenizer->getLocation().c_str());
         return BAD_VALUE;
     }
 
     if (mMap->mType == KeyboardType::UNKNOWN) {
         ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.",
-                mTokenizer->getLocation().string());
+              mTokenizer->getLocation().c_str());
         return BAD_VALUE;
     }
 
     if (mFormat == Format::BASE) {
         if (mMap->mType == KeyboardType::OVERLAY) {
             ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.",
-                    mTokenizer->getLocation().string());
+                  mTokenizer->getLocation().c_str());
             return BAD_VALUE;
         }
     } else if (mFormat == Format::OVERLAY) {
         if (mMap->mType != KeyboardType::OVERLAY) {
             ALOGE("%s: Overlay keyboard layout missing required keyboard "
-                    "'type OVERLAY' declaration.",
-                    mTokenizer->getLocation().string());
+                  "'type OVERLAY' declaration.",
+                  mTokenizer->getLocation().c_str());
             return BAD_VALUE;
         }
     }
@@ -837,8 +836,7 @@
 
 status_t KeyCharacterMap::Parser::parseType() {
     if (mMap->mType != KeyboardType::UNKNOWN) {
-        ALOGE("%s: Duplicate keyboard 'type' declaration.",
-                mTokenizer->getLocation().string());
+        ALOGE("%s: Duplicate keyboard 'type' declaration.", mTokenizer->getLocation().c_str());
         return BAD_VALUE;
     }
 
@@ -860,8 +858,8 @@
     } else if (typeToken == "OVERLAY") {
         type = KeyboardType::OVERLAY;
     } else {
-        ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(),
-                typeToken.string());
+        ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().c_str(),
+              typeToken.c_str());
         return BAD_VALUE;
     }
 
@@ -878,8 +876,8 @@
         mTokenizer->skipDelimiters(WHITESPACE);
         return parseMapKey();
     }
-    ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
-            keywordToken.string());
+    ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().c_str(),
+          keywordToken.c_str());
     return BAD_VALUE;
 }
 
@@ -893,26 +891,26 @@
     }
 
     char* end;
-    int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
+    int32_t code = int32_t(strtol(codeToken.c_str(), &end, 0));
     if (*end) {
-        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().c_str(),
+              mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
     std::map<int32_t, int32_t>& map = mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
     const auto it = map.find(code);
     if (it != map.end()) {
-        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().c_str(),
+                mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.c_str());
     if (!keyCode) {
-        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
-                keyCodeToken.string());
+        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().c_str(),
+              keyCodeToken.c_str());
         return BAD_VALUE;
     }
 
@@ -926,23 +924,23 @@
 
 status_t KeyCharacterMap::Parser::parseKey() {
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.c_str());
     if (!keyCode) {
-        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
-                keyCodeToken.string());
+        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().c_str(),
+              keyCodeToken.c_str());
         return BAD_VALUE;
     }
     if (mMap->mKeys.find(*keyCode) != mMap->mKeys.end()) {
-        ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
-                keyCodeToken.string());
+        ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().c_str(),
+                keyCodeToken.c_str());
         return BAD_VALUE;
     }
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 openBraceToken = mTokenizer->nextToken(WHITESPACE);
     if (openBraceToken != "{") {
-        ALOGE("%s: Expected '{' after key code label, got '%s'.",
-                mTokenizer->getLocation().string(), openBraceToken.string());
+        ALOGE("%s: Expected '{' after key code label, got '%s'.", mTokenizer->getLocation().c_str(),
+              openBraceToken.c_str());
         return BAD_VALUE;
     }
 
@@ -971,10 +969,10 @@
             properties.emplace_back(PROPERTY_NUMBER);
         } else {
             int32_t metaState;
-            status_t status = parseModifier(token.string(), &metaState);
+            status_t status = parseModifier(token.c_str(), &metaState);
             if (status) {
                 ALOGE("%s: Expected a property name or modifier, got '%s'.",
-                        mTokenizer->getLocation().string(), token.string());
+                      mTokenizer->getLocation().c_str(), token.c_str());
                 return status;
             }
             properties.emplace_back(PROPERTY_META, metaState);
@@ -992,8 +990,7 @@
             }
         }
 
-        ALOGE("%s: Expected ',' or ':' after property name.",
-                mTokenizer->getLocation().string());
+        ALOGE("%s: Expected ',' or ':' after property name.", mTokenizer->getLocation().c_str());
         return BAD_VALUE;
     }
 
@@ -1011,18 +1008,17 @@
             char16_t character;
             status_t status = parseCharacterLiteral(&character);
             if (status || !character) {
-                ALOGE("%s: Invalid character literal for key.",
-                        mTokenizer->getLocation().string());
+                ALOGE("%s: Invalid character literal for key.", mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
             if (haveCharacter) {
                 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
-                        mTokenizer->getLocation().string());
+                      mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
             if (haveReplacement) {
                 ALOGE("%s: Cannot combine character literal with replace action.",
-                        mTokenizer->getLocation().string());
+                      mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
             behavior.character = character;
@@ -1032,28 +1028,27 @@
             if (token == "none") {
                 if (haveCharacter) {
                     ALOGE("%s: Cannot combine multiple character literals or 'none'.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 if (haveReplacement) {
                     ALOGE("%s: Cannot combine 'none' with replace action.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 haveCharacter = true;
             } else if (token == "fallback") {
                 mTokenizer->skipDelimiters(WHITESPACE);
                 token = mTokenizer->nextToken(WHITESPACE);
-                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
+                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.c_str());
                 if (!keyCode) {
                     ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
-                            mTokenizer->getLocation().string(),
-                            token.string());
+                          mTokenizer->getLocation().c_str(), token.c_str());
                     return BAD_VALUE;
                 }
                 if (haveFallback || haveReplacement) {
                     ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 behavior.fallbackKeyCode = *keyCode;
@@ -1061,29 +1056,27 @@
             } else if (token == "replace") {
                 mTokenizer->skipDelimiters(WHITESPACE);
                 token = mTokenizer->nextToken(WHITESPACE);
-                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
+                std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(token.c_str());
                 if (!keyCode) {
                     ALOGE("%s: Invalid key code label for replace, got '%s'.",
-                            mTokenizer->getLocation().string(),
-                            token.string());
+                          mTokenizer->getLocation().c_str(), token.c_str());
                     return BAD_VALUE;
                 }
                 if (haveCharacter) {
                     ALOGE("%s: Cannot combine character literal with replace action.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 if (haveFallback || haveReplacement) {
                     ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 behavior.replacementKeyCode = *keyCode;
                 haveReplacement = true;
 
             } else {
-                ALOGE("%s: Expected a key behavior after ':'.",
-                        mTokenizer->getLocation().string());
+                ALOGE("%s: Expected a key behavior after ':'.", mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
         }
@@ -1096,7 +1089,7 @@
         switch (property.property) {
         case PROPERTY_LABEL:
                 if (key.label) {
-                    ALOGE("%s: Duplicate label for key.", mTokenizer->getLocation().string());
+                    ALOGE("%s: Duplicate label for key.", mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
                 key.label = behavior.character;
@@ -1106,7 +1099,7 @@
             break;
         case PROPERTY_NUMBER:
             if (key.number) {
-                    ALOGE("%s: Duplicate number for key.", mTokenizer->getLocation().string());
+                    ALOGE("%s: Duplicate number for key.", mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
             }
             key.number = behavior.character;
@@ -1118,7 +1111,7 @@
             for (const Behavior& b : key.behaviors) {
                     if (b.metaState == property.metaState) {
                     ALOGE("%s: Duplicate key behavior for modifier.",
-                            mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                     }
             }
@@ -1185,8 +1178,8 @@
                 return BAD_VALUE;
             }
             if (combinedMeta & metaState) {
-                ALOGE("%s: Duplicate modifier combination '%s'.",
-                        mTokenizer->getLocation().string(), token.c_str());
+                ALOGE("%s: Duplicate modifier combination '%s'.", mTokenizer->getLocation().c_str(),
+                      token.c_str());
                 return BAD_VALUE;
             }
 
@@ -1259,7 +1252,7 @@
     }
 
 Error:
-    ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
+    ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().c_str());
     return BAD_VALUE;
 }
 
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index a194513..ddc9ea4 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -177,7 +177,7 @@
 #if DEBUG_PARSER_PERFORMANCE
         nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
         ALOGD("Parsed key layout map file '%s' %d lines in %0.3fms.",
-              tokenizer->getFilename().string(), tokenizer->getLineNumber(),
+              tokenizer->getFilename().c_str(), tokenizer->getLineNumber(),
               elapsedTime / 1000000.0);
 #endif
         if (!status) {
@@ -306,8 +306,8 @@
 
 status_t KeyLayoutMap::Parser::parse() {
     while (!mTokenizer->isEof()) {
-        ALOGD_IF(DEBUG_PARSER, "Parsing %s: '%s'.", mTokenizer->getLocation().string(),
-                 mTokenizer->peekRemainderOfLine().string());
+        ALOGD_IF(DEBUG_PARSER, "Parsing %s: '%s'.", mTokenizer->getLocation().c_str(),
+                 mTokenizer->peekRemainderOfLine().c_str());
 
         mTokenizer->skipDelimiters(WHITESPACE);
 
@@ -334,16 +334,15 @@
                 status_t status = parseRequiredKernelConfig();
                 if (status) return status;
             } else {
-                ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
-                        keywordToken.string());
+                ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().c_str(),
+                      keywordToken.c_str());
                 return BAD_VALUE;
             }
 
             mTokenizer->skipDelimiters(WHITESPACE);
             if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
                 ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
-                        mTokenizer->getLocation().string(),
-                        mTokenizer->peekRemainderOfLine().string());
+                      mTokenizer->getLocation().c_str(), mTokenizer->peekRemainderOfLine().c_str());
                 return BAD_VALUE;
             }
         }
@@ -362,26 +361,26 @@
         codeToken = mTokenizer->nextToken(WHITESPACE);
     }
 
-    std::optional<int> code = parseInt(codeToken.string());
+    std::optional<int> code = parseInt(codeToken.c_str());
     if (!code) {
-        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().c_str(),
+                mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
     std::unordered_map<int32_t, Key>& map =
             mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
     if (map.find(*code) != map.end()) {
-        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().c_str(),
+                mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
+    std::optional<int> keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.c_str());
     if (!keyCode) {
-        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
-                keyCodeToken.string());
+        ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().c_str(),
+              keyCodeToken.c_str());
         return BAD_VALUE;
     }
 
@@ -391,15 +390,15 @@
         if (mTokenizer->isEol() || mTokenizer->peekChar() == '#') break;
 
         String8 flagToken = mTokenizer->nextToken(WHITESPACE);
-        std::optional<int> flag = InputEventLookup::getKeyFlagByLabel(flagToken.string());
+        std::optional<int> flag = InputEventLookup::getKeyFlagByLabel(flagToken.c_str());
         if (!flag) {
-            ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().string(),
-                    flagToken.string());
+            ALOGE("%s: Expected key flag label, got '%s'.", mTokenizer->getLocation().c_str(),
+                  flagToken.c_str());
             return BAD_VALUE;
         }
         if (flags & *flag) {
-            ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().string(),
-                    flagToken.string());
+            ALOGE("%s: Duplicate key flag '%s'.", mTokenizer->getLocation().c_str(),
+                    flagToken.c_str());
             return BAD_VALUE;
         }
         flags |= *flag;
@@ -417,15 +416,15 @@
 
 status_t KeyLayoutMap::Parser::parseAxis() {
     String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> scanCode = parseInt(scanCodeToken.string());
+    std::optional<int> scanCode = parseInt(scanCodeToken.c_str());
     if (!scanCode) {
-        ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().string(),
-                scanCodeToken.string());
+        ALOGE("%s: Expected axis scan code number, got '%s'.", mTokenizer->getLocation().c_str(),
+                scanCodeToken.c_str());
         return BAD_VALUE;
     }
     if (mMap->mAxes.find(*scanCode) != mMap->mAxes.end()) {
-        ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().string(),
-                scanCodeToken.string());
+        ALOGE("%s: Duplicate entry for axis scan code '%s'.", mTokenizer->getLocation().c_str(),
+                scanCodeToken.c_str());
         return BAD_VALUE;
     }
 
@@ -438,10 +437,10 @@
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 axisToken = mTokenizer->nextToken(WHITESPACE);
-        std::optional<int> axis = InputEventLookup::getAxisByLabel(axisToken.string());
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(axisToken.c_str());
         if (!axis) {
             ALOGE("%s: Expected inverted axis label, got '%s'.",
-                    mTokenizer->getLocation().string(), axisToken.string());
+                    mTokenizer->getLocation().c_str(), axisToken.c_str());
             return BAD_VALUE;
         }
         axisInfo.axis = *axis;
@@ -450,38 +449,38 @@
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 splitToken = mTokenizer->nextToken(WHITESPACE);
-        std::optional<int> splitValue = parseInt(splitToken.string());
+        std::optional<int> splitValue = parseInt(splitToken.c_str());
         if (!splitValue) {
             ALOGE("%s: Expected split value, got '%s'.",
-                    mTokenizer->getLocation().string(), splitToken.string());
+                    mTokenizer->getLocation().c_str(), splitToken.c_str());
             return BAD_VALUE;
         }
         axisInfo.splitValue = *splitValue;
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
-        std::optional<int> axis = InputEventLookup::getAxisByLabel(lowAxisToken.string());
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(lowAxisToken.c_str());
         if (!axis) {
             ALOGE("%s: Expected low axis label, got '%s'.",
-                    mTokenizer->getLocation().string(), lowAxisToken.string());
+                    mTokenizer->getLocation().c_str(), lowAxisToken.c_str());
             return BAD_VALUE;
         }
         axisInfo.axis = *axis;
 
         mTokenizer->skipDelimiters(WHITESPACE);
         String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
-        std::optional<int> highAxis = InputEventLookup::getAxisByLabel(highAxisToken.string());
+        std::optional<int> highAxis = InputEventLookup::getAxisByLabel(highAxisToken.c_str());
         if (!highAxis) {
             ALOGE("%s: Expected high axis label, got '%s'.",
-                    mTokenizer->getLocation().string(), highAxisToken.string());
+                    mTokenizer->getLocation().c_str(), highAxisToken.c_str());
             return BAD_VALUE;
         }
         axisInfo.highAxis = *highAxis;
     } else {
-        std::optional<int> axis = InputEventLookup::getAxisByLabel(token.string());
+        std::optional<int> axis = InputEventLookup::getAxisByLabel(token.c_str());
         if (!axis) {
             ALOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
-                    mTokenizer->getLocation().string(), token.string());
+                  mTokenizer->getLocation().c_str(), token.c_str());
             return BAD_VALUE;
         }
         axisInfo.axis = *axis;
@@ -496,16 +495,16 @@
         if (keywordToken == "flat") {
             mTokenizer->skipDelimiters(WHITESPACE);
             String8 flatToken = mTokenizer->nextToken(WHITESPACE);
-            std::optional<int> flatOverride = parseInt(flatToken.string());
+            std::optional<int> flatOverride = parseInt(flatToken.c_str());
             if (!flatOverride) {
                 ALOGE("%s: Expected flat value, got '%s'.",
-                        mTokenizer->getLocation().string(), flatToken.string());
+                        mTokenizer->getLocation().c_str(), flatToken.c_str());
                 return BAD_VALUE;
             }
             axisInfo.flatOverride = *flatOverride;
         } else {
-            ALOGE("%s: Expected keyword 'flat', got '%s'.",
-                    mTokenizer->getLocation().string(), keywordToken.string());
+            ALOGE("%s: Expected keyword 'flat', got '%s'.", mTokenizer->getLocation().c_str(),
+                  keywordToken.c_str());
             return BAD_VALUE;
         }
     }
@@ -527,27 +526,27 @@
         mTokenizer->skipDelimiters(WHITESPACE);
         codeToken = mTokenizer->nextToken(WHITESPACE);
     }
-    std::optional<int> code = parseInt(codeToken.string());
+    std::optional<int> code = parseInt(codeToken.c_str());
     if (!code) {
-        ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().c_str(),
+                mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     std::unordered_map<int32_t, Led>& map =
             mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
     if (map.find(*code) != map.end()) {
-        ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
-                mapUsage ? "usage" : "scan code", codeToken.string());
+        ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().c_str(),
+                mapUsage ? "usage" : "scan code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> ledCode = InputEventLookup::getLedByLabel(ledCodeToken.string());
+    std::optional<int> ledCode = InputEventLookup::getLedByLabel(ledCodeToken.c_str());
     if (!ledCode) {
-        ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
-                ledCodeToken.string());
+        ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().c_str(),
+                ledCodeToken.c_str());
         return BAD_VALUE;
     }
 
@@ -569,7 +568,7 @@
 }
 
 static std::optional<int32_t> getSensorDataIndex(String8 token) {
-    std::string tokenStr(token.string());
+    std::string tokenStr(token.c_str());
     if (tokenStr == "X") {
         return 0;
     } else if (tokenStr == "Y") {
@@ -594,26 +593,26 @@
 // sensor 0x05 GYROSCOPE Z
 status_t KeyLayoutMap::Parser::parseSensor() {
     String8 codeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<int> code = parseInt(codeToken.string());
+    std::optional<int> code = parseInt(codeToken.c_str());
     if (!code) {
-        ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().string(),
-              "abs code", codeToken.string());
+        ALOGE("%s: Expected sensor %s number, got '%s'.", mTokenizer->getLocation().c_str(),
+              "abs code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     std::unordered_map<int32_t, Sensor>& map = mMap->mSensorsByAbsCode;
     if (map.find(*code) != map.end()) {
-        ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().string(),
-              "abs code", codeToken.string());
+        ALOGE("%s: Duplicate entry for sensor %s '%s'.", mTokenizer->getLocation().c_str(),
+              "abs code", codeToken.c_str());
         return BAD_VALUE;
     }
 
     mTokenizer->skipDelimiters(WHITESPACE);
     String8 sensorTypeToken = mTokenizer->nextToken(WHITESPACE);
-    std::optional<InputDeviceSensorType> typeOpt = getSensorType(sensorTypeToken.string());
+    std::optional<InputDeviceSensorType> typeOpt = getSensorType(sensorTypeToken.c_str());
     if (!typeOpt) {
-        ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().string(),
-              sensorTypeToken.string());
+        ALOGE("%s: Expected sensor code label, got '%s'.", mTokenizer->getLocation().c_str(),
+              sensorTypeToken.c_str());
         return BAD_VALUE;
     }
     InputDeviceSensorType sensorType = typeOpt.value();
@@ -621,8 +620,8 @@
     String8 sensorDataIndexToken = mTokenizer->nextToken(WHITESPACE);
     std::optional<int32_t> indexOpt = getSensorDataIndex(sensorDataIndexToken);
     if (!indexOpt) {
-        ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().string(),
-              sensorDataIndexToken.string());
+        ALOGE("%s: Expected sensor data index label, got '%s'.", mTokenizer->getLocation().c_str(),
+              sensorDataIndexToken.c_str());
         return BAD_VALUE;
     }
     int32_t sensorDataIndex = indexOpt.value();
@@ -643,12 +642,12 @@
 // requires_kernel_config CONFIG_HID_PLAYSTATION
 status_t KeyLayoutMap::Parser::parseRequiredKernelConfig() {
     String8 codeToken = mTokenizer->nextToken(WHITESPACE);
-    std::string configName = codeToken.string();
+    std::string configName = codeToken.c_str();
 
     const auto result = mMap->mRequiredKernelConfigs.emplace(configName);
     if (!result.second) {
         ALOGE("%s: Duplicate entry for required kernel config %s.",
-              mTokenizer->getLocation().string(), configName.c_str());
+              mTokenizer->getLocation().c_str(), configName.c_str());
         return BAD_VALUE;
     }
 
diff --git a/libs/input/PropertyMap.cpp b/libs/input/PropertyMap.cpp
index 548f894..315f5a6 100644
--- a/libs/input/PropertyMap.cpp
+++ b/libs/input/PropertyMap.cpp
@@ -163,8 +163,8 @@
 status_t PropertyMap::Parser::parse() {
     while (!mTokenizer->isEof()) {
 #if DEBUG_PARSER
-        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
-              mTokenizer->peekRemainderOfLine().string());
+        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().c_str(),
+              mTokenizer->peekRemainderOfLine().c_str());
 #endif
 
         mTokenizer->skipDelimiters(WHITESPACE);
@@ -172,7 +172,7 @@
         if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
             String8 keyToken = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
             if (keyToken.isEmpty()) {
-                ALOGE("%s: Expected non-empty property key.", mTokenizer->getLocation().string());
+                ALOGE("%s: Expected non-empty property key.", mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
 
@@ -180,7 +180,7 @@
 
             if (mTokenizer->nextChar() != '=') {
                 ALOGE("%s: Expected '=' between property key and value.",
-                      mTokenizer->getLocation().string());
+                      mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
 
@@ -189,20 +189,20 @@
             String8 valueToken = mTokenizer->nextToken(WHITESPACE);
             if (valueToken.find("\\", 0) >= 0 || valueToken.find("\"", 0) >= 0) {
                 ALOGE("%s: Found reserved character '\\' or '\"' in property value.",
-                      mTokenizer->getLocation().string());
+                      mTokenizer->getLocation().c_str());
                 return BAD_VALUE;
             }
 
             mTokenizer->skipDelimiters(WHITESPACE);
             if (!mTokenizer->isEol()) {
-                ALOGE("%s: Expected end of line, got '%s'.", mTokenizer->getLocation().string(),
-                      mTokenizer->peekRemainderOfLine().string());
+                ALOGE("%s: Expected end of line, got '%s'.", mTokenizer->getLocation().c_str(),
+                      mTokenizer->peekRemainderOfLine().c_str());
                 return BAD_VALUE;
             }
 
             if (mMap->hasProperty(keyToken.string())) {
                 ALOGE("%s: Duplicate property value for key '%s'.",
-                      mTokenizer->getLocation().string(), keyToken.string());
+                      mTokenizer->getLocation().c_str(), keyToken.c_str());
                 return BAD_VALUE;
             }
 
diff --git a/libs/input/VirtualKeyMap.cpp b/libs/input/VirtualKeyMap.cpp
index 865366b..de62c87 100644
--- a/libs/input/VirtualKeyMap.cpp
+++ b/libs/input/VirtualKeyMap.cpp
@@ -79,8 +79,8 @@
 status_t VirtualKeyMap::Parser::parse() {
     while (!mTokenizer->isEof()) {
 #if DEBUG_PARSER
-        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
-                mTokenizer->peekRemainderOfLine().string());
+        ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().c_str(),
+              mTokenizer->peekRemainderOfLine().c_str());
 #endif
 
         mTokenizer->skipDelimiters(WHITESPACE);
@@ -91,7 +91,7 @@
                 String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
                 if (token != "0x01") {
                     ALOGE("%s: Unknown virtual key type, expected 0x01.",
-                          mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
 
@@ -103,7 +103,7 @@
                         && parseNextIntField(&defn.height);
                 if (!success) {
                     ALOGE("%s: Expected 5 colon-delimited integers in virtual key definition.",
-                          mTokenizer->getLocation().string());
+                          mTokenizer->getLocation().c_str());
                     return BAD_VALUE;
                 }
 
@@ -116,9 +116,8 @@
             } while (consumeFieldDelimiterAndSkipWhitespace());
 
             if (!mTokenizer->isEol()) {
-                ALOGE("%s: Expected end of line, got '%s'.",
-                        mTokenizer->getLocation().string(),
-                        mTokenizer->peekRemainderOfLine().string());
+                ALOGE("%s: Expected end of line, got '%s'.", mTokenizer->getLocation().c_str(),
+                      mTokenizer->peekRemainderOfLine().c_str());
                 return BAD_VALUE;
             }
         }
@@ -146,9 +145,9 @@
 
     String8 token = mTokenizer->nextToken(WHITESPACE_OR_FIELD_DELIMITER);
     char* end;
-    *outValue = strtol(token.string(), &end, 0);
+    *outValue = strtol(token.c_str(), &end, 0);
     if (token.isEmpty() || *end != '\0') {
-        ALOGE("Expected an integer, got '%s'.", token.string());
+        ALOGE("Expected an integer, got '%s'.", token.c_str());
         return false;
     }
     return true;
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 8d19c45..ba2eb7d 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -56,30 +56,8 @@
 filegroup {
     name: "librenderengine_sources",
     srcs: [
-        "Description.cpp",
         "ExternalTexture.cpp",
-        "Mesh.cpp",
         "RenderEngine.cpp",
-        "Texture.cpp",
-    ],
-}
-
-filegroup {
-    name: "librenderengine_gl_sources",
-    srcs: [
-        "gl/GLESRenderEngine.cpp",
-        "gl/GLExtensions.cpp",
-        "gl/GLFramebuffer.cpp",
-        "gl/GLImage.cpp",
-        "gl/GLShadowTexture.cpp",
-        "gl/GLShadowVertexGenerator.cpp",
-        "gl/GLSkiaShadowPort.cpp",
-        "gl/GLVertexBuffer.cpp",
-        "gl/ImageManager.cpp",
-        "gl/Program.cpp",
-        "gl/ProgramCache.cpp",
-        "gl/filters/BlurFilter.cpp",
-        "gl/filters/GenericProgram.cpp",
     ],
 }
 
@@ -96,6 +74,7 @@
         "skia/AutoBackendTexture.cpp",
         "skia/Cache.cpp",
         "skia/ColorSpaces.cpp",
+        "skia/GLExtensions.cpp",
         "skia/SkiaRenderEngine.cpp",
         "skia/SkiaGLRenderEngine.cpp",
         "skia/SkiaVkRenderEngine.cpp",
@@ -136,7 +115,6 @@
     ],
     srcs: [
         ":librenderengine_sources",
-        ":librenderengine_gl_sources",
         ":librenderengine_threaded_sources",
         ":librenderengine_skia_sources",
     ],
@@ -155,8 +133,6 @@
     name: "librenderengine_mocks",
     defaults: ["librenderengine_defaults"],
     srcs: [
-        "mock/Framebuffer.cpp",
-        "mock/Image.cpp",
         "mock/RenderEngine.cpp",
     ],
     static_libs: [
diff --git a/libs/renderengine/Description.cpp b/libs/renderengine/Description.cpp
deleted file mode 100644
index 245c9e1..0000000
--- a/libs/renderengine/Description.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <renderengine/private/Description.h>
-
-#include <stdint.h>
-
-#include <utils/TypeHelpers.h>
-
-namespace android {
-namespace renderengine {
-
-Description::TransferFunction Description::dataSpaceToTransferFunction(ui::Dataspace dataSpace) {
-    ui::Dataspace transfer = static_cast<ui::Dataspace>(dataSpace & ui::Dataspace::TRANSFER_MASK);
-    switch (transfer) {
-        case ui::Dataspace::TRANSFER_ST2084:
-            return Description::TransferFunction::ST2084;
-        case ui::Dataspace::TRANSFER_HLG:
-            return Description::TransferFunction::HLG;
-        case ui::Dataspace::TRANSFER_LINEAR:
-            return Description::TransferFunction::LINEAR;
-        default:
-            return Description::TransferFunction::SRGB;
-    }
-}
-
-bool Description::hasInputTransformMatrix() const {
-    const mat4 identity;
-    return inputTransformMatrix != identity;
-}
-
-bool Description::hasOutputTransformMatrix() const {
-    const mat4 identity;
-    return outputTransformMatrix != identity;
-}
-
-bool Description::hasColorMatrix() const {
-    const mat4 identity;
-    return colorMatrix != identity;
-}
-
-bool Description::hasDisplayColorMatrix() const {
-    const mat4 identity;
-    return displayColorMatrix != identity;
-}
-
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index 9eb42cd..6f2a96a 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -27,14 +27,6 @@
       : mBuffer(buffer), mRenderEngine(renderEngine), mWritable(usage & WRITEABLE) {
     LOG_ALWAYS_FATAL_IF(buffer == nullptr,
                         "Attempted to bind a null buffer to an external texture!");
-    // GLESRenderEngine has a separate texture cache for output buffers,
-    if (usage == WRITEABLE &&
-        (mRenderEngine.getRenderEngineType() ==
-                 renderengine::RenderEngine::RenderEngineType::GLES ||
-         mRenderEngine.getRenderEngineType() ==
-                 renderengine::RenderEngine::RenderEngineType::THREADED)) {
-        return;
-    }
     mRenderEngine.mapExternalTextureBuffer(mBuffer, mWritable);
 }
 
diff --git a/libs/renderengine/Mesh.cpp b/libs/renderengine/Mesh.cpp
deleted file mode 100644
index ed2f45f..0000000
--- a/libs/renderengine/Mesh.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <renderengine/Mesh.h>
-
-#include <utils/Log.h>
-
-namespace android {
-namespace renderengine {
-
-Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize,
-           size_t cropCoordsSize, size_t shadowColorSize, size_t shadowParamsSize,
-           size_t indexCount)
-      : mVertexCount(vertexCount),
-        mVertexSize(vertexSize),
-        mTexCoordsSize(texCoordSize),
-        mCropCoordsSize(cropCoordsSize),
-        mShadowColorSize(shadowColorSize),
-        mShadowParamsSize(shadowParamsSize),
-        mPrimitive(primitive),
-        mIndexCount(indexCount) {
-    if (vertexCount == 0) {
-        mVertices.resize(1);
-        mVertices[0] = 0.0f;
-        mStride = 0;
-        return;
-    }
-    size_t stride = vertexSize + texCoordSize + cropCoordsSize + shadowColorSize + shadowParamsSize;
-    size_t remainder = (stride * vertexCount) / vertexCount;
-    // Since all of the input parameters are unsigned, if stride is less than
-    // either vertexSize or texCoordSize, it must have overflowed. remainder
-    // will be equal to stride as long as stride * vertexCount doesn't overflow.
-    if ((stride < vertexSize) || (remainder != stride)) {
-        ALOGE("Overflow in Mesh(..., %zu, %zu, %zu, %zu, %zu, %zu)", vertexCount, vertexSize,
-              texCoordSize, cropCoordsSize, shadowColorSize, shadowParamsSize);
-        mVertices.resize(1);
-        mVertices[0] = 0.0f;
-        mVertexCount = 0;
-        mVertexSize = 0;
-        mTexCoordsSize = 0;
-        mCropCoordsSize = 0;
-        mShadowColorSize = 0;
-        mShadowParamsSize = 0;
-        mStride = 0;
-        return;
-    }
-
-    mVertices.resize(stride * vertexCount);
-    mStride = stride;
-    mIndices.resize(indexCount);
-}
-
-Mesh::Primitive Mesh::getPrimitive() const {
-    return mPrimitive;
-}
-
-float const* Mesh::getPositions() const {
-    return mVertices.data();
-}
-float* Mesh::getPositions() {
-    return mVertices.data();
-}
-
-float const* Mesh::getTexCoords() const {
-    return mVertices.data() + mVertexSize;
-}
-float* Mesh::getTexCoords() {
-    return mVertices.data() + mVertexSize;
-}
-
-float const* Mesh::getCropCoords() const {
-    return mVertices.data() + mVertexSize + mTexCoordsSize;
-}
-float* Mesh::getCropCoords() {
-    return mVertices.data() + mVertexSize + mTexCoordsSize;
-}
-
-float const* Mesh::getShadowColor() const {
-    return mVertices.data() + mVertexSize + mTexCoordsSize + mCropCoordsSize;
-}
-float* Mesh::getShadowColor() {
-    return mVertices.data() + mVertexSize + mTexCoordsSize + mCropCoordsSize;
-}
-
-float const* Mesh::getShadowParams() const {
-    return mVertices.data() + mVertexSize + mTexCoordsSize + mCropCoordsSize + mShadowColorSize;
-}
-float* Mesh::getShadowParams() {
-    return mVertices.data() + mVertexSize + mTexCoordsSize + mCropCoordsSize + mShadowColorSize;
-}
-
-uint16_t const* Mesh::getIndices() const {
-    return mIndices.data();
-}
-
-uint16_t* Mesh::getIndices() {
-    return mIndices.data();
-}
-
-size_t Mesh::getVertexCount() const {
-    return mVertexCount;
-}
-
-size_t Mesh::getVertexSize() const {
-    return mVertexSize;
-}
-
-size_t Mesh::getTexCoordsSize() const {
-    return mTexCoordsSize;
-}
-
-size_t Mesh::getShadowColorSize() const {
-    return mShadowColorSize;
-}
-
-size_t Mesh::getShadowParamsSize() const {
-    return mShadowParamsSize;
-}
-
-size_t Mesh::getByteStride() const {
-    return mStride * sizeof(float);
-}
-
-size_t Mesh::getStride() const {
-    return mStride;
-}
-
-size_t Mesh::getIndexCount() const {
-    return mIndexCount;
-}
-
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index d08c221..a8e92c6 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -18,7 +18,6 @@
 
 #include <cutils/properties.h>
 #include <log/log.h>
-#include "gl/GLESRenderEngine.h"
 #include "renderengine/ExternalTexture.h"
 #include "threaded/RenderEngineThreaded.h"
 
@@ -30,11 +29,6 @@
 
 std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
     switch (args.renderEngineType) {
-        case RenderEngineType::THREADED:
-            ALOGD("Threaded RenderEngine with GLES Backend");
-            return renderengine::threaded::RenderEngineThreaded::create(
-                    [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); },
-                    args.renderEngineType);
         case RenderEngineType::SKIA_GL:
             ALOGD("RenderEngine with SkiaGL Backend");
             return renderengine::skia::SkiaGLRenderEngine::create(args);
@@ -56,10 +50,6 @@
                         return android::renderengine::skia::SkiaVkRenderEngine::create(args);
                     },
                     args.renderEngineType);
-        case RenderEngineType::GLES:
-        default:
-            ALOGD("RenderEngine with GLES Backend");
-            return renderengine::gl::GLESRenderEngine::create(args);
     }
 }
 
diff --git a/libs/renderengine/Texture.cpp b/libs/renderengine/Texture.cpp
deleted file mode 100644
index 154cde8..0000000
--- a/libs/renderengine/Texture.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#include <renderengine/Texture.h>
-
-namespace android {
-namespace renderengine {
-
-Texture::Texture()
-      : mTextureName(0), mTextureTarget(TEXTURE_2D), mWidth(0), mHeight(0), mFiltering(false) {}
-
-Texture::Texture(Target textureTarget, uint32_t textureName)
-      : mTextureName(textureName),
-        mTextureTarget(textureTarget),
-        mWidth(0),
-        mHeight(0),
-        mFiltering(false) {}
-
-void Texture::init(Target textureTarget, uint32_t textureName) {
-    mTextureName = textureName;
-    mTextureTarget = textureTarget;
-}
-
-Texture::~Texture() {}
-
-void Texture::setMatrix(float const* matrix) {
-    mTextureMatrix = mat4(matrix);
-}
-
-void Texture::setFiltering(bool enabled) {
-    mFiltering = enabled;
-}
-
-void Texture::setDimensions(size_t width, size_t height) {
-    mWidth = width;
-    mHeight = height;
-}
-
-uint32_t Texture::getTextureName() const {
-    return mTextureName;
-}
-
-uint32_t Texture::getTextureTarget() const {
-    return mTextureTarget;
-}
-
-const mat4& Texture::getMatrix() const {
-    return mTextureMatrix;
-}
-
-bool Texture::getFiltering() const {
-    return mFiltering;
-}
-
-size_t Texture::getWidth() const {
-    return mWidth;
-}
-
-size_t Texture::getHeight() const {
-    return mHeight;
-}
-
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp
index 791d4c9..ce2c7d7 100644
--- a/libs/renderengine/benchmark/RenderEngineBench.cpp
+++ b/libs/renderengine/benchmark/RenderEngineBench.cpp
@@ -43,10 +43,6 @@
             return "skiavk";
         case RenderEngine::RenderEngineType::SKIA_VK_THREADED:
             return "skiavkthreaded";
-        case RenderEngine::RenderEngineType::GLES:
-        case RenderEngine::RenderEngineType::THREADED:
-            LOG_ALWAYS_FATAL("GLESRenderEngine is deprecated - why time it?");
-            return "unused";
     }
 }
 
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
deleted file mode 100644
index a512b9a..0000000
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ /dev/null
@@ -1,1853 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-//#define LOG_NDEBUG 0
-#include "EGL/egl.h"
-#undef LOG_TAG
-#define LOG_TAG "RenderEngine"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <sched.h>
-#include <cmath>
-#include <fstream>
-#include <sstream>
-#include <unordered_set>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <android-base/stringprintf.h>
-#include <cutils/compiler.h>
-#include <cutils/properties.h>
-#include <gui/DebugEGLImageTracker.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Texture.h>
-#include <renderengine/private/Description.h>
-#include <sync/sync.h>
-#include <ui/ColorSpace.h>
-#include <ui/DebugUtils.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <utils/KeyedVector.h>
-#include <utils/Trace.h>
-#include "GLESRenderEngine.h"
-#include "GLExtensions.h"
-#include "GLFramebuffer.h"
-#include "GLImage.h"
-#include "GLShadowVertexGenerator.h"
-#include "Program.h"
-#include "ProgramCache.h"
-#include "filters/BlurFilter.h"
-
-bool checkGlError(const char* op, int lineNumber) {
-    bool errorFound = false;
-    GLint error = glGetError();
-    while (error != GL_NO_ERROR) {
-        errorFound = true;
-        error = glGetError();
-        ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
-    }
-    return errorFound;
-}
-
-static constexpr bool outputDebugPPMs = false;
-
-void writePPM(const char* basename, GLuint width, GLuint height) {
-    ALOGV("writePPM #%s: %d x %d", basename, width, height);
-
-    std::vector<GLubyte> pixels(width * height * 4);
-    std::vector<GLubyte> outBuffer(width * height * 3);
-
-    // TODO(courtneygo): We can now have float formats, need
-    // to remove this code or update to support.
-    // Make returned pixels fit in uint32_t, one byte per component
-    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
-    if (checkGlError(__FUNCTION__, __LINE__)) {
-        return;
-    }
-
-    std::string filename(basename);
-    filename.append(".ppm");
-    std::ofstream file(filename.c_str(), std::ios::binary);
-    if (!file.is_open()) {
-        ALOGE("Unable to open file: %s", filename.c_str());
-        ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
-              "surfaceflinger to write debug images");
-        return;
-    }
-
-    file << "P6\n";
-    file << width << "\n";
-    file << height << "\n";
-    file << 255 << "\n";
-
-    auto ptr = reinterpret_cast<char*>(pixels.data());
-    auto outPtr = reinterpret_cast<char*>(outBuffer.data());
-    for (int y = height - 1; y >= 0; y--) {
-        char* data = ptr + y * width * sizeof(uint32_t);
-
-        for (GLuint x = 0; x < width; x++) {
-            // Only copy R, G and B components
-            outPtr[0] = data[0];
-            outPtr[1] = data[1];
-            outPtr[2] = data[2];
-            data += sizeof(uint32_t);
-            outPtr += 3;
-        }
-    }
-    file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
-}
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class BindNativeBufferAsFramebuffer {
-public:
-    BindNativeBufferAsFramebuffer(GLESRenderEngine& engine, ANativeWindowBuffer* buffer,
-                                  const bool useFramebufferCache)
-          : mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) {
-        mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(),
-                                                      useFramebufferCache)
-                ? mEngine.bindFrameBuffer(mFramebuffer)
-                : NO_MEMORY;
-    }
-    ~BindNativeBufferAsFramebuffer() {
-        mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true);
-        mEngine.unbindFrameBuffer(mFramebuffer);
-    }
-    status_t getStatus() const { return mStatus; }
-
-private:
-    GLESRenderEngine& mEngine;
-    Framebuffer* mFramebuffer;
-    status_t mStatus;
-};
-
-using base::StringAppendF;
-using ui::Dataspace;
-
-static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
-                                         EGLint wanted, EGLConfig* outConfig) {
-    EGLint numConfigs = -1, n = 0;
-    eglGetConfigs(dpy, nullptr, 0, &numConfigs);
-    std::vector<EGLConfig> configs(numConfigs, EGL_NO_CONFIG_KHR);
-    eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n);
-    configs.resize(n);
-
-    if (!configs.empty()) {
-        if (attribute != EGL_NONE) {
-            for (EGLConfig config : configs) {
-                EGLint value = 0;
-                eglGetConfigAttrib(dpy, config, attribute, &value);
-                if (wanted == value) {
-                    *outConfig = config;
-                    return NO_ERROR;
-                }
-            }
-        } else {
-            // just pick the first one
-            *outConfig = configs[0];
-            return NO_ERROR;
-        }
-    }
-
-    return NAME_NOT_FOUND;
-}
-
-static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
-                                EGLConfig* config) {
-    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
-    // it is to be used with WIFI displays
-    status_t err;
-    EGLint wantedAttribute;
-    EGLint wantedAttributeValue;
-
-    std::vector<EGLint> attribs;
-    if (renderableType) {
-        const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
-        const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
-
-        // Default to 8 bits per channel.
-        const EGLint tmpAttribs[] = {
-                EGL_RENDERABLE_TYPE,
-                renderableType,
-                EGL_RECORDABLE_ANDROID,
-                EGL_TRUE,
-                EGL_SURFACE_TYPE,
-                EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
-                EGL_FRAMEBUFFER_TARGET_ANDROID,
-                EGL_TRUE,
-                EGL_RED_SIZE,
-                is1010102 ? 10 : 8,
-                EGL_GREEN_SIZE,
-                is1010102 ? 10 : 8,
-                EGL_BLUE_SIZE,
-                is1010102 ? 10 : 8,
-                EGL_ALPHA_SIZE,
-                is1010102 ? 2 : 8,
-                EGL_NONE,
-        };
-        std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
-                  std::back_inserter(attribs));
-        wantedAttribute = EGL_NONE;
-        wantedAttributeValue = EGL_NONE;
-    } else {
-        // if no renderable type specified, fallback to a simplified query
-        wantedAttribute = EGL_NATIVE_VISUAL_ID;
-        wantedAttributeValue = format;
-    }
-
-    err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
-                                   config);
-    if (err == NO_ERROR) {
-        EGLint caveat;
-        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
-            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
-    }
-
-    return err;
-}
-
-std::optional<RenderEngine::ContextPriority> GLESRenderEngine::createContextPriority(
-        const RenderEngineCreationArgs& args) {
-    if (!GLExtensions::getInstance().hasContextPriority()) {
-        return std::nullopt;
-    }
-
-    switch (args.contextPriority) {
-        case RenderEngine::ContextPriority::REALTIME:
-            if (gl::GLExtensions::getInstance().hasRealtimePriority()) {
-                return RenderEngine::ContextPriority::REALTIME;
-            } else {
-                ALOGI("Realtime priority unsupported, degrading gracefully to high priority");
-                return RenderEngine::ContextPriority::HIGH;
-            }
-        case RenderEngine::ContextPriority::HIGH:
-        case RenderEngine::ContextPriority::MEDIUM:
-        case RenderEngine::ContextPriority::LOW:
-            return args.contextPriority;
-        default:
-            return std::nullopt;
-    }
-}
-
-std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCreationArgs& args) {
-    // initialize EGL for the default display
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (!eglInitialize(display, nullptr, nullptr)) {
-        LOG_ALWAYS_FATAL("failed to initialize EGL. EGL error=0x%x", eglGetError());
-    }
-
-    const auto eglVersion = eglQueryString(display, EGL_VERSION);
-    if (!eglVersion) {
-        checkGlError(__FUNCTION__, __LINE__);
-        LOG_ALWAYS_FATAL("eglQueryString(EGL_VERSION) failed");
-    }
-
-    // Use the Android impl to grab EGL_NV_context_priority_realtime
-    const auto eglExtensions = eglQueryString(display, EGL_EXTENSIONS);
-    if (!eglExtensions) {
-        checkGlError(__FUNCTION__, __LINE__);
-        LOG_ALWAYS_FATAL("eglQueryString(EGL_EXTENSIONS) failed");
-    }
-
-    GLExtensions& extensions = GLExtensions::getInstance();
-    extensions.initWithEGLStrings(eglVersion, eglExtensions);
-
-    // The code assumes that ES2 or later is available if this extension is
-    // supported.
-    EGLConfig config = EGL_NO_CONFIG;
-    if (!extensions.hasNoConfigContext()) {
-        config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
-    }
-
-    const std::optional<RenderEngine::ContextPriority> priority = createContextPriority(args);
-    EGLContext protectedContext = EGL_NO_CONTEXT;
-    if (args.enableProtectedContext && extensions.hasProtectedContent()) {
-        protectedContext =
-                createEglContext(display, config, nullptr, priority, Protection::PROTECTED);
-        ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
-    }
-
-    EGLContext ctxt =
-            createEglContext(display, config, protectedContext, priority, Protection::UNPROTECTED);
-
-    // if can't create a GL context, we can only abort.
-    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
-
-    EGLSurface stub = EGL_NO_SURFACE;
-    if (!extensions.hasSurfacelessContext()) {
-        stub = createStubEglPbufferSurface(display, config, args.pixelFormat,
-                                           Protection::UNPROTECTED);
-        LOG_ALWAYS_FATAL_IF(stub == EGL_NO_SURFACE, "can't create stub pbuffer");
-    }
-    EGLBoolean success = eglMakeCurrent(display, stub, stub, ctxt);
-    LOG_ALWAYS_FATAL_IF(!success, "can't make stub pbuffer current");
-    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
-                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
-
-    EGLSurface protectedStub = EGL_NO_SURFACE;
-    if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
-        protectedStub = createStubEglPbufferSurface(display, config, args.pixelFormat,
-                                                    Protection::PROTECTED);
-        ALOGE_IF(protectedStub == EGL_NO_SURFACE, "can't create protected stub pbuffer");
-    }
-
-    // now figure out what version of GL did we actually get
-    GlesVersion version = parseGlesVersion(extensions.getVersion());
-
-    LOG_ALWAYS_FATAL_IF(args.supportsBackgroundBlur && version < GLES_VERSION_3_0,
-        "Blurs require OpenGL ES 3.0. Please unset ro.surface_flinger.supports_background_blur");
-
-    // initialize the renderer while GL is current
-    std::unique_ptr<GLESRenderEngine> engine;
-    switch (version) {
-        case GLES_VERSION_1_0:
-        case GLES_VERSION_1_1:
-            LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
-            break;
-        case GLES_VERSION_2_0:
-        case GLES_VERSION_3_0:
-            engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, stub,
-                                                        protectedContext, protectedStub);
-            break;
-    }
-
-    ALOGI("OpenGL ES informations:");
-    ALOGI("vendor    : %s", extensions.getVendor());
-    ALOGI("renderer  : %s", extensions.getRenderer());
-    ALOGI("version   : %s", extensions.getVersion());
-    ALOGI("extensions: %s", extensions.getExtensions());
-    ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
-    ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
-    return engine;
-}
-
-EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
-    status_t err;
-    EGLConfig config;
-
-    // First try to get an ES3 config
-    err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
-    if (err != NO_ERROR) {
-        // If ES3 fails, try to get an ES2 config
-        err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
-        if (err != NO_ERROR) {
-            // If ES2 still doesn't work, probably because we're on the emulator.
-            // try a simplified query
-            ALOGW("no suitable EGLConfig found, trying a simpler query");
-            err = selectEGLConfig(display, format, 0, &config);
-            if (err != NO_ERROR) {
-                // this EGL is too lame for android
-                LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
-            }
-        }
-    }
-
-    if (logConfig) {
-        // print some debugging info
-        EGLint r, g, b, a;
-        eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
-        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
-        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
-        ALOGI("EGL information:");
-        ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-        ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-        ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
-        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
-        ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-    }
-
-    return config;
-}
-
-GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
-                                   EGLConfig config, EGLContext ctxt, EGLSurface stub,
-                                   EGLContext protectedContext, EGLSurface protectedStub)
-      : RenderEngine(args.renderEngineType),
-        mEGLDisplay(display),
-        mEGLConfig(config),
-        mEGLContext(ctxt),
-        mStubSurface(stub),
-        mProtectedEGLContext(protectedContext),
-        mProtectedStubSurface(protectedStub),
-        mVpWidth(0),
-        mVpHeight(0),
-        mFramebufferImageCacheSize(args.imageCacheSize),
-        mPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly) {
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
-    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
-
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-    glPixelStorei(GL_PACK_ALIGNMENT, 4);
-
-    // Initialize protected EGL Context.
-    if (mProtectedEGLContext != EGL_NO_CONTEXT) {
-        EGLBoolean success = eglMakeCurrent(display, mProtectedStubSurface, mProtectedStubSurface,
-                                            mProtectedEGLContext);
-        ALOGE_IF(!success, "can't make protected context current");
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-        glPixelStorei(GL_PACK_ALIGNMENT, 4);
-        success = eglMakeCurrent(display, mStubSurface, mStubSurface, mEGLContext);
-        LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
-    }
-
-    // mColorBlindnessCorrection = M;
-
-    const ColorSpace srgb(ColorSpace::sRGB());
-    const ColorSpace displayP3(ColorSpace::DisplayP3());
-    const ColorSpace bt2020(ColorSpace::BT2020());
-
-    // no chromatic adaptation needed since all color spaces use D65 for their white points.
-    mSrgbToXyz = mat4(srgb.getRGBtoXYZ());
-    mDisplayP3ToXyz = mat4(displayP3.getRGBtoXYZ());
-    mBt2020ToXyz = mat4(bt2020.getRGBtoXYZ());
-    mXyzToSrgb = mat4(srgb.getXYZtoRGB());
-    mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB());
-    mXyzToBt2020 = mat4(bt2020.getXYZtoRGB());
-
-    // Compute sRGB to Display P3 and BT2020 transform matrix.
-    // NOTE: For now, we are limiting output wide color space support to
-    // Display-P3 and BT2020 only.
-    mSrgbToDisplayP3 = mXyzToDisplayP3 * mSrgbToXyz;
-    mSrgbToBt2020 = mXyzToBt2020 * mSrgbToXyz;
-
-    // Compute Display P3 to sRGB and BT2020 transform matrix.
-    mDisplayP3ToSrgb = mXyzToSrgb * mDisplayP3ToXyz;
-    mDisplayP3ToBt2020 = mXyzToBt2020 * mDisplayP3ToXyz;
-
-    // Compute BT2020 to sRGB and Display P3 transform matrix
-    mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz;
-    mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz;
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.egl.traceGpuCompletion", value, "0");
-    if (atoi(value)) {
-        mTraceGpuCompletion = true;
-        mFlushTracer = std::make_unique<FlushTracer>(this);
-    }
-
-    if (args.supportsBackgroundBlur) {
-        mBlurFilter = new BlurFilter(*this);
-        checkErrors("BlurFilter creation");
-    }
-
-    mImageManager = std::make_unique<ImageManager>(this);
-    mImageManager->initThread();
-    mDrawingBuffer = createFramebuffer();
-    sp<GraphicBuffer> buf =
-            sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBA_8888, 1,
-                                    GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE,
-                                    "placeholder");
-
-    const status_t err = buf->initCheck();
-    if (err != OK) {
-        ALOGE("Error allocating placeholder buffer: %d", err);
-        return;
-    }
-    mPlaceholderBuffer = buf.get();
-    EGLint attributes[] = {
-            EGL_NONE,
-    };
-    mPlaceholderImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                          mPlaceholderBuffer, attributes);
-    ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
-             eglGetError());
-
-    mShadowTexture = std::make_unique<GLShadowTexture>();
-}
-
-GLESRenderEngine::~GLESRenderEngine() {
-    // Destroy the image manager first.
-    mImageManager = nullptr;
-    mShadowTexture = nullptr;
-    cleanFramebufferCache();
-    ProgramCache::getInstance().purgeCaches();
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    glDisableVertexAttribArray(Program::position);
-    unbindFrameBuffer(mDrawingBuffer.get());
-    mDrawingBuffer = nullptr;
-    eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
-    mImageCache.clear();
-    if (mStubSurface != EGL_NO_SURFACE) {
-        eglDestroySurface(mEGLDisplay, mStubSurface);
-    }
-    if (mProtectedStubSurface != EGL_NO_SURFACE) {
-        eglDestroySurface(mEGLDisplay, mProtectedStubSurface);
-    }
-    if (mEGLContext != EGL_NO_CONTEXT) {
-        eglDestroyContext(mEGLDisplay, mEGLContext);
-    }
-    if (mProtectedEGLContext != EGL_NO_CONTEXT) {
-        eglDestroyContext(mEGLDisplay, mProtectedEGLContext);
-    }
-    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(mEGLDisplay);
-    eglReleaseThread();
-}
-
-std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
-    return std::make_unique<GLFramebuffer>(*this);
-}
-
-std::unique_ptr<Image> GLESRenderEngine::createImage() {
-    return std::make_unique<GLImage>(*this);
-}
-
-Framebuffer* GLESRenderEngine::getFramebufferForDrawing() {
-    return mDrawingBuffer.get();
-}
-
-std::future<void> GLESRenderEngine::primeCache() {
-    ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
-                                           mPrecacheToneMapperShaderOnly);
-    return {};
-}
-
-base::unique_fd GLESRenderEngine::flush() {
-    ATRACE_CALL();
-    if (!GLExtensions::getInstance().hasNativeFenceSync()) {
-        return base::unique_fd();
-    }
-
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
-        return base::unique_fd();
-    }
-
-    // native fence fd will not be populated until flush() is done.
-    glFlush();
-
-    // get the fence fd
-    base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-        ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
-    }
-
-    // Only trace if we have a valid fence, as current usage falls back to
-    // calling finish() if the fence fd is invalid.
-    if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() >= 0) {
-        mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
-    }
-
-    return fenceFd;
-}
-
-bool GLESRenderEngine::finish() {
-    ATRACE_CALL();
-    if (!GLExtensions::getInstance().hasFenceSync()) {
-        ALOGW("no synchronization support");
-        return false;
-    }
-
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGW("failed to create EGL fence sync: %#x", eglGetError());
-        return false;
-    }
-
-    if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer)) {
-        mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
-    }
-
-    return waitSync(sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR);
-}
-
-bool GLESRenderEngine::waitSync(EGLSyncKHR sync, EGLint flags) {
-    EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, flags, 2000000000 /*2 sec*/);
-    EGLint error = eglGetError();
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (result != EGL_CONDITION_SATISFIED_KHR) {
-        if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-            ALOGW("fence wait timed out");
-        } else {
-            ALOGW("error waiting on EGL fence: %#x", error);
-        }
-        return false;
-    }
-
-    return true;
-}
-
-bool GLESRenderEngine::waitFence(base::unique_fd fenceFd) {
-    if (!GLExtensions::getInstance().hasNativeFenceSync() ||
-        !GLExtensions::getInstance().hasWaitSync()) {
-        return false;
-    }
-
-    // release the fd and transfer the ownership to EGLSync
-    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
-        return false;
-    }
-
-    // XXX: The spec draft is inconsistent as to whether this should return an
-    // EGLint or void.  Ignore the return value for now, as it's not strictly
-    // needed.
-    eglWaitSyncKHR(mEGLDisplay, sync, 0);
-    EGLint error = eglGetError();
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (error != EGL_SUCCESS) {
-        ALOGE("failed to wait for EGL native fence sync: %#x", error);
-        return false;
-    }
-
-    return true;
-}
-
-void GLESRenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
-    ATRACE_CALL();
-    glDisable(GL_BLEND);
-    glClearColor(red, green, blue, alpha);
-    glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void GLESRenderEngine::fillRegionWithColor(const Region& region, float red, float green, float blue,
-                                           float alpha) {
-    size_t c;
-    Rect const* r = region.getArray(&c);
-    Mesh mesh = Mesh::Builder()
-                        .setPrimitive(Mesh::TRIANGLES)
-                        .setVertices(c * 6 /* count */, 2 /* size */)
-                        .build();
-    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    for (size_t i = 0; i < c; i++, r++) {
-        position[i * 6 + 0].x = r->left;
-        position[i * 6 + 0].y = r->top;
-        position[i * 6 + 1].x = r->left;
-        position[i * 6 + 1].y = r->bottom;
-        position[i * 6 + 2].x = r->right;
-        position[i * 6 + 2].y = r->bottom;
-        position[i * 6 + 3].x = r->left;
-        position[i * 6 + 3].y = r->top;
-        position[i * 6 + 4].x = r->right;
-        position[i * 6 + 4].y = r->bottom;
-        position[i * 6 + 5].x = r->right;
-        position[i * 6 + 5].y = r->top;
-    }
-    setupFillWithColor(red, green, blue, alpha);
-    drawMesh(mesh);
-}
-
-void GLESRenderEngine::setScissor(const Rect& region) {
-    glScissor(region.left, region.top, region.getWidth(), region.getHeight());
-    glEnable(GL_SCISSOR_TEST);
-}
-
-void GLESRenderEngine::disableScissor() {
-    glDisable(GL_SCISSOR_TEST);
-}
-
-void GLESRenderEngine::genTextures(size_t count, uint32_t* names) {
-    glGenTextures(count, names);
-}
-
-void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
-    for (int i = 0; i < count; ++i) {
-        mTextureView.erase(names[i]);
-    }
-    glDeleteTextures(count, names);
-}
-
-void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
-    ATRACE_CALL();
-    const GLImage& glImage = static_cast<const GLImage&>(image);
-    const GLenum target = GL_TEXTURE_EXTERNAL_OES;
-
-    glBindTexture(target, texName);
-    if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
-        glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
-    }
-}
-
-void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer,
-                                                 const sp<Fence>& bufferFence) {
-    ATRACE_CALL();
-
-    bool found = false;
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        auto cachedImage = mImageCache.find(buffer->getId());
-        found = (cachedImage != mImageCache.end());
-    }
-
-    // If we couldn't find the image in the cache at this time, then either
-    // SurfaceFlinger messed up registering the buffer ahead of time or we got
-    // backed up creating other EGLImages.
-    if (!found) {
-        status_t cacheResult = mImageManager->cache(buffer);
-        if (cacheResult != NO_ERROR) {
-            ALOGE("Error with caching buffer: %d", cacheResult);
-            return;
-        }
-    }
-
-    // Whether or not we needed to cache, re-check mImageCache to make sure that
-    // there's an EGLImage. The current threading model guarantees that we don't
-    // destroy a cached image until it's really not needed anymore (i.e. this
-    // function should not be called), so the only possibility is that something
-    // terrible went wrong and we should just bind something and move on.
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        auto cachedImage = mImageCache.find(buffer->getId());
-
-        if (cachedImage == mImageCache.end()) {
-            // We failed creating the image if we got here, so bail out.
-            ALOGE("Failed to create an EGLImage when rendering");
-            bindExternalTextureImage(texName, *createImage());
-            return;
-        }
-
-        bindExternalTextureImage(texName, *cachedImage->second);
-        mTextureView.insert_or_assign(texName, buffer->getId());
-    }
-
-    // Wait for the new buffer to be ready.
-    if (bufferFence != nullptr && bufferFence->isValid()) {
-        if (GLExtensions::getInstance().hasWaitSync()) {
-            base::unique_fd fenceFd(bufferFence->dup());
-            if (fenceFd == -1) {
-                ALOGE("error dup'ing fence fd: %d", errno);
-                return;
-            }
-            if (!waitFence(std::move(fenceFd))) {
-                ALOGE("failed to wait on fence fd");
-                return;
-            }
-        } else {
-            status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
-            if (err != NO_ERROR) {
-                ALOGE("error waiting for fence: %d", err);
-                return;
-            }
-        }
-    }
-
-    return;
-}
-
-void GLESRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
-                                                bool /*isRenderable*/) {
-    ATRACE_CALL();
-    mImageManager->cacheAsync(buffer, nullptr);
-}
-
-std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::cacheExternalTextureBufferForTesting(
-        const sp<GraphicBuffer>& buffer) {
-    auto barrier = std::make_shared<ImageManager::Barrier>();
-    mImageManager->cacheAsync(buffer, barrier);
-    return barrier;
-}
-
-status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer) {
-    if (buffer == nullptr) {
-        return BAD_VALUE;
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        if (mImageCache.count(buffer->getId()) > 0) {
-            // If there's already an image then fail fast here.
-            return NO_ERROR;
-        }
-    }
-    ATRACE_CALL();
-
-    // Create the image without holding a lock so that we don't block anything.
-    std::unique_ptr<Image> newImage = createImage();
-
-    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
-                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
-    if (!created) {
-        ALOGE("Failed to create image. id=%" PRIx64 " size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
-              buffer->getId(), buffer->getWidth(), buffer->getHeight(), buffer->getStride(),
-              buffer->getUsage(), buffer->getPixelFormat());
-        return NO_INIT;
-    }
-
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        if (mImageCache.count(buffer->getId()) > 0) {
-            // In theory it's possible for another thread to recache the image,
-            // so bail out if another thread won.
-            return NO_ERROR;
-        }
-        mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
-    }
-
-    return NO_ERROR;
-}
-
-void GLESRenderEngine::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
-    mImageManager->releaseAsync(buffer->getId(), nullptr);
-}
-
-std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::unbindExternalTextureBufferForTesting(
-        uint64_t bufferId) {
-    auto barrier = std::make_shared<ImageManager::Barrier>();
-    mImageManager->releaseAsync(bufferId, barrier);
-    return barrier;
-}
-
-void GLESRenderEngine::unbindExternalTextureBufferInternal(uint64_t bufferId) {
-    std::unique_ptr<Image> image;
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        const auto& cachedImage = mImageCache.find(bufferId);
-
-        if (cachedImage != mImageCache.end()) {
-            ALOGV("Destroying image for buffer: %" PRIu64, bufferId);
-            // Move the buffer out of cache first, so that we can destroy
-            // without holding the cache's lock.
-            image = std::move(cachedImage->second);
-            mImageCache.erase(bufferId);
-            return;
-        }
-    }
-    ALOGV("Failed to find image for buffer: %" PRIu64, bufferId);
-}
-
-int GLESRenderEngine::getContextPriority() {
-    int value;
-    eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value);
-    return value;
-}
-
-FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
-    // Translate win by the rounded corners rect coordinates, to have all values in
-    // layer coordinate space.
-    FloatRect cropWin = layer.geometry.boundaries;
-    const FloatRect& roundedCornersCrop = layer.geometry.roundedCornersCrop;
-    cropWin.left -= roundedCornersCrop.left;
-    cropWin.right -= roundedCornersCrop.left;
-    cropWin.top -= roundedCornersCrop.top;
-    cropWin.bottom -= roundedCornersCrop.top;
-    Mesh::VertexArray<vec2> cropCoords(mesh.getCropCoordArray<vec2>());
-    cropCoords[0] = vec2(cropWin.left, cropWin.top);
-    cropCoords[1] = vec2(cropWin.left, cropWin.top + cropWin.getHeight());
-    cropCoords[2] = vec2(cropWin.right, cropWin.top + cropWin.getHeight());
-    cropCoords[3] = vec2(cropWin.right, cropWin.top);
-
-    setupCornerRadiusCropSize(roundedCornersCrop.getWidth(), roundedCornersCrop.getHeight());
-    return cropWin;
-}
-
-void GLESRenderEngine::handleRoundedCorners(const DisplaySettings& display,
-                                            const LayerSettings& layer, const Mesh& mesh) {
-    // We separate the layer into 3 parts essentially, such that we only turn on blending for the
-    // top rectangle and the bottom rectangle, and turn off blending for the middle rectangle.
-    FloatRect bounds = layer.geometry.roundedCornersCrop;
-
-    // Explicitly compute the transform from the clip rectangle to the physical
-    // display. Normally, this is done in glViewport but we explicitly compute
-    // it here so that we can get the scissor bounds correct.
-    const Rect& source = display.clip;
-    const Rect& destination = display.physicalDisplay;
-    // Here we compute the following transform:
-    // 1. Translate the top left corner of the source clip to (0, 0)
-    // 2. Rotate the clip rectangle about the origin in accordance with the
-    // orientation flag
-    // 3. Translate the top left corner back to the origin.
-    // 4. Scale the clip rectangle to the destination rectangle dimensions
-    // 5. Translate the top left corner to the destination rectangle's top left
-    // corner.
-    const mat4 translateSource = mat4::translate(vec4(-source.left, -source.top, 0, 1));
-    mat4 rotation;
-    int displacementX = 0;
-    int displacementY = 0;
-    float destinationWidth = static_cast<float>(destination.getWidth());
-    float destinationHeight = static_cast<float>(destination.getHeight());
-    float sourceWidth = static_cast<float>(source.getWidth());
-    float sourceHeight = static_cast<float>(source.getHeight());
-    const float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
-    switch (display.orientation) {
-        case ui::Transform::ROT_90:
-            rotation = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
-            displacementX = source.getHeight();
-            std::swap(sourceHeight, sourceWidth);
-            break;
-        case ui::Transform::ROT_180:
-            rotation = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
-            displacementY = source.getHeight();
-            displacementX = source.getWidth();
-            break;
-        case ui::Transform::ROT_270:
-            rotation = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
-            displacementY = source.getWidth();
-            std::swap(sourceHeight, sourceWidth);
-            break;
-        default:
-            break;
-    }
-
-    const mat4 intermediateTranslation = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-    const mat4 scale = mat4::scale(
-            vec4(destinationWidth / sourceWidth, destinationHeight / sourceHeight, 1, 1));
-    const mat4 translateDestination =
-            mat4::translate(vec4(destination.left, destination.top, 0, 1));
-    const mat4 globalTransform =
-            translateDestination * scale * intermediateTranslation * rotation * translateSource;
-
-    const mat4 transformMatrix = globalTransform * layer.geometry.positionTransform;
-    const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
-    const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
-    const vec4 leftTopCoordinateInBuffer = transformMatrix * leftTopCoordinate;
-    const vec4 rightBottomCoordinateInBuffer = transformMatrix * rightBottomCoordinate;
-    bounds = FloatRect(std::min(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
-                       std::min(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]),
-                       std::max(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
-                       std::max(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]));
-
-    // Finally, we cut the layer into 3 parts, with top and bottom parts having rounded corners
-    // and the middle part without rounded corners.
-    const int32_t radius = ceil(
-            (layer.geometry.roundedCornersRadius.x + layer.geometry.roundedCornersRadius.y) / 2.0);
-    const Rect topRect(bounds.left, bounds.top, bounds.right, bounds.top + radius);
-    setScissor(topRect);
-    drawMesh(mesh);
-    const Rect bottomRect(bounds.left, bounds.bottom - radius, bounds.right, bounds.bottom);
-    setScissor(bottomRect);
-    drawMesh(mesh);
-
-    // The middle part of the layer can turn off blending.
-    if (topRect.bottom < bottomRect.top) {
-        const Rect middleRect(bounds.left, bounds.top + radius, bounds.right,
-                              bounds.bottom - radius);
-        setScissor(middleRect);
-        mState.cornerRadius = 0.0;
-        disableBlending();
-        drawMesh(mesh);
-    }
-    disableScissor();
-}
-
-status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
-    ATRACE_CALL();
-    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
-    EGLImageKHR eglImage = glFramebuffer->getEGLImage();
-    uint32_t textureName = glFramebuffer->getTextureName();
-    uint32_t framebufferName = glFramebuffer->getFramebufferName();
-
-    // Bind the texture and turn our EGLImage into a texture
-    glBindTexture(GL_TEXTURE_2D, textureName);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
-
-    // Bind the Framebuffer to render into
-    glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
-
-    uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
-             glStatus);
-
-    return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
-}
-
-void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) {
-    ATRACE_CALL();
-
-    // back to main framebuffer
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-bool GLESRenderEngine::canSkipPostRenderCleanup() const {
-    return mPriorResourcesCleaned ||
-            (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled);
-}
-
-void GLESRenderEngine::cleanupPostRender() {
-    ATRACE_CALL();
-
-    if (canSkipPostRenderCleanup()) {
-        // If we don't have a prior frame needing cleanup, then don't do anything.
-        return;
-    }
-
-    // Bind the texture to placeholder so that backing image data can be freed.
-    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
-    glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
-
-    // Release the cached fence here, so that we don't churn reallocations when
-    // we could no-op repeated calls of this method instead.
-    mLastDrawFence = nullptr;
-    mPriorResourcesCleaned = true;
-}
-
-void GLESRenderEngine::cleanFramebufferCache() {
-    std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
-    // Bind the texture to placeholder so that backing image data can be freed.
-    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
-    glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
-
-    while (!mFramebufferImageCache.empty()) {
-        EGLImageKHR expired = mFramebufferImageCache.front().second;
-        mFramebufferImageCache.pop_front();
-        eglDestroyImageKHR(mEGLDisplay, expired);
-        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
-    }
-}
-
-void GLESRenderEngine::checkErrors() const {
-    checkErrors(nullptr);
-}
-
-void GLESRenderEngine::checkErrors(const char* tag) const {
-    do {
-        // there could be more than one error flag
-        GLenum error = glGetError();
-        if (error == GL_NO_ERROR) break;
-        if (tag == nullptr) {
-            ALOGE("GL error 0x%04x", int(error));
-        } else {
-            ALOGE("GL error: %s -> 0x%04x", tag, int(error));
-        }
-    } while (true);
-}
-
-bool GLESRenderEngine::supportsProtectedContent() const {
-    return mProtectedEGLContext != EGL_NO_CONTEXT;
-}
-
-void GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
-    if (useProtectedContext == mInProtectedContext ||
-        (useProtectedContext && !supportsProtectedContent())) {
-        return;
-    }
-
-    const EGLSurface surface = useProtectedContext ? mProtectedStubSurface : mStubSurface;
-    const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
-    if (eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE) {
-        mInProtectedContext = useProtectedContext;
-    }
-}
-EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
-                                                             bool isProtected,
-                                                             bool useFramebufferCache) {
-    sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
-    if (useFramebufferCache) {
-        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
-        for (const auto& image : mFramebufferImageCache) {
-            if (image.first == graphicBuffer->getId()) {
-                return image.second;
-            }
-        }
-    }
-    EGLint attributes[] = {
-            isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
-            isProtected ? EGL_TRUE : EGL_NONE,
-            EGL_NONE,
-    };
-    EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                          nativeBuffer, attributes);
-    if (useFramebufferCache) {
-        if (image != EGL_NO_IMAGE_KHR) {
-            std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
-            if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
-                EGLImageKHR expired = mFramebufferImageCache.front().second;
-                mFramebufferImageCache.pop_front();
-                eglDestroyImageKHR(mEGLDisplay, expired);
-                DEBUG_EGL_IMAGE_TRACKER_DESTROY();
-            }
-            mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
-        }
-    }
-
-    if (image != EGL_NO_IMAGE_KHR) {
-        DEBUG_EGL_IMAGE_TRACKER_CREATE();
-    }
-    return image;
-}
-
-void GLESRenderEngine::drawLayersInternal(
-        const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
-        const DisplaySettings& display, const std::vector<LayerSettings>& layers,
-        const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
-        base::unique_fd&& bufferFence) {
-    ATRACE_CALL();
-    if (layers.empty()) {
-        ALOGV("Drawing empty layer stack");
-        resultPromise->set_value(Fence::NO_FENCE);
-        return;
-    }
-
-    if (bufferFence.get() >= 0) {
-        // Duplicate the fence for passing to waitFence.
-        base::unique_fd bufferFenceDup(dup(bufferFence.get()));
-        if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
-            ATRACE_NAME("Waiting before draw");
-            sync_wait(bufferFence.get(), -1);
-        }
-    }
-
-    if (buffer == nullptr) {
-        ALOGE("No output buffer provided. Aborting GPU composition.");
-        resultPromise->set_value(base::unexpected(BAD_VALUE));
-        return;
-    }
-
-    validateOutputBufferUsage(buffer->getBuffer());
-
-    std::unique_ptr<BindNativeBufferAsFramebuffer> fbo;
-    // Gathering layers that requested blur, we'll need them to decide when to render to an
-    // offscreen buffer, and when to render to the native buffer.
-    std::deque<const LayerSettings> blurLayers;
-    if (CC_LIKELY(mBlurFilter != nullptr)) {
-        for (const auto& layer : layers) {
-            if (layer.backgroundBlurRadius > 0) {
-                blurLayers.push_back(layer);
-            }
-        }
-    }
-    const auto blurLayersSize = blurLayers.size();
-
-    if (blurLayersSize == 0) {
-        fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this,
-                                                              buffer->getBuffer()
-                                                                      .get()
-                                                                      ->getNativeBuffer(),
-                                                              useFramebufferCache);
-        if (fbo->getStatus() != NO_ERROR) {
-            ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
-                  buffer->getBuffer()->handle);
-            checkErrors();
-            resultPromise->set_value(base::unexpected(fbo->getStatus()));
-            return;
-        }
-        setViewportAndProjection(display.physicalDisplay, display.clip);
-    } else {
-        setViewportAndProjection(display.physicalDisplay, display.clip);
-        auto status =
-                mBlurFilter->setAsDrawTarget(display, blurLayers.front().backgroundBlurRadius);
-        if (status != NO_ERROR) {
-            ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
-                  buffer->getBuffer()->handle);
-            checkErrors();
-            resultPromise->set_value(base::unexpected(status));
-            return;
-        }
-    }
-
-    // clear the entire buffer, sometimes when we reuse buffers we'd persist
-    // ghost images otherwise.
-    // we also require a full transparent framebuffer for overlays. This is
-    // probably not quite efficient on all GPUs, since we could filter out
-    // opaque layers.
-    clearWithColor(0.0, 0.0, 0.0, 0.0);
-
-    setOutputDataSpace(display.outputDataspace);
-    setDisplayMaxLuminance(display.maxLuminance);
-    setDisplayColorTransform(display.colorTransform);
-
-    const mat4 projectionMatrix =
-            ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
-
-    Mesh mesh = Mesh::Builder()
-                        .setPrimitive(Mesh::TRIANGLE_FAN)
-                        .setVertices(4 /* count */, 2 /* size */)
-                        .setTexCoords(2 /* size */)
-                        .setCropCoords(2 /* size */)
-                        .build();
-    for (const auto& layer : layers) {
-        if (blurLayers.size() > 0 && blurLayers.front() == layer) {
-            blurLayers.pop_front();
-
-            auto status = mBlurFilter->prepare();
-            if (status != NO_ERROR) {
-                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
-                      buffer->getBuffer()->handle);
-                checkErrors("Can't render first blur pass");
-                resultPromise->set_value(base::unexpected(status));
-                return;
-            }
-
-            if (blurLayers.size() == 0) {
-                // Done blurring, time to bind the native FBO and render our blur onto it.
-                fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this,
-                                                                      buffer.get()
-                                                                              ->getBuffer()
-                                                                              ->getNativeBuffer(),
-                                                                      useFramebufferCache);
-                status = fbo->getStatus();
-                setViewportAndProjection(display.physicalDisplay, display.clip);
-            } else {
-                // There's still something else to blur, so let's keep rendering to our FBO
-                // instead of to the display.
-                status = mBlurFilter->setAsDrawTarget(display,
-                                                      blurLayers.front().backgroundBlurRadius);
-            }
-            if (status != NO_ERROR) {
-                ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
-                      buffer->getBuffer()->handle);
-                checkErrors("Can't bind native framebuffer");
-                resultPromise->set_value(base::unexpected(status));
-                return;
-            }
-
-            status = mBlurFilter->render(blurLayersSize > 1);
-            if (status != NO_ERROR) {
-                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
-                      buffer->getBuffer()->handle);
-                checkErrors("Can't render blur filter");
-                resultPromise->set_value(base::unexpected(status));
-                return;
-            }
-        }
-
-        // Ensure luminance is at least 100 nits to avoid div-by-zero
-        const float maxLuminance = std::max(100.f, layer.source.buffer.maxLuminanceNits);
-        mState.maxMasteringLuminance = maxLuminance;
-        mState.maxContentLuminance = maxLuminance;
-        mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
-
-        const FloatRect bounds = layer.geometry.boundaries;
-        Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-        position[0] = vec2(bounds.left, bounds.top);
-        position[1] = vec2(bounds.left, bounds.bottom);
-        position[2] = vec2(bounds.right, bounds.bottom);
-        position[3] = vec2(bounds.right, bounds.top);
-
-        setupLayerCropping(layer, mesh);
-        setColorTransform(layer.colorTransform);
-
-        bool usePremultipliedAlpha = true;
-        bool disableTexture = true;
-        bool isOpaque = false;
-        if (layer.source.buffer.buffer != nullptr) {
-            disableTexture = false;
-            isOpaque = layer.source.buffer.isOpaque;
-
-            sp<GraphicBuffer> gBuf = layer.source.buffer.buffer->getBuffer();
-            validateInputBufferUsage(gBuf);
-            bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
-                                      layer.source.buffer.fence);
-
-            usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
-            Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
-            mat4 texMatrix = layer.source.buffer.textureTransform;
-
-            texture.setMatrix(texMatrix.asArray());
-            texture.setFiltering(layer.source.buffer.useTextureFiltering);
-
-            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
-
-            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
-            texCoords[0] = vec2(0.0, 0.0);
-            texCoords[1] = vec2(0.0, 1.0);
-            texCoords[2] = vec2(1.0, 1.0);
-            texCoords[3] = vec2(1.0, 0.0);
-            setupLayerTexturing(texture);
-
-            // Do not cache protected EGLImage, protected memory is limited.
-            if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) {
-                unmapExternalTextureBuffer(std::move(gBuf));
-            }
-        }
-
-        const half3 solidColor = layer.source.solidColor;
-        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
-        const float radius =
-                (layer.geometry.roundedCornersRadius.x + layer.geometry.roundedCornersRadius.y) /
-                2.0f;
-        // Buffer sources will have a black solid color ignored in the shader,
-        // so in that scenario the solid color passed here is arbitrary.
-        setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, radius);
-        if (layer.disableBlending) {
-            glDisable(GL_BLEND);
-        }
-        setSourceDataSpace(layer.sourceDataspace);
-
-        if (layer.shadow.length > 0.0f) {
-            handleShadow(layer.geometry.boundaries, radius, layer.shadow);
-        }
-        // We only want to do a special handling for rounded corners when having rounded corners
-        // is the only reason it needs to turn on blending, otherwise, we handle it like the
-        // usual way since it needs to turn on blending anyway.
-        else if (radius > 0.0 && color.a >= 1.0f && isOpaque) {
-            handleRoundedCorners(display, layer, mesh);
-        } else {
-            drawMesh(mesh);
-        }
-
-        // Cleanup if there's a buffer source
-        if (layer.source.buffer.buffer != nullptr) {
-            disableBlending();
-            disableTexturing();
-        }
-    }
-
-    base::unique_fd drawFence = flush();
-
-    // If flush failed or we don't support native fences, we need to force the
-    // gl command stream to be executed.
-    if (drawFence.get() < 0) {
-        bool success = finish();
-        if (!success) {
-            ALOGE("Failed to flush RenderEngine commands");
-            checkErrors();
-            // Chances are, something illegal happened (either the caller passed
-            // us bad parameters, or we messed up our shader generation).
-            resultPromise->set_value(base::unexpected(INVALID_OPERATION));
-            return;
-        }
-        mLastDrawFence = nullptr;
-    } else {
-        // The caller takes ownership of drawFence, so we need to duplicate the
-        // fd here.
-        mLastDrawFence = new Fence(dup(drawFence.get()));
-    }
-    mPriorResourcesCleaned = false;
-
-    checkErrors();
-    resultPromise->set_value(sp<Fence>::make(std::move(drawFence)));
-}
-
-void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
-    ATRACE_CALL();
-    mVpWidth = viewport.getWidth();
-    mVpHeight = viewport.getHeight();
-
-    // We pass the the top left corner instead of the bottom left corner,
-    // because since we're rendering off-screen first.
-    glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight);
-
-    mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1);
-}
-
-void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                                          const half4& color, float cornerRadius) {
-    mState.isPremultipliedAlpha = premultipliedAlpha;
-    mState.isOpaque = opaque;
-    mState.color = color;
-    mState.cornerRadius = cornerRadius;
-
-    if (disableTexture) {
-        mState.textureEnabled = false;
-    }
-
-    if (color.a < 1.0f || !opaque || cornerRadius > 0.0f) {
-        glEnable(GL_BLEND);
-        glBlendFuncSeparate(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
-                            GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    } else {
-        glDisable(GL_BLEND);
-    }
-}
-
-void GLESRenderEngine::setSourceDataSpace(Dataspace source) {
-    mDataSpace = source;
-}
-
-void GLESRenderEngine::setOutputDataSpace(Dataspace dataspace) {
-    mOutputDataSpace = dataspace;
-}
-
-void GLESRenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
-    mState.displayMaxLuminance = maxLuminance;
-}
-
-void GLESRenderEngine::setupLayerTexturing(const Texture& texture) {
-    GLuint target = texture.getTextureTarget();
-    glBindTexture(target, texture.getTextureName());
-    GLenum filter = GL_NEAREST;
-    if (texture.getFiltering()) {
-        filter = GL_LINEAR;
-    }
-    glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
-    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
-
-    mState.texture = texture;
-    mState.textureEnabled = true;
-}
-
-void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
-    mState.colorMatrix = colorTransform;
-}
-
-void GLESRenderEngine::setDisplayColorTransform(const mat4& colorTransform) {
-    mState.displayColorMatrix = colorTransform;
-}
-
-void GLESRenderEngine::disableTexturing() {
-    mState.textureEnabled = false;
-}
-
-void GLESRenderEngine::disableBlending() {
-    glDisable(GL_BLEND);
-}
-
-void GLESRenderEngine::setupFillWithColor(float r, float g, float b, float a) {
-    mState.isPremultipliedAlpha = true;
-    mState.isOpaque = false;
-    mState.color = half4(r, g, b, a);
-    mState.textureEnabled = false;
-    glDisable(GL_BLEND);
-}
-
-void GLESRenderEngine::setupCornerRadiusCropSize(float width, float height) {
-    mState.cropSize = half2(width, height);
-}
-
-void GLESRenderEngine::drawMesh(const Mesh& mesh) {
-    ATRACE_CALL();
-    if (mesh.getTexCoordsSize()) {
-        glEnableVertexAttribArray(Program::texCoords);
-        glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE,
-                              mesh.getByteStride(), mesh.getTexCoords());
-    }
-
-    glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
-                          mesh.getByteStride(), mesh.getPositions());
-
-    if (mState.cornerRadius > 0.0f) {
-        glEnableVertexAttribArray(Program::cropCoords);
-        glVertexAttribPointer(Program::cropCoords, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
-                              mesh.getByteStride(), mesh.getCropCoords());
-    }
-
-    if (mState.drawShadows) {
-        glEnableVertexAttribArray(Program::shadowColor);
-        glVertexAttribPointer(Program::shadowColor, mesh.getShadowColorSize(), GL_FLOAT, GL_FALSE,
-                              mesh.getByteStride(), mesh.getShadowColor());
-
-        glEnableVertexAttribArray(Program::shadowParams);
-        glVertexAttribPointer(Program::shadowParams, mesh.getShadowParamsSize(), GL_FLOAT, GL_FALSE,
-                              mesh.getByteStride(), mesh.getShadowParams());
-    }
-
-    Description managedState = mState;
-    // By default, DISPLAY_P3 is the only supported wide color output. However,
-    // when HDR content is present, hardware composer may be able to handle
-    // BT2020 data space, in that case, the output data space is set to be
-    // BT2020_HLG or BT2020_PQ respectively. In GPU fall back we need
-    // to respect this and convert non-HDR content to HDR format.
-    Dataspace inputStandard = static_cast<Dataspace>(mDataSpace & Dataspace::STANDARD_MASK);
-    Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
-    Dataspace outputStandard = static_cast<Dataspace>(mOutputDataSpace & Dataspace::STANDARD_MASK);
-    Dataspace outputTransfer = static_cast<Dataspace>(mOutputDataSpace & Dataspace::TRANSFER_MASK);
-    bool needsXYZConversion = needsXYZTransformMatrix();
-
-    // NOTE: if the input standard of the input dataspace is not STANDARD_DCI_P3 or
-    // STANDARD_BT2020, it will be  treated as STANDARD_BT709
-    if (inputStandard != Dataspace::STANDARD_DCI_P3 &&
-        inputStandard != Dataspace::STANDARD_BT2020) {
-        inputStandard = Dataspace::STANDARD_BT709;
-    }
-
-    if (needsXYZConversion) {
-        // The supported input color spaces are standard RGB, Display P3 and BT2020.
-        switch (inputStandard) {
-            case Dataspace::STANDARD_DCI_P3:
-                managedState.inputTransformMatrix = mDisplayP3ToXyz;
-                break;
-            case Dataspace::STANDARD_BT2020:
-                managedState.inputTransformMatrix = mBt2020ToXyz;
-                break;
-            default:
-                managedState.inputTransformMatrix = mSrgbToXyz;
-                break;
-        }
-
-        // The supported output color spaces are BT2020, Display P3 and standard RGB.
-        switch (outputStandard) {
-            case Dataspace::STANDARD_BT2020:
-                managedState.outputTransformMatrix = mXyzToBt2020;
-                break;
-            case Dataspace::STANDARD_DCI_P3:
-                managedState.outputTransformMatrix = mXyzToDisplayP3;
-                break;
-            default:
-                managedState.outputTransformMatrix = mXyzToSrgb;
-                break;
-        }
-    } else if (inputStandard != outputStandard) {
-        // At this point, the input data space and output data space could be both
-        // HDR data spaces, but they match each other, we do nothing in this case.
-        // In addition to the case above, the input data space could be
-        // - scRGB linear
-        // - scRGB non-linear
-        // - sRGB
-        // - Display P3
-        // - BT2020
-        // The output data spaces could be
-        // - sRGB
-        // - Display P3
-        // - BT2020
-        switch (outputStandard) {
-            case Dataspace::STANDARD_BT2020:
-                if (inputStandard == Dataspace::STANDARD_BT709) {
-                    managedState.outputTransformMatrix = mSrgbToBt2020;
-                } else if (inputStandard == Dataspace::STANDARD_DCI_P3) {
-                    managedState.outputTransformMatrix = mDisplayP3ToBt2020;
-                }
-                break;
-            case Dataspace::STANDARD_DCI_P3:
-                if (inputStandard == Dataspace::STANDARD_BT709) {
-                    managedState.outputTransformMatrix = mSrgbToDisplayP3;
-                } else if (inputStandard == Dataspace::STANDARD_BT2020) {
-                    managedState.outputTransformMatrix = mBt2020ToDisplayP3;
-                }
-                break;
-            default:
-                if (inputStandard == Dataspace::STANDARD_DCI_P3) {
-                    managedState.outputTransformMatrix = mDisplayP3ToSrgb;
-                } else if (inputStandard == Dataspace::STANDARD_BT2020) {
-                    managedState.outputTransformMatrix = mBt2020ToSrgb;
-                }
-                break;
-        }
-    }
-
-    // we need to convert the RGB value to linear space and convert it back when:
-    // - there is a color matrix that is not an identity matrix, or
-    // - there is an output transform matrix that is not an identity matrix, or
-    // - the input transfer function doesn't match the output transfer function.
-    if (managedState.hasColorMatrix() || managedState.hasOutputTransformMatrix() ||
-        inputTransfer != outputTransfer) {
-        managedState.inputTransferFunction =
-                Description::dataSpaceToTransferFunction(inputTransfer);
-        managedState.outputTransferFunction =
-                Description::dataSpaceToTransferFunction(outputTransfer);
-    }
-
-    ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
-                                           managedState);
-
-    if (mState.drawShadows) {
-        glDrawElements(mesh.getPrimitive(), mesh.getIndexCount(), GL_UNSIGNED_SHORT,
-                       mesh.getIndices());
-    } else {
-        glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
-    }
-
-    if (outputDebugPPMs) {
-        static uint64_t managedColorFrameCount = 0;
-        std::ostringstream out;
-        out << "/data/texture_out" << managedColorFrameCount++;
-        writePPM(out.str().c_str(), mVpWidth, mVpHeight);
-    }
-
-    if (mesh.getTexCoordsSize()) {
-        glDisableVertexAttribArray(Program::texCoords);
-    }
-
-    if (mState.cornerRadius > 0.0f) {
-        glDisableVertexAttribArray(Program::cropCoords);
-    }
-
-    if (mState.drawShadows) {
-        glDisableVertexAttribArray(Program::shadowColor);
-        glDisableVertexAttribArray(Program::shadowParams);
-    }
-}
-
-size_t GLESRenderEngine::getMaxTextureSize() const {
-    return mMaxTextureSize;
-}
-
-size_t GLESRenderEngine::getMaxViewportDims() const {
-    return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
-}
-
-void GLESRenderEngine::dump(std::string& result) {
-    const GLExtensions& extensions = GLExtensions::getInstance();
-    ProgramCache& cache = ProgramCache::getInstance();
-
-    StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
-    StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
-    StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
-                  extensions.getVersion());
-    StringAppendF(&result, "%s\n", extensions.getExtensions());
-    StringAppendF(&result, "RenderEngine supports protected context: %d\n",
-                  supportsProtectedContent());
-    StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
-    StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n",
-                  cache.getSize(mEGLContext));
-    StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n",
-                  cache.getSize(mProtectedEGLContext));
-    StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
-                  dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
-                  dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
-    {
-        std::lock_guard<std::mutex> lock(mRenderingMutex);
-        StringAppendF(&result, "RenderEngine image cache size: %zu\n", mImageCache.size());
-        StringAppendF(&result, "Dumping buffer ids...\n");
-        for (const auto& [id, unused] : mImageCache) {
-            StringAppendF(&result, "0x%" PRIx64 "\n", id);
-        }
-    }
-    {
-        std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
-        StringAppendF(&result, "RenderEngine framebuffer image cache size: %zu\n",
-                      mFramebufferImageCache.size());
-        StringAppendF(&result, "Dumping buffer ids...\n");
-        for (const auto& [id, unused] : mFramebufferImageCache) {
-            StringAppendF(&result, "0x%" PRIx64 "\n", id);
-        }
-    }
-}
-
-GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
-    int major, minor;
-    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
-        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
-            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
-            return GLES_VERSION_1_0;
-        }
-    }
-
-    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
-    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
-    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
-    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
-
-    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
-    return GLES_VERSION_1_0;
-}
-
-EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
-                                              EGLContext shareContext,
-                                              std::optional<ContextPriority> contextPriority,
-                                              Protection protection) {
-    EGLint renderableType = 0;
-    if (config == EGL_NO_CONFIG) {
-        renderableType = EGL_OPENGL_ES3_BIT;
-    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
-        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
-    }
-    EGLint contextClientVersion = 0;
-    if (renderableType & EGL_OPENGL_ES3_BIT) {
-        contextClientVersion = 3;
-    } else if (renderableType & EGL_OPENGL_ES2_BIT) {
-        contextClientVersion = 2;
-    } else if (renderableType & EGL_OPENGL_ES_BIT) {
-        contextClientVersion = 1;
-    } else {
-        LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
-    }
-
-    std::vector<EGLint> contextAttributes;
-    contextAttributes.reserve(7);
-    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
-    contextAttributes.push_back(contextClientVersion);
-    if (contextPriority) {
-        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
-        switch (*contextPriority) {
-            case ContextPriority::REALTIME:
-                contextAttributes.push_back(EGL_CONTEXT_PRIORITY_REALTIME_NV);
-                break;
-            case ContextPriority::MEDIUM:
-                contextAttributes.push_back(EGL_CONTEXT_PRIORITY_MEDIUM_IMG);
-                break;
-            case ContextPriority::LOW:
-                contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LOW_IMG);
-                break;
-            case ContextPriority::HIGH:
-            default:
-                contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
-                break;
-        }
-    }
-    if (protection == Protection::PROTECTED) {
-        contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
-        contextAttributes.push_back(EGL_TRUE);
-    }
-    contextAttributes.push_back(EGL_NONE);
-
-    EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
-
-    if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
-        // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
-        // EGL_NO_CONTEXT so that we can abort.
-        if (config != EGL_NO_CONFIG) {
-            return context;
-        }
-        // If |config| is EGL_NO_CONFIG, we speculatively try to create GLES 3 context, so we should
-        // try to fall back to GLES 2.
-        contextAttributes[1] = 2;
-        context = eglCreateContext(display, config, shareContext, contextAttributes.data());
-    }
-
-    return context;
-}
-
-EGLSurface GLESRenderEngine::createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
-                                                         int hwcFormat, Protection protection) {
-    EGLConfig stubConfig = config;
-    if (stubConfig == EGL_NO_CONFIG) {
-        stubConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
-    }
-    std::vector<EGLint> attributes;
-    attributes.reserve(7);
-    attributes.push_back(EGL_WIDTH);
-    attributes.push_back(1);
-    attributes.push_back(EGL_HEIGHT);
-    attributes.push_back(1);
-    if (protection == Protection::PROTECTED) {
-        attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
-        attributes.push_back(EGL_TRUE);
-    }
-    attributes.push_back(EGL_NONE);
-
-    return eglCreatePbufferSurface(display, stubConfig, attributes.data());
-}
-
-bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
-    const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
-    const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
-    return standard == Dataspace::STANDARD_BT2020 &&
-            (transfer == Dataspace::TRANSFER_ST2084 || transfer == Dataspace::TRANSFER_HLG);
-}
-
-// For convenience, we want to convert the input color space to XYZ color space first,
-// and then convert from XYZ color space to output color space when
-// - SDR and HDR contents are mixed, either SDR content will be converted to HDR or
-//   HDR content will be tone-mapped to SDR; Or,
-// - there are HDR PQ and HLG contents presented at the same time, where we want to convert
-//   HLG content to PQ content.
-// In either case above, we need to operate the Y value in XYZ color space. Thus, when either
-// input data space or output data space is HDR data space, and the input transfer function
-// doesn't match the output transfer function, we would enable an intermediate transfrom to
-// XYZ color space.
-bool GLESRenderEngine::needsXYZTransformMatrix() const {
-    const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace);
-    const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace);
-    const Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
-    const Dataspace outputTransfer =
-            static_cast<Dataspace>(mOutputDataSpace & Dataspace::TRANSFER_MASK);
-
-    return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
-}
-
-bool GLESRenderEngine::isImageCachedForTesting(uint64_t bufferId) {
-    std::lock_guard<std::mutex> lock(mRenderingMutex);
-    const auto& cachedImage = mImageCache.find(bufferId);
-    return cachedImage != mImageCache.end();
-}
-
-bool GLESRenderEngine::isTextureNameKnownForTesting(uint32_t texName) {
-    const auto& entry = mTextureView.find(texName);
-    return entry != mTextureView.end();
-}
-
-std::optional<uint64_t> GLESRenderEngine::getBufferIdForTextureNameForTesting(uint32_t texName) {
-    const auto& entry = mTextureView.find(texName);
-    return entry != mTextureView.end() ? entry->second : std::nullopt;
-}
-
-bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
-    std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
-    return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
-                       [=](std::pair<uint64_t, EGLImageKHR> image) {
-                           return image.first == bufferId;
-                       });
-}
-
-// FlushTracer implementation
-GLESRenderEngine::FlushTracer::FlushTracer(GLESRenderEngine* engine) : mEngine(engine) {
-    mThread = std::thread(&GLESRenderEngine::FlushTracer::loop, this);
-}
-
-GLESRenderEngine::FlushTracer::~FlushTracer() {
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mRunning = false;
-    }
-    mCondition.notify_all();
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-}
-
-void GLESRenderEngine::FlushTracer::queueSync(EGLSyncKHR sync) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    char name[64];
-    const uint64_t frameNum = mFramesQueued++;
-    snprintf(name, sizeof(name), "Queueing sync for frame: %lu",
-             static_cast<unsigned long>(frameNum));
-    ATRACE_NAME(name);
-    mQueue.push({sync, frameNum});
-    ATRACE_INT("GPU Frames Outstanding", mQueue.size());
-    mCondition.notify_one();
-}
-
-void GLESRenderEngine::FlushTracer::loop() {
-    while (mRunning) {
-        QueueEntry entry;
-        {
-            std::lock_guard<std::mutex> lock(mMutex);
-
-            mCondition.wait(mMutex,
-                            [&]() REQUIRES(mMutex) { return !mQueue.empty() || !mRunning; });
-
-            if (!mRunning) {
-                // if mRunning is false, then FlushTracer is being destroyed, so
-                // bail out now.
-                break;
-            }
-            entry = mQueue.front();
-            mQueue.pop();
-        }
-        {
-            char name[64];
-            snprintf(name, sizeof(name), "waiting for frame %lu",
-                     static_cast<unsigned long>(entry.mFrameNum));
-            ATRACE_NAME(name);
-            mEngine->waitSync(entry.mSync, 0);
-        }
-    }
-}
-
-void GLESRenderEngine::handleShadow(const FloatRect& casterRect, float casterCornerRadius,
-                                    const ShadowSettings& settings) {
-    ATRACE_CALL();
-    const float casterZ = settings.length / 2.0f;
-    const GLShadowVertexGenerator shadows(casterRect, casterCornerRadius, casterZ,
-                                          settings.casterIsTranslucent, settings.ambientColor,
-                                          settings.spotColor, settings.lightPos,
-                                          settings.lightRadius);
-
-    // setup mesh for both shadows
-    Mesh mesh = Mesh::Builder()
-                        .setPrimitive(Mesh::TRIANGLES)
-                        .setVertices(shadows.getVertexCount(), 2 /* size */)
-                        .setShadowAttrs()
-                        .setIndices(shadows.getIndexCount())
-                        .build();
-
-    Mesh::VertexArray<vec2> position = mesh.getPositionArray<vec2>();
-    Mesh::VertexArray<vec4> shadowColor = mesh.getShadowColorArray<vec4>();
-    Mesh::VertexArray<vec3> shadowParams = mesh.getShadowParamsArray<vec3>();
-    shadows.fillVertices(position, shadowColor, shadowParams);
-    shadows.fillIndices(mesh.getIndicesArray());
-
-    mState.cornerRadius = 0.0f;
-    mState.drawShadows = true;
-    setupLayerTexturing(mShadowTexture->getTexture());
-    drawMesh(mesh);
-    mState.drawShadows = false;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
deleted file mode 100644
index f5368d4..0000000
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_GLESRENDERENGINE_H_
-#define SF_GLESRENDERENGINE_H_
-
-#include <condition_variable>
-#include <deque>
-#include <mutex>
-#include <queue>
-#include <thread>
-#include <unordered_map>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <android-base/thread_annotations.h>
-#include <renderengine/RenderEngine.h>
-#include <renderengine/private/Description.h>
-#include <sys/types.h>
-#include <ui/FenceResult.h>
-#include "GLShadowTexture.h"
-#include "ImageManager.h"
-
-#define EGL_NO_CONFIG ((EGLConfig)0)
-
-namespace android {
-
-namespace renderengine {
-
-class Mesh;
-class Texture;
-
-namespace gl {
-
-class GLImage;
-class BlurFilter;
-
-class GLESRenderEngine : public RenderEngine {
-public:
-    static std::unique_ptr<GLESRenderEngine> create(const RenderEngineCreationArgs& args);
-
-    GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config,
-                     EGLContext ctxt, EGLSurface stub, EGLContext protectedContext,
-                     EGLSurface protectedStub);
-    ~GLESRenderEngine() override EXCLUDES(mRenderingMutex);
-
-    std::future<void> primeCache() override;
-    void genTextures(size_t count, uint32_t* names) override;
-    void deleteTextures(size_t count, uint32_t const* names) override;
-    bool isProtected() const { return mInProtectedContext; }
-    bool supportsProtectedContent() const override;
-    void useProtectedContext(bool useProtectedContext) override;
-    void cleanupPostRender() override;
-    int getContextPriority() override;
-    bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
-    void onActiveDisplaySizeChanged(ui::Size size) override {}
-
-    EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
-    // Creates an output image for rendering to
-    EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                                               bool useFramebufferCache)
-            EXCLUDES(mFramebufferImageCacheMutex);
-
-    // Test-only methods
-    // Returns true iff mImageCache contains an image keyed by bufferId
-    bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
-    // Returns true iff texName was previously generated by RenderEngine and was
-    // not destroyed.
-    bool isTextureNameKnownForTesting(uint32_t texName);
-    // Returns the buffer ID of the content bound to texName, or nullopt if no
-    // such mapping exists.
-    std::optional<uint64_t> getBufferIdForTextureNameForTesting(uint32_t texName);
-    // Returns true iff mFramebufferImageCache contains an image keyed by bufferId
-    bool isFramebufferImageCachedForTesting(uint64_t bufferId)
-            EXCLUDES(mFramebufferImageCacheMutex);
-    // These are wrappers around public methods above, but exposing Barrier
-    // objects so that tests can block.
-    std::shared_ptr<ImageManager::Barrier> cacheExternalTextureBufferForTesting(
-            const sp<GraphicBuffer>& buffer);
-    std::shared_ptr<ImageManager::Barrier> unbindExternalTextureBufferForTesting(uint64_t bufferId);
-
-protected:
-    Framebuffer* getFramebufferForDrawing();
-    void dump(std::string& result) override EXCLUDES(mRenderingMutex)
-            EXCLUDES(mFramebufferImageCacheMutex);
-    size_t getMaxTextureSize() const override;
-    size_t getMaxViewportDims() const override;
-    void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable)
-            EXCLUDES(mRenderingMutex);
-    void unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) EXCLUDES(mRenderingMutex);
-    bool canSkipPostRenderCleanup() const override;
-    void drawLayersInternal(const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
-                            const DisplaySettings& display,
-                            const std::vector<LayerSettings>& layers,
-                            const std::shared_ptr<ExternalTexture>& buffer,
-                            const bool useFramebufferCache, base::unique_fd&& bufferFence) override;
-
-private:
-    friend class BindNativeBufferAsFramebuffer;
-
-    enum GlesVersion {
-        GLES_VERSION_1_0 = 0x10000,
-        GLES_VERSION_1_1 = 0x10001,
-        GLES_VERSION_2_0 = 0x20000,
-        GLES_VERSION_3_0 = 0x30000,
-    };
-
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
-    static GlesVersion parseGlesVersion(const char* str);
-    static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
-                                       EGLContext shareContext,
-                                       std::optional<ContextPriority> contextPriority,
-                                       Protection protection);
-    static std::optional<RenderEngine::ContextPriority> createContextPriority(
-            const RenderEngineCreationArgs& args);
-    static EGLSurface createStubEglPbufferSurface(EGLDisplay display, EGLConfig config,
-                                                  int hwcFormat, Protection protection);
-    std::unique_ptr<Framebuffer> createFramebuffer();
-    std::unique_ptr<Image> createImage();
-    void checkErrors() const;
-    void checkErrors(const char* tag) const;
-    void setScissor(const Rect& region);
-    void disableScissor();
-    bool waitSync(EGLSyncKHR sync, EGLint flags);
-    status_t cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer)
-            EXCLUDES(mRenderingMutex);
-    void unbindExternalTextureBufferInternal(uint64_t bufferId) EXCLUDES(mRenderingMutex);
-    status_t bindFrameBuffer(Framebuffer* framebuffer);
-    void unbindFrameBuffer(Framebuffer* framebuffer);
-    void bindExternalTextureImage(uint32_t texName, const Image& image);
-    void bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer,
-                                   const sp<Fence>& fence) EXCLUDES(mRenderingMutex);
-    void cleanFramebufferCache() EXCLUDES(mFramebufferImageCacheMutex) override;
-
-    // A data space is considered HDR data space if it has BT2020 color space
-    // with PQ or HLG transfer function.
-    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
-    bool needsXYZTransformMatrix() const;
-    // Defines the viewport, and sets the projection matrix to the projection
-    // defined by the clip.
-    void setViewportAndProjection(Rect viewport, Rect clip);
-    // Evicts stale images from the buffer cache.
-    void evictImages(const std::vector<LayerSettings>& layers);
-    // Computes the cropping window for the layer and sets up cropping
-    // coordinates for the mesh.
-    FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh);
-
-    // We do a special handling for rounded corners when it's possible to turn off blending
-    // for the majority of the layer. The rounded corners needs to turn on blending such that
-    // we can set the alpha value correctly, however, only the corners need this, and since
-    // blending is an expensive operation, we want to turn off blending when it's not necessary.
-    void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer,
-                              const Mesh& mesh);
-    base::unique_fd flush();
-    bool finish();
-    bool waitFence(base::unique_fd fenceFd);
-    void clearWithColor(float red, float green, float blue, float alpha);
-    void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha);
-    void handleShadow(const FloatRect& casterRect, float casterCornerRadius,
-                      const ShadowSettings& shadowSettings);
-    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                            const half4& color, float cornerRadius);
-    void setupLayerTexturing(const Texture& texture);
-    void setupFillWithColor(float r, float g, float b, float a);
-    void setColorTransform(const mat4& colorTransform);
-    void setDisplayColorTransform(const mat4& colorTransform);
-    void disableTexturing();
-    void disableBlending();
-    void setupCornerRadiusCropSize(float width, float height);
-
-    // HDR and color management related functions and state
-    void setSourceDataSpace(ui::Dataspace source);
-    void setOutputDataSpace(ui::Dataspace dataspace);
-    void setDisplayMaxLuminance(const float maxLuminance);
-
-    // drawing
-    void drawMesh(const Mesh& mesh);
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-    EGLContext mEGLContext;
-    EGLSurface mStubSurface;
-    EGLContext mProtectedEGLContext;
-    EGLSurface mProtectedStubSurface;
-    GLint mMaxViewportDims[2];
-    GLint mMaxTextureSize;
-    GLuint mVpWidth;
-    GLuint mVpHeight;
-    Description mState;
-    std::unique_ptr<GLShadowTexture> mShadowTexture = nullptr;
-
-    mat4 mSrgbToXyz;
-    mat4 mDisplayP3ToXyz;
-    mat4 mBt2020ToXyz;
-    mat4 mXyzToSrgb;
-    mat4 mXyzToDisplayP3;
-    mat4 mXyzToBt2020;
-    mat4 mSrgbToDisplayP3;
-    mat4 mSrgbToBt2020;
-    mat4 mDisplayP3ToSrgb;
-    mat4 mDisplayP3ToBt2020;
-    mat4 mBt2020ToSrgb;
-    mat4 mBt2020ToDisplayP3;
-
-    bool mInProtectedContext = false;
-    // If set to true, then enables tracing flush() and finish() to systrace.
-    bool mTraceGpuCompletion = false;
-    // Maximum size of mFramebufferImageCache. If more images would be cached, then (approximately)
-    // the last recently used buffer should be kicked out.
-    uint32_t mFramebufferImageCacheSize = 0;
-
-    // Cache of output images, keyed by corresponding GraphicBuffer ID.
-    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache
-            GUARDED_BY(mFramebufferImageCacheMutex);
-    // The only reason why we have this mutex is so that we don't segfault when
-    // dumping info.
-    std::mutex mFramebufferImageCacheMutex;
-
-    // Current dataspace of layer being rendered
-    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
-
-    // Current output dataspace of the render engine
-    ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
-
-    // Whether only shaders performing tone mapping from HDR to SDR will be generated on
-    // primeCache().
-    const bool mPrecacheToneMapperShaderOnly = false;
-
-    // Cache of GL images that we'll store per GraphicBuffer ID
-    std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex);
-    std::unordered_map<uint32_t, std::optional<uint64_t>> mTextureView;
-
-    // Mutex guarding rendering operations, so that:
-    // 1. GL operations aren't interleaved, and
-    // 2. Internal state related to rendering that is potentially modified by
-    // multiple threads is guaranteed thread-safe.
-    std::mutex mRenderingMutex;
-
-    std::unique_ptr<Framebuffer> mDrawingBuffer;
-    // this is a 1x1 RGB buffer, but over-allocate in case a driver wants more
-    // memory or if it needs to satisfy alignment requirements. In this case:
-    // assume that each channel requires 4 bytes, and add 3 additional bytes to
-    // ensure that we align on a word. Allocating 16 bytes will provide a
-    // guarantee that we don't clobber memory.
-    uint32_t mPlaceholderDrawBuffer[4];
-    // Placeholder buffer and image, similar to mPlaceholderDrawBuffer, but
-    // instead these are intended for cleaning up texture memory with the
-    // GL_TEXTURE_EXTERNAL_OES target.
-    ANativeWindowBuffer* mPlaceholderBuffer = nullptr;
-    EGLImage mPlaceholderImage = EGL_NO_IMAGE_KHR;
-    sp<Fence> mLastDrawFence;
-    // Store a separate boolean checking if prior resources were cleaned up, as
-    // devices that don't support native sync fences can't rely on a last draw
-    // fence that doesn't exist.
-    bool mPriorResourcesCleaned = true;
-
-    // Blur effect processor, only instantiated when a layer requests it.
-    BlurFilter* mBlurFilter = nullptr;
-
-    class FlushTracer {
-    public:
-        FlushTracer(GLESRenderEngine* engine);
-        ~FlushTracer();
-        void queueSync(EGLSyncKHR sync) EXCLUDES(mMutex);
-
-        struct QueueEntry {
-            EGLSyncKHR mSync = nullptr;
-            uint64_t mFrameNum = 0;
-        };
-
-    private:
-        void loop();
-        GLESRenderEngine* const mEngine;
-        std::thread mThread;
-        std::condition_variable_any mCondition;
-        std::mutex mMutex;
-        std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
-        uint64_t mFramesQueued GUARDED_BY(mMutex) = 0;
-        bool mRunning = true;
-    };
-    friend class FlushTracer;
-    friend class ImageManager;
-    friend class GLFramebuffer;
-    friend class BlurFilter;
-    friend class GenericProgram;
-    std::unique_ptr<FlushTracer> mFlushTracer;
-    std::unique_ptr<ImageManager> mImageManager;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
-
-#endif /* SF_GLESRENDERENGINE_H_ */
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
deleted file mode 100644
index 58d6caa..0000000
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "GLFramebuffer.h"
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2ext.h>
-#include <GLES3/gl3.h>
-#include <gui/DebugEGLImageTracker.h>
-#include <nativebase/nativebase.h>
-#include <utils/Trace.h>
-#include "GLESRenderEngine.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine)
-      : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
-    glGenTextures(1, &mTextureName);
-    glGenFramebuffers(1, &mFramebufferName);
-}
-
-GLFramebuffer::~GLFramebuffer() {
-    setNativeWindowBuffer(nullptr, false, false);
-    glDeleteFramebuffers(1, &mFramebufferName);
-    glDeleteTextures(1, &mTextureName);
-}
-
-bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                                          const bool useFramebufferCache) {
-    ATRACE_CALL();
-    if (mEGLImage != EGL_NO_IMAGE_KHR) {
-        if (!usingFramebufferCache) {
-            eglDestroyImageKHR(mEGLDisplay, mEGLImage);
-            DEBUG_EGL_IMAGE_TRACKER_DESTROY();
-        }
-        mEGLImage = EGL_NO_IMAGE_KHR;
-        mBufferWidth = 0;
-        mBufferHeight = 0;
-    }
-
-    if (nativeBuffer) {
-        mEGLImage = mEngine.createFramebufferImageIfNeeded(nativeBuffer, isProtected,
-                                                           useFramebufferCache);
-        if (mEGLImage == EGL_NO_IMAGE_KHR) {
-            return false;
-        }
-        usingFramebufferCache = useFramebufferCache;
-        mBufferWidth = nativeBuffer->width;
-        mBufferHeight = nativeBuffer->height;
-    }
-    return true;
-}
-
-void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height, void* data) {
-    ATRACE_CALL();
-
-    glBindTexture(GL_TEXTURE_2D, mTextureName);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
-
-    mBufferHeight = height;
-    mBufferWidth = width;
-    mEngine.checkErrors("Allocating Fbo texture");
-
-    bind();
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureName, 0);
-    mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    unbind();
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    if (mStatus != GL_FRAMEBUFFER_COMPLETE) {
-        ALOGE("Frame buffer is not complete. Error %d", mStatus);
-    }
-}
-
-void GLFramebuffer::bind() const {
-    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
-}
-
-void GLFramebuffer::bindAsReadBuffer() const {
-    glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferName);
-}
-
-void GLFramebuffer::bindAsDrawBuffer() const {
-    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferName);
-}
-
-void GLFramebuffer::unbind() const {
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
deleted file mode 100644
index 6757695..0000000
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <renderengine/Framebuffer.h>
-
-struct ANativeWindowBuffer;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLESRenderEngine;
-
-class GLFramebuffer : public renderengine::Framebuffer {
-public:
-    explicit GLFramebuffer(GLESRenderEngine& engine);
-    explicit GLFramebuffer(GLESRenderEngine& engine, bool multiTarget);
-    ~GLFramebuffer() override;
-
-    bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                               const bool useFramebufferCache) override;
-    void allocateBuffers(uint32_t width, uint32_t height, void* data = nullptr);
-    EGLImageKHR getEGLImage() const { return mEGLImage; }
-    uint32_t getTextureName() const { return mTextureName; }
-    uint32_t getFramebufferName() const { return mFramebufferName; }
-    int32_t getBufferHeight() const { return mBufferHeight; }
-    int32_t getBufferWidth() const { return mBufferWidth; }
-    GLenum getStatus() const { return mStatus; }
-    void bind() const;
-    void bindAsReadBuffer() const;
-    void bindAsDrawBuffer() const;
-    void unbind() const;
-
-private:
-    GLESRenderEngine& mEngine;
-    EGLDisplay mEGLDisplay;
-    EGLImageKHR mEGLImage;
-    bool usingFramebufferCache = false;
-    GLenum mStatus = GL_FRAMEBUFFER_UNSUPPORTED;
-    uint32_t mTextureName, mFramebufferName;
-
-    int32_t mBufferHeight = 0;
-    int32_t mBufferWidth = 0;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
deleted file mode 100644
index 8497721..0000000
--- a/libs/renderengine/gl/GLImage.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "GLImage.h"
-
-#include <vector>
-
-#include <gui/DebugEGLImageTracker.h>
-#include <log/log.h>
-#include <utils/Trace.h>
-#include "GLESRenderEngine.h"
-#include "GLExtensions.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-static std::vector<EGLint> buildAttributeList(bool isProtected) {
-    std::vector<EGLint> attrs;
-    attrs.reserve(16);
-
-    attrs.push_back(EGL_IMAGE_PRESERVED_KHR);
-    attrs.push_back(EGL_TRUE);
-
-    if (isProtected && GLExtensions::getInstance().hasProtectedContent()) {
-        attrs.push_back(EGL_PROTECTED_CONTENT_EXT);
-        attrs.push_back(EGL_TRUE);
-    }
-
-    attrs.push_back(EGL_NONE);
-
-    return attrs;
-}
-
-GLImage::GLImage(const GLESRenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
-
-GLImage::~GLImage() {
-    setNativeWindowBuffer(nullptr, false);
-}
-
-bool GLImage::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) {
-    ATRACE_CALL();
-    if (mEGLImage != EGL_NO_IMAGE_KHR) {
-        if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
-            ALOGE("failed to destroy image: %#x", eglGetError());
-        }
-        DEBUG_EGL_IMAGE_TRACKER_DESTROY();
-        mEGLImage = EGL_NO_IMAGE_KHR;
-    }
-
-    if (buffer) {
-        std::vector<EGLint> attrs = buildAttributeList(isProtected);
-        mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                      static_cast<EGLClientBuffer>(buffer), attrs.data());
-        if (mEGLImage == EGL_NO_IMAGE_KHR) {
-            ALOGE("failed to create EGLImage: %#x", eglGetError());
-            return false;
-        }
-        DEBUG_EGL_IMAGE_TRACKER_CREATE();
-        mProtected = isProtected;
-    }
-
-    return true;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLImage.h b/libs/renderengine/gl/GLImage.h
deleted file mode 100644
index 59d6ce3..0000000
--- a/libs/renderengine/gl/GLImage.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <android-base/macros.h>
-#include <renderengine/Image.h>
-
-struct ANativeWindowBuffer;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLESRenderEngine;
-
-class GLImage : public renderengine::Image {
-public:
-    explicit GLImage(const GLESRenderEngine& engine);
-    ~GLImage() override;
-
-    bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
-
-    EGLImageKHR getEGLImage() const { return mEGLImage; }
-    bool isProtected() const { return mProtected; }
-
-private:
-    EGLDisplay mEGLDisplay;
-    EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
-    bool mProtected = false;
-
-    DISALLOW_COPY_AND_ASSIGN(GLImage);
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLShadowTexture.cpp b/libs/renderengine/gl/GLShadowTexture.cpp
deleted file mode 100644
index 2423a34..0000000
--- a/libs/renderengine/gl/GLShadowTexture.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES3/gl3.h>
-
-#include "GLShadowTexture.h"
-#include "GLSkiaShadowPort.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLShadowTexture::GLShadowTexture() {
-    fillShadowTextureData(mTextureData, SHADOW_TEXTURE_WIDTH);
-
-    glGenTextures(1, &mName);
-    glBindTexture(GL_TEXTURE_2D, mName);
-    glTexImage2D(GL_TEXTURE_2D, 0 /* base image level */, GL_ALPHA, SHADOW_TEXTURE_WIDTH,
-                 SHADOW_TEXTURE_HEIGHT, 0 /* border */, GL_ALPHA, GL_UNSIGNED_BYTE, mTextureData);
-    mTexture.init(Texture::TEXTURE_2D, mName);
-    mTexture.setFiltering(true);
-    mTexture.setDimensions(SHADOW_TEXTURE_WIDTH, 1);
-}
-
-GLShadowTexture::~GLShadowTexture() {
-    glDeleteTextures(1, &mName);
-}
-
-const Texture& GLShadowTexture::getTexture() {
-    return mTexture;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLShadowTexture.h b/libs/renderengine/gl/GLShadowTexture.h
deleted file mode 100644
index 250a9d7..0000000
--- a/libs/renderengine/gl/GLShadowTexture.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 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
-
-#include <renderengine/Texture.h>
-#include <cstdint>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLShadowTexture {
-public:
-    GLShadowTexture();
-    ~GLShadowTexture();
-
-    const Texture& getTexture();
-
-private:
-    static constexpr int SHADOW_TEXTURE_WIDTH = 128;
-    static constexpr int SHADOW_TEXTURE_HEIGHT = 1;
-
-    GLuint mName;
-    Texture mTexture;
-    uint8_t mTextureData[SHADOW_TEXTURE_WIDTH];
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLShadowVertexGenerator.cpp b/libs/renderengine/gl/GLShadowVertexGenerator.cpp
deleted file mode 100644
index 3181f9b..0000000
--- a/libs/renderengine/gl/GLShadowVertexGenerator.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include <renderengine/Mesh.h>
-
-#include <math/vec4.h>
-
-#include <ui/Rect.h>
-#include <ui/Transform.h>
-
-#include "GLShadowVertexGenerator.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLShadowVertexGenerator::GLShadowVertexGenerator(const FloatRect& casterRect,
-                                                 float casterCornerRadius, float casterZ,
-                                                 bool casterIsTranslucent, const vec4& ambientColor,
-                                                 const vec4& spotColor, const vec3& lightPosition,
-                                                 float lightRadius) {
-    mDrawAmbientShadow = ambientColor.a > 0.f;
-    mDrawSpotShadow = spotColor.a > 0.f;
-
-    // Generate geometries and find number of vertices to generate
-    if (mDrawAmbientShadow) {
-        mAmbientShadowGeometry = getAmbientShadowGeometry(casterRect, casterCornerRadius, casterZ,
-                                                          casterIsTranslucent, ambientColor);
-        mAmbientShadowVertexCount = getVertexCountForGeometry(*mAmbientShadowGeometry.get());
-        mAmbientShadowIndexCount = getIndexCountForGeometry(*mAmbientShadowGeometry.get());
-    } else {
-        mAmbientShadowVertexCount = 0;
-        mAmbientShadowIndexCount = 0;
-    }
-
-    if (mDrawSpotShadow) {
-        mSpotShadowGeometry =
-                getSpotShadowGeometry(casterRect, casterCornerRadius, casterZ, casterIsTranslucent,
-                                      spotColor, lightPosition, lightRadius);
-        mSpotShadowVertexCount = getVertexCountForGeometry(*mSpotShadowGeometry.get());
-        mSpotShadowIndexCount = getIndexCountForGeometry(*mSpotShadowGeometry.get());
-    } else {
-        mSpotShadowVertexCount = 0;
-        mSpotShadowIndexCount = 0;
-    }
-}
-
-size_t GLShadowVertexGenerator::getVertexCount() const {
-    return mAmbientShadowVertexCount + mSpotShadowVertexCount;
-}
-
-size_t GLShadowVertexGenerator::getIndexCount() const {
-    return mAmbientShadowIndexCount + mSpotShadowIndexCount;
-}
-
-void GLShadowVertexGenerator::fillVertices(Mesh::VertexArray<vec2>& position,
-                                           Mesh::VertexArray<vec4>& color,
-                                           Mesh::VertexArray<vec3>& params) const {
-    if (mDrawAmbientShadow) {
-        fillVerticesForGeometry(*mAmbientShadowGeometry.get(), mAmbientShadowVertexCount, position,
-                                color, params);
-    }
-    if (mDrawSpotShadow) {
-        fillVerticesForGeometry(*mSpotShadowGeometry.get(), mSpotShadowVertexCount,
-                                Mesh::VertexArray<vec2>(position, mAmbientShadowVertexCount),
-                                Mesh::VertexArray<vec4>(color, mAmbientShadowVertexCount),
-                                Mesh::VertexArray<vec3>(params, mAmbientShadowVertexCount));
-    }
-}
-
-void GLShadowVertexGenerator::fillIndices(uint16_t* indices) const {
-    if (mDrawAmbientShadow) {
-        fillIndicesForGeometry(*mAmbientShadowGeometry.get(), mAmbientShadowIndexCount,
-                               0 /* starting vertex offset */, indices);
-    }
-    if (mDrawSpotShadow) {
-        fillIndicesForGeometry(*mSpotShadowGeometry.get(), mSpotShadowIndexCount,
-                               mAmbientShadowVertexCount /* starting vertex offset */,
-                               &(indices[mAmbientShadowIndexCount]));
-    }
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLShadowVertexGenerator.h b/libs/renderengine/gl/GLShadowVertexGenerator.h
deleted file mode 100644
index 112f976..0000000
--- a/libs/renderengine/gl/GLShadowVertexGenerator.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2019 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
-
-#include <math/vec4.h>
-#include <ui/Rect.h>
-
-#include "GLSkiaShadowPort.h"
-
-namespace android {
-namespace renderengine {
-
-class Mesh;
-
-namespace gl {
-
-/**
- * Generates gl attributes required to draw shadow spot and/or ambient shadows.
- *
- * Each shadow can support different colors. This class generates three vertex attributes for
- * each shadow, its position, color and shadow params(offset and distance). These can be sent
- * using a single glDrawElements call.
- */
-class GLShadowVertexGenerator {
-public:
-    GLShadowVertexGenerator(const FloatRect& casterRect, float casterCornerRadius, float casterZ,
-                            bool casterIsTranslucent, const vec4& ambientColor,
-                            const vec4& spotColor, const vec3& lightPosition, float lightRadius);
-    ~GLShadowVertexGenerator() = default;
-
-    size_t getVertexCount() const;
-    size_t getIndexCount() const;
-    void fillVertices(Mesh::VertexArray<vec2>& position, Mesh::VertexArray<vec4>& color,
-                      Mesh::VertexArray<vec3>& params) const;
-    void fillIndices(uint16_t* indices) const;
-
-private:
-    bool mDrawAmbientShadow;
-    std::unique_ptr<Geometry> mAmbientShadowGeometry;
-    int mAmbientShadowVertexCount = 0;
-    int mAmbientShadowIndexCount = 0;
-
-    bool mDrawSpotShadow;
-    std::unique_ptr<Geometry> mSpotShadowGeometry;
-    int mSpotShadowVertexCount = 0;
-    int mSpotShadowIndexCount = 0;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLSkiaShadowPort.cpp b/libs/renderengine/gl/GLSkiaShadowPort.cpp
deleted file mode 100644
index da8b435..0000000
--- a/libs/renderengine/gl/GLSkiaShadowPort.cpp
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include <math/vec4.h>
-
-#include <renderengine/Mesh.h>
-
-#include <ui/Rect.h>
-#include <ui/Transform.h>
-
-#include <utils/Log.h>
-
-#include "GLSkiaShadowPort.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-/**
- * The shadow geometry logic and vertex generation code has been ported from skia shadow
- * fast path OpenGL implementation to draw shadows around rects and rounded rects including
- * circles.
- *
- * path: skia/src/gpu/GrRenderTargetContext.cpp GrRenderTargetContext::drawFastShadow
- *
- * Modifications made:
- * - Switched to using std lib math functions
- * - Fall off function is implemented in vertex shader rather than a shadow texture
- * - Removed transformations applied on the caster rect since the caster will be in local
- *   coordinate space and will be transformed by the vertex shader.
- */
-
-static inline float divide_and_pin(float numer, float denom, float min, float max) {
-    if (denom == 0.0f) return min;
-    return std::clamp(numer / denom, min, max);
-}
-
-static constexpr auto SK_ScalarSqrt2 = 1.41421356f;
-static constexpr auto kAmbientHeightFactor = 1.0f / 128.0f;
-static constexpr auto kAmbientGeomFactor = 64.0f;
-// Assuming that we have a light height of 600 for the spot shadow,
-// the spot values will reach their maximum at a height of approximately 292.3077.
-// We'll round up to 300 to keep it simple.
-static constexpr auto kMaxAmbientRadius = 300 * kAmbientHeightFactor * kAmbientGeomFactor;
-
-inline float AmbientBlurRadius(float height) {
-    return std::min(height * kAmbientHeightFactor * kAmbientGeomFactor, kMaxAmbientRadius);
-}
-inline float AmbientRecipAlpha(float height) {
-    return 1.0f + std::max(height * kAmbientHeightFactor, 0.0f);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Circle Data
-//
-// We have two possible cases for geometry for a circle:
-
-// In the case of a normal fill, we draw geometry for the circle as an octagon.
-static const uint16_t gFillCircleIndices[] = {
-        // enter the octagon
-        // clang-format off
-         0, 1, 8, 1, 2, 8,
-         2, 3, 8, 3, 4, 8,
-         4, 5, 8, 5, 6, 8,
-         6, 7, 8, 7, 0, 8,
-        // clang-format on
-};
-
-// For stroked circles, we use two nested octagons.
-static const uint16_t gStrokeCircleIndices[] = {
-        // enter the octagon
-        // clang-format off
-         0, 1,  9, 0,  9,  8,
-         1, 2, 10, 1, 10,  9,
-         2, 3, 11, 2, 11, 10,
-         3, 4, 12, 3, 12, 11,
-         4, 5, 13, 4, 13, 12,
-         5, 6, 14, 5, 14, 13,
-         6, 7, 15, 6, 15, 14,
-         7, 0,  8, 7,  8, 15,
-        // clang-format on
-};
-
-#define SK_ARRAY_COUNT(a) (sizeof(a) / sizeof((a)[0]))
-static const int kIndicesPerFillCircle = SK_ARRAY_COUNT(gFillCircleIndices);
-static const int kIndicesPerStrokeCircle = SK_ARRAY_COUNT(gStrokeCircleIndices);
-static const int kVertsPerStrokeCircle = 16;
-static const int kVertsPerFillCircle = 9;
-
-static int circle_type_to_vert_count(bool stroked) {
-    return stroked ? kVertsPerStrokeCircle : kVertsPerFillCircle;
-}
-
-static int circle_type_to_index_count(bool stroked) {
-    return stroked ? kIndicesPerStrokeCircle : kIndicesPerFillCircle;
-}
-
-static const uint16_t* circle_type_to_indices(bool stroked) {
-    return stroked ? gStrokeCircleIndices : gFillCircleIndices;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// RoundRect Data
-//
-// The geometry for a shadow roundrect is similar to a 9-patch:
-//    ____________
-//   |_|________|_|
-//   | |        | |
-//   | |        | |
-//   | |        | |
-//   |_|________|_|
-//   |_|________|_|
-//
-// However, each corner is rendered as a fan rather than a simple quad, as below. (The diagram
-// shows the upper part of the upper left corner. The bottom triangle would similarly be split
-// into two triangles.)
-//    ________
-//   |\  \   |
-//   |  \ \  |
-//   |    \\ |
-//   |      \|
-//   --------
-//
-// The center of the fan handles the curve of the corner. For roundrects where the stroke width
-// is greater than the corner radius, the outer triangles blend from the curve to the straight
-// sides. Otherwise these triangles will be degenerate.
-//
-// In the case where the stroke width is greater than the corner radius and the
-// blur radius (overstroke), we add additional geometry to mark out the rectangle in the center.
-// This rectangle extends the coverage values of the center edges of the 9-patch.
-//    ____________
-//   |_|________|_|
-//   | |\ ____ /| |
-//   | | |    | | |
-//   | | |____| | |
-//   |_|/______\|_|
-//   |_|________|_|
-//
-// For filled rrects we reuse the stroke geometry but add an additional quad to the center.
-
-static const uint16_t gRRectIndices[] = {
-        // clang-format off
-     // overstroke quads
-     // we place this at the beginning so that we can skip these indices when rendering as filled
-     0, 6, 25, 0, 25, 24,
-     6, 18, 27, 6, 27, 25,
-     18, 12, 26, 18, 26, 27,
-     12, 0, 24, 12, 24, 26,
-
-     // corners
-     0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5,
-     6, 11, 10, 6, 10, 9, 6, 9, 8, 6, 8, 7,
-     12, 17, 16, 12, 16, 15, 12, 15, 14, 12, 14, 13,
-     18, 19, 20, 18, 20, 21, 18, 21, 22, 18, 22, 23,
-
-     // edges
-     0, 5, 11, 0, 11, 6,
-     6, 7, 19, 6, 19, 18,
-     18, 23, 17, 18, 17, 12,
-     12, 13, 1, 12, 1, 0,
-
-     // fill quad
-     // we place this at the end so that we can skip these indices when rendering as stroked
-     0, 6, 18, 0, 18, 12,
-        // clang-format on
-};
-
-// overstroke count
-static const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6;
-// simple stroke count skips overstroke indices
-static const int kIndicesPerStrokeRRect = kIndicesPerOverstrokeRRect - 6 * 4;
-// fill count adds final quad to stroke count
-static const int kIndicesPerFillRRect = kIndicesPerStrokeRRect + 6;
-static const int kVertsPerStrokeRRect = 24;
-static const int kVertsPerOverstrokeRRect = 28;
-static const int kVertsPerFillRRect = 24;
-
-static int rrect_type_to_vert_count(RRectType type) {
-    switch (type) {
-        case kFill_RRectType:
-            return kVertsPerFillRRect;
-        case kStroke_RRectType:
-            return kVertsPerStrokeRRect;
-        case kOverstroke_RRectType:
-            return kVertsPerOverstrokeRRect;
-    }
-    ALOGE("Invalid rect type: %d", type);
-    return -1;
-}
-
-static int rrect_type_to_index_count(RRectType type) {
-    switch (type) {
-        case kFill_RRectType:
-            return kIndicesPerFillRRect;
-        case kStroke_RRectType:
-            return kIndicesPerStrokeRRect;
-        case kOverstroke_RRectType:
-            return kIndicesPerOverstrokeRRect;
-    }
-    ALOGE("Invalid rect type: %d", type);
-    return -1;
-}
-
-static const uint16_t* rrect_type_to_indices(RRectType type) {
-    switch (type) {
-        case kFill_RRectType:
-        case kStroke_RRectType:
-            return gRRectIndices + 6 * 4;
-        case kOverstroke_RRectType:
-            return gRRectIndices;
-    }
-    ALOGE("Invalid rect type: %d", type);
-    return nullptr;
-}
-
-static void fillInCircleVerts(const Geometry& args, bool isStroked,
-                              Mesh::VertexArray<vec2>& position,
-                              Mesh::VertexArray<vec4>& shadowColor,
-                              Mesh::VertexArray<vec3>& shadowParams) {
-    vec4 color = args.fColor;
-    float outerRadius = args.fOuterRadius;
-    float innerRadius = args.fInnerRadius;
-    float blurRadius = args.fBlurRadius;
-    float distanceCorrection = outerRadius / blurRadius;
-
-    const FloatRect& bounds = args.fDevBounds;
-
-    // The inner radius in the vertex data must be specified in normalized space.
-    innerRadius = innerRadius / outerRadius;
-
-    vec2 center = vec2(bounds.getWidth() / 2.0f, bounds.getHeight() / 2.0f);
-    float halfWidth = 0.5f * bounds.getWidth();
-    float octOffset = 0.41421356237f; // sqrt(2) - 1
-    int vertexCount = 0;
-
-    position[vertexCount] = center + vec2(-octOffset * halfWidth, -halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(-octOffset, -1, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(octOffset * halfWidth, -halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(octOffset, -1, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(halfWidth, -octOffset * halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(1, -octOffset, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(halfWidth, octOffset * halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(1, octOffset, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(octOffset * halfWidth, halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(octOffset, 1, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(-octOffset * halfWidth, halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(-octOffset, 1, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(-halfWidth, octOffset * halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(-1, octOffset, distanceCorrection);
-    vertexCount++;
-
-    position[vertexCount] = center + vec2(-halfWidth, -octOffset * halfWidth);
-    shadowColor[vertexCount] = color;
-    shadowParams[vertexCount] = vec3(-1, -octOffset, distanceCorrection);
-    vertexCount++;
-
-    if (isStroked) {
-        // compute the inner ring
-
-        // cosine and sine of pi/8
-        float c = 0.923579533f;
-        float s = 0.382683432f;
-        float r = args.fInnerRadius;
-
-        position[vertexCount] = center + vec2(-s * r, -c * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(-s * innerRadius, -c * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(s * r, -c * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(s * innerRadius, -c * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(c * r, -s * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(c * innerRadius, -s * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(c * r, s * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(c * innerRadius, s * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(s * r, c * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(s * innerRadius, c * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(-s * r, c * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(-s * innerRadius, c * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(-c * r, s * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(-c * innerRadius, s * innerRadius, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = center + vec2(-c * r, -s * r);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(-c * innerRadius, -s * innerRadius, distanceCorrection);
-        vertexCount++;
-    } else {
-        // filled
-        position[vertexCount] = center;
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-    }
-}
-
-static void fillInRRectVerts(const Geometry& args, Mesh::VertexArray<vec2>& position,
-                             Mesh::VertexArray<vec4>& shadowColor,
-                             Mesh::VertexArray<vec3>& shadowParams) {
-    vec4 color = args.fColor;
-    float outerRadius = args.fOuterRadius;
-
-    const FloatRect& bounds = args.fDevBounds;
-
-    float umbraInset = args.fUmbraInset;
-    float minDim = 0.5f * std::min(bounds.getWidth(), bounds.getHeight());
-    if (umbraInset > minDim) {
-        umbraInset = minDim;
-    }
-
-    float xInner[4] = {bounds.left + umbraInset, bounds.right - umbraInset,
-                       bounds.left + umbraInset, bounds.right - umbraInset};
-    float xMid[4] = {bounds.left + outerRadius, bounds.right - outerRadius,
-                     bounds.left + outerRadius, bounds.right - outerRadius};
-    float xOuter[4] = {bounds.left, bounds.right, bounds.left, bounds.right};
-    float yInner[4] = {bounds.top + umbraInset, bounds.top + umbraInset, bounds.bottom - umbraInset,
-                       bounds.bottom - umbraInset};
-    float yMid[4] = {bounds.top + outerRadius, bounds.top + outerRadius,
-                     bounds.bottom - outerRadius, bounds.bottom - outerRadius};
-    float yOuter[4] = {bounds.top, bounds.top, bounds.bottom, bounds.bottom};
-
-    float blurRadius = args.fBlurRadius;
-
-    // In the case where we have to inset more for the umbra, our two triangles in the
-    // corner get skewed to a diamond rather than a square. To correct for that,
-    // we also skew the vectors we send to the shader that help define the circle.
-    // By doing so, we end up with a quarter circle in the corner rather than the
-    // elliptical curve.
-
-    // This is a bit magical, but it gives us the correct results at extrema:
-    //   a) umbraInset == outerRadius produces an orthogonal vector
-    //   b) outerRadius == 0 produces a diagonal vector
-    // And visually the corner looks correct.
-    vec2 outerVec = vec2(outerRadius - umbraInset, -outerRadius - umbraInset);
-    outerVec = normalize(outerVec);
-    // We want the circle edge to fall fractionally along the diagonal at
-    //      (sqrt(2)*(umbraInset - outerRadius) + outerRadius)/sqrt(2)*umbraInset
-    //
-    // Setting the components of the diagonal offset to the following value will give us that.
-    float diagVal = umbraInset / (SK_ScalarSqrt2 * (outerRadius - umbraInset) - outerRadius);
-    vec2 diagVec = vec2(diagVal, diagVal);
-    float distanceCorrection = umbraInset / blurRadius;
-
-    int vertexCount = 0;
-    // build corner by corner
-    for (int i = 0; i < 4; ++i) {
-        // inner point
-        position[vertexCount] = vec2(xInner[i], yInner[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-
-        // outer points
-        position[vertexCount] = vec2(xOuter[i], yInner[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, -1, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = vec2(xOuter[i], yMid[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(outerVec.x, outerVec.y, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = vec2(xOuter[i], yOuter[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(diagVec.x, diagVec.y, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = vec2(xMid[i], yOuter[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(outerVec.x, outerVec.y, distanceCorrection);
-        vertexCount++;
-
-        position[vertexCount] = vec2(xInner[i], yOuter[i]);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, -1, distanceCorrection);
-        vertexCount++;
-    }
-
-    // Add the additional vertices for overstroked rrects.
-    // Effectively this is an additional stroked rrect, with its
-    // parameters equal to those in the center of the 9-patch. This will
-    // give constant values across this inner ring.
-    if (kOverstroke_RRectType == args.fType) {
-        float inset = umbraInset + args.fInnerRadius;
-
-        // TL
-        position[vertexCount] = vec2(bounds.left + inset, bounds.top + inset);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-
-        // TR
-        position[vertexCount] = vec2(bounds.right - inset, bounds.top + inset);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-
-        // BL
-        position[vertexCount] = vec2(bounds.left + inset, bounds.bottom - inset);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-
-        // BR
-        position[vertexCount] = vec2(bounds.right - inset, bounds.bottom - inset);
-        shadowColor[vertexCount] = color;
-        shadowParams[vertexCount] = vec3(0, 0, distanceCorrection);
-        vertexCount++;
-    }
-}
-
-int getVertexCountForGeometry(const Geometry& shadowGeometry) {
-    if (shadowGeometry.fIsCircle) {
-        return circle_type_to_vert_count(shadowGeometry.fType);
-    }
-
-    return rrect_type_to_vert_count(shadowGeometry.fType);
-}
-
-int getIndexCountForGeometry(const Geometry& shadowGeometry) {
-    if (shadowGeometry.fIsCircle) {
-        return circle_type_to_index_count(kStroke_RRectType == shadowGeometry.fType);
-    }
-
-    return rrect_type_to_index_count(shadowGeometry.fType);
-}
-
-void fillVerticesForGeometry(const Geometry& shadowGeometry, int /* vertexCount */,
-                             Mesh::VertexArray<vec2> position, Mesh::VertexArray<vec4> shadowColor,
-                             Mesh::VertexArray<vec3> shadowParams) {
-    if (shadowGeometry.fIsCircle) {
-        fillInCircleVerts(shadowGeometry, shadowGeometry.fIsStroked, position, shadowColor,
-                          shadowParams);
-    } else {
-        fillInRRectVerts(shadowGeometry, position, shadowColor, shadowParams);
-    }
-}
-
-void fillIndicesForGeometry(const Geometry& shadowGeometry, int indexCount,
-                            int startingVertexOffset, uint16_t* indices) {
-    if (shadowGeometry.fIsCircle) {
-        const uint16_t* primIndices = circle_type_to_indices(shadowGeometry.fIsStroked);
-        for (int i = 0; i < indexCount; ++i) {
-            indices[i] = primIndices[i] + startingVertexOffset;
-        }
-    } else {
-        const uint16_t* primIndices = rrect_type_to_indices(shadowGeometry.fType);
-        for (int i = 0; i < indexCount; ++i) {
-            indices[i] = primIndices[i] + startingVertexOffset;
-        }
-    }
-}
-
-inline void GetSpotParams(float occluderZ, float lightX, float lightY, float lightZ,
-                          float lightRadius, float& blurRadius, float& scale, vec2& translate) {
-    float zRatio = divide_and_pin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);
-    blurRadius = lightRadius * zRatio;
-    scale = divide_and_pin(lightZ, lightZ - occluderZ, 1.0f, 1.95f);
-    translate.x = -zRatio * lightX;
-    translate.y = -zRatio * lightY;
-}
-
-static std::unique_ptr<Geometry> getShadowGeometry(const vec4& color, const FloatRect& devRect,
-                                                   float devRadius, float blurRadius,
-                                                   float insetWidth) {
-    // An insetWidth > 1/2 rect width or height indicates a simple fill.
-    const bool isCircle = ((devRadius >= devRect.getWidth()) && (devRadius >= devRect.getHeight()));
-
-    FloatRect bounds = devRect;
-    float innerRadius = 0.0f;
-    float outerRadius = devRadius;
-    float umbraInset;
-
-    RRectType type = kFill_RRectType;
-    if (isCircle) {
-        umbraInset = 0;
-    } else {
-        umbraInset = std::max(outerRadius, blurRadius);
-    }
-
-    // If stroke is greater than width or height, this is still a fill,
-    // otherwise we compute stroke params.
-    if (isCircle) {
-        innerRadius = devRadius - insetWidth;
-        type = innerRadius > 0 ? kStroke_RRectType : kFill_RRectType;
-    } else {
-        if (insetWidth <= 0.5f * std::min(devRect.getWidth(), devRect.getHeight())) {
-            // We don't worry about a real inner radius, we just need to know if we
-            // need to create overstroke vertices.
-            innerRadius = std::max(insetWidth - umbraInset, 0.0f);
-            type = innerRadius > 0 ? kOverstroke_RRectType : kStroke_RRectType;
-        }
-    }
-    const bool isStroked = (kStroke_RRectType == type);
-    return std::make_unique<Geometry>(Geometry{color, outerRadius, umbraInset, innerRadius,
-                                               blurRadius, bounds, type, isCircle, isStroked});
-}
-
-std::unique_ptr<Geometry> getAmbientShadowGeometry(const FloatRect& casterRect,
-                                                   float casterCornerRadius, float casterZ,
-                                                   bool casterIsTranslucent,
-                                                   const vec4& ambientColor) {
-    float devSpaceInsetWidth = AmbientBlurRadius(casterZ);
-    const float umbraRecipAlpha = AmbientRecipAlpha(casterZ);
-    const float devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
-
-    // Outset the shadow rrect to the border of the penumbra
-    float ambientPathOutset = devSpaceInsetWidth;
-    FloatRect outsetRect(casterRect);
-    outsetRect.left -= ambientPathOutset;
-    outsetRect.top -= ambientPathOutset;
-    outsetRect.right += ambientPathOutset;
-    outsetRect.bottom += ambientPathOutset;
-
-    float outsetRad = casterCornerRadius + ambientPathOutset;
-    if (casterIsTranslucent) {
-        // set a large inset to force a fill
-        devSpaceInsetWidth = outsetRect.getWidth();
-    }
-
-    return getShadowGeometry(ambientColor, outsetRect, std::abs(outsetRad), devSpaceAmbientBlur,
-                             std::abs(devSpaceInsetWidth));
-}
-
-std::unique_ptr<Geometry> getSpotShadowGeometry(const FloatRect& casterRect,
-                                                float casterCornerRadius, float casterZ,
-                                                bool casterIsTranslucent, const vec4& spotColor,
-                                                const vec3& lightPosition, float lightRadius) {
-    float devSpaceSpotBlur;
-    float spotScale;
-    vec2 spotOffset;
-    GetSpotParams(casterZ, lightPosition.x, lightPosition.y, lightPosition.z, lightRadius,
-                  devSpaceSpotBlur, spotScale, spotOffset);
-    // handle scale of radius due to CTM
-    const float srcSpaceSpotBlur = devSpaceSpotBlur;
-
-    // Adjust translate for the effect of the scale.
-    spotOffset.x += spotScale;
-    spotOffset.y += spotScale;
-
-    // Compute the transformed shadow rect
-    ui::Transform shadowTransform;
-    shadowTransform.set(spotOffset.x, spotOffset.y);
-    shadowTransform.set(spotScale, 0, 0, spotScale);
-    FloatRect spotShadowRect = shadowTransform.transform(casterRect);
-    float spotShadowRadius = casterCornerRadius * spotScale;
-
-    // Compute the insetWidth
-    float blurOutset = srcSpaceSpotBlur;
-    float insetWidth = blurOutset;
-    if (casterIsTranslucent) {
-        // If transparent, just do a fill
-        insetWidth += spotShadowRect.getWidth();
-    } else {
-        // For shadows, instead of using a stroke we specify an inset from the penumbra
-        // border. We want to extend this inset area so that it meets up with the caster
-        // geometry. The inset geometry will by default already be inset by the blur width.
-        //
-        // We compare the min and max corners inset by the radius between the original
-        // rrect and the shadow rrect. The distance between the two plus the difference
-        // between the scaled radius and the original radius gives the distance from the
-        // transformed shadow shape to the original shape in that corner. The max
-        // of these gives the maximum distance we need to cover.
-        //
-        // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
-        // that to get the full insetWidth.
-        float maxOffset;
-        if (casterCornerRadius <= 0.f) {
-            // Manhattan distance works better for rects
-            maxOffset = std::max(std::max(std::abs(spotShadowRect.left - casterRect.left),
-                                          std::abs(spotShadowRect.top - casterRect.top)),
-                                 std::max(std::abs(spotShadowRect.right - casterRect.right),
-                                          std::abs(spotShadowRect.bottom - casterRect.bottom)));
-        } else {
-            float dr = spotShadowRadius - casterCornerRadius;
-            vec2 upperLeftOffset = vec2(spotShadowRect.left - casterRect.left + dr,
-                                        spotShadowRect.top - casterRect.top + dr);
-            vec2 lowerRightOffset = vec2(spotShadowRect.right - casterRect.right - dr,
-                                         spotShadowRect.bottom - casterRect.bottom - dr);
-            maxOffset = sqrt(std::max(dot(upperLeftOffset, lowerRightOffset),
-                                      dot(lowerRightOffset, lowerRightOffset))) +
-                    dr;
-        }
-        insetWidth += std::max(blurOutset, maxOffset);
-    }
-
-    // Outset the shadow rrect to the border of the penumbra
-    spotShadowRadius += blurOutset;
-    spotShadowRect.left -= blurOutset;
-    spotShadowRect.top -= blurOutset;
-    spotShadowRect.right += blurOutset;
-    spotShadowRect.bottom += blurOutset;
-
-    return getShadowGeometry(spotColor, spotShadowRect, std::abs(spotShadowRadius),
-                             2.0f * devSpaceSpotBlur, std::abs(insetWidth));
-}
-
-void fillShadowTextureData(uint8_t* data, size_t shadowTextureWidth) {
-    for (int i = 0; i < shadowTextureWidth; i++) {
-        const float d = 1 - i / ((shadowTextureWidth * 1.0f) - 1.0f);
-        data[i] = static_cast<uint8_t>((exp(-4.0f * d * d) - 0.018f) * 255);
-    }
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLSkiaShadowPort.h b/libs/renderengine/gl/GLSkiaShadowPort.h
deleted file mode 100644
index 912c8bb..0000000
--- a/libs/renderengine/gl/GLSkiaShadowPort.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2019 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
-
-#include <math/vec4.h>
-#include <renderengine/Mesh.h>
-#include <ui/Rect.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-/**
- * The shadow geometry logic and vertex generation code has been ported from skia shadow
- * fast path OpenGL implementation to draw shadows around rects and rounded rects including
- * circles.
- *
- * path: skia/src/gpu/GrRenderTargetContext.cpp GrRenderTargetContext::drawFastShadow
- *
- * Modifications made:
- * - Switched to using std lib math functions
- * - Fall off function is implemented in vertex shader rather than a shadow texture
- * - Removed transformations applied on the caster rect since the caster will be in local
- *   coordinate space and will be transformed by the vertex shader.
- */
-
-enum RRectType {
-    kFill_RRectType,
-    kStroke_RRectType,
-    kOverstroke_RRectType,
-};
-
-struct Geometry {
-    vec4 fColor;
-    float fOuterRadius;
-    float fUmbraInset;
-    float fInnerRadius;
-    float fBlurRadius;
-    FloatRect fDevBounds;
-    RRectType fType;
-    bool fIsCircle;
-    bool fIsStroked;
-};
-
-std::unique_ptr<Geometry> getSpotShadowGeometry(const FloatRect& casterRect,
-                                                float casterCornerRadius, float casterZ,
-                                                bool casterIsTranslucent, const vec4& spotColor,
-                                                const vec3& lightPosition, float lightRadius);
-
-std::unique_ptr<Geometry> getAmbientShadowGeometry(const FloatRect& casterRect,
-                                                   float casterCornerRadius, float casterZ,
-                                                   bool casterIsTranslucent,
-                                                   const vec4& ambientColor);
-
-int getVertexCountForGeometry(const Geometry& shadowGeometry);
-
-int getIndexCountForGeometry(const Geometry& shadowGeometry);
-
-void fillVerticesForGeometry(const Geometry& shadowGeometry, int vertexCount,
-                             Mesh::VertexArray<vec2> position, Mesh::VertexArray<vec4> shadowColor,
-                             Mesh::VertexArray<vec3> shadowParams);
-
-void fillIndicesForGeometry(const Geometry& shadowGeometry, int indexCount,
-                            int startingVertexOffset, uint16_t* indices);
-
-/**
- * Maps shadow geometry 'alpha' varying (1 for darkest, 0 for transparent) to
- * darkness at that spot. Values are determined by an exponential falloff
- * function provided by UX.
- *
- * The texture is used for quick lookup in theshadow shader.
- *
- * textureData - filled with shadow texture data that needs to be at least of
- *               size textureWidth
- *
- * textureWidth - width of the texture, height is always 1
- */
-void fillShadowTextureData(uint8_t* textureData, size_t textureWidth);
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLVertexBuffer.cpp b/libs/renderengine/gl/GLVertexBuffer.cpp
deleted file mode 100644
index e50c471..0000000
--- a/libs/renderengine/gl/GLVertexBuffer.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "GLVertexBuffer.h"
-
-#include <GLES/gl.h>
-#include <GLES2/gl2.h>
-#include <nativebase/nativebase.h>
-#include <utils/Trace.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLVertexBuffer::GLVertexBuffer() {
-    glGenBuffers(1, &mBufferName);
-}
-
-GLVertexBuffer::~GLVertexBuffer() {
-    glDeleteBuffers(1, &mBufferName);
-}
-
-void GLVertexBuffer::allocateBuffers(const GLfloat data[], const GLuint size) {
-    ATRACE_CALL();
-    bind();
-    glBufferData(GL_ARRAY_BUFFER, size * sizeof(GLfloat), data, GL_STATIC_DRAW);
-    unbind();
-}
-
-void GLVertexBuffer::bind() const {
-    glBindBuffer(GL_ARRAY_BUFFER, mBufferName);
-}
-
-void GLVertexBuffer::unbind() const {
-    glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLVertexBuffer.h b/libs/renderengine/gl/GLVertexBuffer.h
deleted file mode 100644
index c0fd0c1..0000000
--- a/libs/renderengine/gl/GLVertexBuffer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 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
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-
-struct ANativeWindowBuffer;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLESRenderEngine;
-
-class GLVertexBuffer {
-public:
-    explicit GLVertexBuffer();
-    ~GLVertexBuffer();
-
-    void allocateBuffers(const GLfloat data[], const GLuint size);
-    uint32_t getBufferName() const { return mBufferName; }
-    void bind() const;
-    void unbind() const;
-
-private:
-    uint32_t mBufferName;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/ImageManager.cpp b/libs/renderengine/gl/ImageManager.cpp
deleted file mode 100644
index 6256649..0000000
--- a/libs/renderengine/gl/ImageManager.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-//#define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "RenderEngine"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <pthread.h>
-
-#include <processgroup/sched_policy.h>
-#include <utils/Trace.h>
-#include "GLESRenderEngine.h"
-#include "ImageManager.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-ImageManager::ImageManager(GLESRenderEngine* engine) : mEngine(engine) {}
-
-void ImageManager::initThread() {
-    mThread = std::thread([this]() { threadMain(); });
-    pthread_setname_np(mThread.native_handle(), "ImageManager");
-    // Use SCHED_FIFO to minimize jitter
-    struct sched_param param = {0};
-    param.sched_priority = 2;
-    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO for ImageManager");
-    }
-}
-
-ImageManager::~ImageManager() {
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mRunning = false;
-    }
-    mCondition.notify_all();
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-}
-
-void ImageManager::cacheAsync(const sp<GraphicBuffer>& buffer,
-                              const std::shared_ptr<Barrier>& barrier) {
-    if (buffer == nullptr) {
-        {
-            std::lock_guard<std::mutex> lock(barrier->mutex);
-            barrier->isOpen = true;
-            barrier->result = BAD_VALUE;
-        }
-        barrier->condition.notify_one();
-        return;
-    }
-    ATRACE_CALL();
-    QueueEntry entry = {QueueEntry::Operation::Insert, buffer, buffer->getId(), barrier};
-    queueOperation(std::move(entry));
-}
-
-status_t ImageManager::cache(const sp<GraphicBuffer>& buffer) {
-    ATRACE_CALL();
-    auto barrier = std::make_shared<Barrier>();
-    cacheAsync(buffer, barrier);
-    std::lock_guard<std::mutex> lock(barrier->mutex);
-    barrier->condition.wait(barrier->mutex,
-                            [&]() REQUIRES(barrier->mutex) { return barrier->isOpen; });
-    return barrier->result;
-}
-
-void ImageManager::releaseAsync(uint64_t bufferId, const std::shared_ptr<Barrier>& barrier) {
-    ATRACE_CALL();
-    QueueEntry entry = {QueueEntry::Operation::Delete, nullptr, bufferId, barrier};
-    queueOperation(std::move(entry));
-}
-
-void ImageManager::queueOperation(const QueueEntry&& entry) {
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mQueue.emplace(entry);
-        ATRACE_INT("ImageManagerQueueDepth", mQueue.size());
-    }
-    mCondition.notify_one();
-}
-
-void ImageManager::threadMain() {
-    set_sched_policy(0, SP_FOREGROUND);
-    bool run;
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        run = mRunning;
-    }
-    while (run) {
-        QueueEntry entry;
-        {
-            std::lock_guard<std::mutex> lock(mMutex);
-            mCondition.wait(mMutex,
-                            [&]() REQUIRES(mMutex) { return !mQueue.empty() || !mRunning; });
-            run = mRunning;
-
-            if (!mRunning) {
-                // if mRunning is false, then ImageManager is being destroyed, so
-                // bail out now.
-                break;
-            }
-
-            entry = mQueue.front();
-            mQueue.pop();
-            ATRACE_INT("ImageManagerQueueDepth", mQueue.size());
-        }
-
-        status_t result = NO_ERROR;
-        switch (entry.op) {
-            case QueueEntry::Operation::Delete:
-                mEngine->unbindExternalTextureBufferInternal(entry.bufferId);
-                break;
-            case QueueEntry::Operation::Insert:
-                result = mEngine->cacheExternalTextureBufferInternal(entry.buffer);
-                break;
-        }
-        if (entry.barrier != nullptr) {
-            {
-                std::lock_guard<std::mutex> entryLock(entry.barrier->mutex);
-                entry.barrier->result = result;
-                entry.barrier->isOpen = true;
-            }
-            entry.barrier->condition.notify_one();
-        }
-    }
-
-    ALOGD("Reached end of threadMain, terminating ImageManager thread!");
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/ImageManager.h b/libs/renderengine/gl/ImageManager.h
deleted file mode 100644
index be67de8..0000000
--- a/libs/renderengine/gl/ImageManager.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2019 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
-
-#include <condition_variable>
-#include <mutex>
-#include <queue>
-#include <thread>
-
-#include <ui/GraphicBuffer.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLESRenderEngine;
-
-class ImageManager {
-public:
-    struct Barrier {
-        std::mutex mutex;
-        std::condition_variable_any condition;
-        bool isOpen GUARDED_BY(mutex) = false;
-        status_t result GUARDED_BY(mutex) = NO_ERROR;
-    };
-    ImageManager(GLESRenderEngine* engine);
-    ~ImageManager();
-    // Starts the background thread for the ImageManager
-    // We need this to guarantee that the class is fully-constructed before the
-    // thread begins running.
-    void initThread();
-    void cacheAsync(const sp<GraphicBuffer>& buffer, const std::shared_ptr<Barrier>& barrier)
-            EXCLUDES(mMutex);
-    status_t cache(const sp<GraphicBuffer>& buffer);
-    void releaseAsync(uint64_t bufferId, const std::shared_ptr<Barrier>& barrier) EXCLUDES(mMutex);
-
-private:
-    struct QueueEntry {
-        enum class Operation { Delete, Insert };
-
-        Operation op = Operation::Delete;
-        sp<GraphicBuffer> buffer = nullptr;
-        uint64_t bufferId = 0;
-        std::shared_ptr<Barrier> barrier = nullptr;
-    };
-
-    void queueOperation(const QueueEntry&& entry);
-    void threadMain();
-    GLESRenderEngine* const mEngine;
-    std::thread mThread;
-    std::condition_variable_any mCondition;
-    std::mutex mMutex;
-    std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
-
-    bool mRunning GUARDED_BY(mMutex) = true;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/Program.cpp b/libs/renderengine/gl/Program.cpp
deleted file mode 100644
index 26f6166..0000000
--- a/libs/renderengine/gl/Program.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*Gluint
- * Copyright 2013 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.
- */
-
-#include "Program.h"
-
-#include <stdint.h>
-
-#include <log/log.h>
-#include <math/mat4.h>
-#include <utils/String8.h>
-#include "ProgramCache.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
-      : mInitialized(false) {
-    GLuint vertexId = buildShader(vertex, GL_VERTEX_SHADER);
-    GLuint fragmentId = buildShader(fragment, GL_FRAGMENT_SHADER);
-    GLuint programId = glCreateProgram();
-    glAttachShader(programId, vertexId);
-    glAttachShader(programId, fragmentId);
-    glBindAttribLocation(programId, position, "position");
-    glBindAttribLocation(programId, texCoords, "texCoords");
-    glBindAttribLocation(programId, cropCoords, "cropCoords");
-    glBindAttribLocation(programId, shadowColor, "shadowColor");
-    glBindAttribLocation(programId, shadowParams, "shadowParams");
-    glLinkProgram(programId);
-
-    GLint status;
-    glGetProgramiv(programId, GL_LINK_STATUS, &status);
-    if (status != GL_TRUE) {
-        ALOGE("Error while linking shaders:");
-        GLint infoLen = 0;
-        glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &infoLen);
-        if (infoLen > 1) {
-            GLchar log[infoLen];
-            glGetProgramInfoLog(programId, infoLen, 0, &log[0]);
-            ALOGE("%s", log);
-        }
-        glDetachShader(programId, vertexId);
-        glDetachShader(programId, fragmentId);
-        glDeleteShader(vertexId);
-        glDeleteShader(fragmentId);
-        glDeleteProgram(programId);
-    } else {
-        mProgram = programId;
-        mVertexShader = vertexId;
-        mFragmentShader = fragmentId;
-        mInitialized = true;
-        mProjectionMatrixLoc = glGetUniformLocation(programId, "projection");
-        mTextureMatrixLoc = glGetUniformLocation(programId, "texture");
-        mSamplerLoc = glGetUniformLocation(programId, "sampler");
-        mColorLoc = glGetUniformLocation(programId, "color");
-        mDisplayColorMatrixLoc = glGetUniformLocation(programId, "displayColorMatrix");
-        mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance");
-        mMaxMasteringLuminanceLoc = glGetUniformLocation(programId, "maxMasteringLuminance");
-        mMaxContentLuminanceLoc = glGetUniformLocation(programId, "maxContentLuminance");
-        mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix");
-        mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix");
-        mCornerRadiusLoc = glGetUniformLocation(programId, "cornerRadius");
-        mCropCenterLoc = glGetUniformLocation(programId, "cropCenter");
-
-        // set-up the default values for our uniforms
-        glUseProgram(programId);
-        glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, mat4().asArray());
-        glEnableVertexAttribArray(0);
-    }
-}
-
-Program::~Program() {
-    glDetachShader(mProgram, mVertexShader);
-    glDetachShader(mProgram, mFragmentShader);
-    glDeleteShader(mVertexShader);
-    glDeleteShader(mFragmentShader);
-    glDeleteProgram(mProgram);
-}
-
-bool Program::isValid() const {
-    return mInitialized;
-}
-
-void Program::use() {
-    glUseProgram(mProgram);
-}
-
-GLuint Program::getAttrib(const char* name) const {
-    // TODO: maybe use a local cache
-    return glGetAttribLocation(mProgram, name);
-}
-
-GLint Program::getUniform(const char* name) const {
-    // TODO: maybe use a local cache
-    return glGetUniformLocation(mProgram, name);
-}
-
-GLuint Program::buildShader(const char* source, GLenum type) {
-    GLuint shader = glCreateShader(type);
-    glShaderSource(shader, 1, &source, 0);
-    glCompileShader(shader);
-    GLint status;
-    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
-    if (status != GL_TRUE) {
-        // Some drivers return wrong values for GL_INFO_LOG_LENGTH
-        // use a fixed size instead
-        GLchar log[512];
-        glGetShaderInfoLog(shader, sizeof(log), 0, log);
-        ALOGE("Error while compiling shader: \n%s\n%s", source, log);
-        glDeleteShader(shader);
-        return 0;
-    }
-    return shader;
-}
-
-void Program::setUniforms(const Description& desc) {
-    // TODO: we should have a mechanism here to not always reset uniforms that
-    // didn't change for this program.
-
-    if (mSamplerLoc >= 0) {
-        glUniform1i(mSamplerLoc, 0);
-        glUniformMatrix4fv(mTextureMatrixLoc, 1, GL_FALSE, desc.texture.getMatrix().asArray());
-    }
-    if (mColorLoc >= 0) {
-        const float color[4] = {desc.color.r, desc.color.g, desc.color.b, desc.color.a};
-        glUniform4fv(mColorLoc, 1, color);
-    }
-    if (mDisplayColorMatrixLoc >= 0) {
-        glUniformMatrix4fv(mDisplayColorMatrixLoc, 1, GL_FALSE, desc.displayColorMatrix.asArray());
-    }
-    if (mInputTransformMatrixLoc >= 0) {
-        mat4 inputTransformMatrix = desc.inputTransformMatrix;
-        glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray());
-    }
-    if (mOutputTransformMatrixLoc >= 0) {
-        // The output transform matrix and color matrix can be combined as one matrix
-        // that is applied right before applying OETF.
-        mat4 outputTransformMatrix = desc.colorMatrix * desc.outputTransformMatrix;
-        glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, outputTransformMatrix.asArray());
-    }
-    if (mDisplayMaxLuminanceLoc >= 0) {
-        glUniform1f(mDisplayMaxLuminanceLoc, desc.displayMaxLuminance);
-    }
-    if (mMaxMasteringLuminanceLoc >= 0) {
-        glUniform1f(mMaxMasteringLuminanceLoc, desc.maxMasteringLuminance);
-    }
-    if (mMaxContentLuminanceLoc >= 0) {
-        glUniform1f(mMaxContentLuminanceLoc, desc.maxContentLuminance);
-    }
-    if (mCornerRadiusLoc >= 0) {
-        glUniform1f(mCornerRadiusLoc, desc.cornerRadius);
-    }
-    if (mCropCenterLoc >= 0) {
-        glUniform2f(mCropCenterLoc, desc.cropSize.x / 2.0f, desc.cropSize.y / 2.0f);
-    }
-    // these uniforms are always present
-    glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.projectionMatrix.asArray());
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/Program.h b/libs/renderengine/gl/Program.h
deleted file mode 100644
index 41f1bf8..0000000
--- a/libs/renderengine/gl/Program.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_RENDER_ENGINE_PROGRAM_H
-#define SF_RENDER_ENGINE_PROGRAM_H
-
-#include <stdint.h>
-
-#include <GLES2/gl2.h>
-#include <renderengine/private/Description.h>
-#include "ProgramCache.h"
-
-namespace android {
-
-class String8;
-
-namespace renderengine {
-namespace gl {
-
-/*
- * Abstracts a GLSL program comprising a vertex and fragment shader
- */
-class Program {
-public:
-    // known locations for position and texture coordinates
-    enum {
-        /* position of each vertex for vertex shader */
-        position = 0,
-
-        /* UV coordinates for texture mapping */
-        texCoords = 1,
-
-        /* Crop coordinates, in pixels */
-        cropCoords = 2,
-
-        /* Shadow color */
-        shadowColor = 3,
-
-        /* Shadow params */
-        shadowParams = 4,
-    };
-
-    Program(const ProgramCache::Key& needs, const char* vertex, const char* fragment);
-    ~Program();
-
-    /* whether this object is usable */
-    bool isValid() const;
-
-    /* Binds this program to the GLES context */
-    void use();
-
-    /* Returns the location of the specified attribute */
-    GLuint getAttrib(const char* name) const;
-
-    /* Returns the location of the specified uniform */
-    GLint getUniform(const char* name) const;
-
-    /* set-up uniforms from the description */
-    void setUniforms(const Description& desc);
-
-private:
-    GLuint buildShader(const char* source, GLenum type);
-
-    // whether the initialization succeeded
-    bool mInitialized;
-
-    // Name of the OpenGL program and shaders
-    GLuint mProgram;
-    GLuint mVertexShader;
-    GLuint mFragmentShader;
-
-    /* location of the projection matrix uniform */
-    GLint mProjectionMatrixLoc;
-
-    /* location of the texture matrix uniform */
-    GLint mTextureMatrixLoc;
-
-    /* location of the sampler uniform */
-    GLint mSamplerLoc;
-
-    /* location of the color uniform */
-    GLint mColorLoc;
-
-    /* location of display luminance uniform */
-    GLint mDisplayMaxLuminanceLoc;
-    /* location of max mastering luminance uniform */
-    GLint mMaxMasteringLuminanceLoc;
-    /* location of max content luminance uniform */
-    GLint mMaxContentLuminanceLoc;
-
-    /* location of transform matrix */
-    GLint mInputTransformMatrixLoc;
-    GLint mOutputTransformMatrixLoc;
-    GLint mDisplayColorMatrixLoc;
-
-    /* location of corner radius uniform */
-    GLint mCornerRadiusLoc;
-
-    /* location of surface crop origin uniform, for rounded corner clipping */
-    GLint mCropCenterLoc;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
-
-#endif /* SF_RENDER_ENGINE_PROGRAM_H */
diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp
deleted file mode 100644
index 96ccf5c..0000000
--- a/libs/renderengine/gl/ProgramCache.cpp
+++ /dev/null
@@ -1,802 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "ProgramCache.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <log/log.h>
-#include <renderengine/private/Description.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-#include "Program.h"
-
-ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::ProgramCache)
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-/*
- * A simple formatter class to automatically add the endl and
- * manage the indentation.
- */
-
-class Formatter;
-static Formatter& indent(Formatter& f);
-static Formatter& dedent(Formatter& f);
-
-class Formatter {
-    String8 mString;
-    int mIndent;
-    typedef Formatter& (*FormaterManipFunc)(Formatter&);
-    friend Formatter& indent(Formatter& f);
-    friend Formatter& dedent(Formatter& f);
-
-public:
-    Formatter() : mIndent(0) {}
-
-    String8 getString() const { return mString; }
-
-    friend Formatter& operator<<(Formatter& out, const char* in) {
-        for (int i = 0; i < out.mIndent; i++) {
-            out.mString.append("    ");
-        }
-        out.mString.append(in);
-        out.mString.append("\n");
-        return out;
-    }
-    friend inline Formatter& operator<<(Formatter& out, const String8& in) {
-        return operator<<(out, in.string());
-    }
-    friend inline Formatter& operator<<(Formatter& to, FormaterManipFunc func) {
-        return (*func)(to);
-    }
-};
-Formatter& indent(Formatter& f) {
-    f.mIndent++;
-    return f;
-}
-Formatter& dedent(Formatter& f) {
-    f.mIndent--;
-    return f;
-}
-
-void ProgramCache::primeCache(EGLContext context, bool toneMapperShaderOnly) {
-    auto& cache = mCaches[context];
-    uint32_t shaderCount = 0;
-
-    if (toneMapperShaderOnly) {
-        Key shaderKey;
-        // base settings used by HDR->SDR tonemap only
-        shaderKey.set(Key::BLEND_MASK | Key::INPUT_TRANSFORM_MATRIX_MASK |
-                      Key::OUTPUT_TRANSFORM_MATRIX_MASK | Key::OUTPUT_TF_MASK |
-                      Key::OPACITY_MASK | Key::ALPHA_MASK |
-                      Key::ROUNDED_CORNERS_MASK | Key::TEXTURE_MASK,
-                      Key::BLEND_NORMAL | Key::INPUT_TRANSFORM_MATRIX_ON |
-                      Key::OUTPUT_TRANSFORM_MATRIX_ON | Key::OUTPUT_TF_SRGB |
-                      Key::OPACITY_OPAQUE | Key::ALPHA_EQ_ONE |
-                      Key::ROUNDED_CORNERS_OFF | Key::TEXTURE_EXT);
-        for (int i = 0; i < 4; i++) {
-            // Cache input transfer for HLG & ST2084
-            shaderKey.set(Key::INPUT_TF_MASK, (i & 1) ?
-                    Key::INPUT_TF_HLG : Key::INPUT_TF_ST2084);
-
-            if (cache.count(shaderKey) == 0) {
-                cache.emplace(shaderKey, generateProgram(shaderKey));
-                shaderCount++;
-            }
-        }
-        return;
-    }
-
-    uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK
-        | Key::ROUNDED_CORNERS_MASK;
-    // Prime the cache for all combinations of the above masks,
-    // leaving off the experimental color matrix mask options.
-
-    nsecs_t timeBefore = systemTime();
-    for (uint32_t keyVal = 0; keyVal <= keyMask; keyVal++) {
-        Key shaderKey;
-        shaderKey.set(keyMask, keyVal);
-        uint32_t tex = shaderKey.getTextureTarget();
-        if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) {
-            continue;
-        }
-        if (cache.count(shaderKey) == 0) {
-            cache.emplace(shaderKey, generateProgram(shaderKey));
-            shaderCount++;
-        }
-    }
-
-    // Prime for sRGB->P3 conversion
-    Key shaderKey;
-    shaderKey.set(Key::BLEND_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK | Key::INPUT_TF_MASK |
-                          Key::OUTPUT_TF_MASK,
-                  Key::BLEND_PREMULT | Key::OUTPUT_TRANSFORM_MATRIX_ON | Key::INPUT_TF_SRGB |
-                          Key::OUTPUT_TF_SRGB);
-    for (int i = 0; i < 16; i++) {
-        shaderKey.set(Key::OPACITY_MASK, (i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
-        shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE);
-
-        // Cache rounded corners
-        shaderKey.set(Key::ROUNDED_CORNERS_MASK,
-                      (i & 4) ? Key::ROUNDED_CORNERS_ON : Key::ROUNDED_CORNERS_OFF);
-
-        // Cache texture off option for window transition
-        shaderKey.set(Key::TEXTURE_MASK, (i & 8) ? Key::TEXTURE_EXT : Key::TEXTURE_OFF);
-        if (cache.count(shaderKey) == 0) {
-            cache.emplace(shaderKey, generateProgram(shaderKey));
-            shaderCount++;
-        }
-    }
-
-    nsecs_t timeAfter = systemTime();
-    float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
-    ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs);
-}
-
-ProgramCache::Key ProgramCache::computeKey(const Description& description) {
-    Key needs;
-    needs.set(Key::TEXTURE_MASK,
-              !description.textureEnabled ? Key::TEXTURE_OFF
-                      : description.texture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES
-                      ? Key::TEXTURE_EXT
-                      : description.texture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_2D
-                                                                                : Key::TEXTURE_OFF)
-            .set(Key::ALPHA_MASK, (description.color.a < 1) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE)
-            .set(Key::BLEND_MASK,
-                 description.isPremultipliedAlpha ? Key::BLEND_PREMULT : Key::BLEND_NORMAL)
-            .set(Key::OPACITY_MASK,
-                 description.isOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
-            .set(Key::Key::INPUT_TRANSFORM_MATRIX_MASK,
-                 description.hasInputTransformMatrix() ? Key::INPUT_TRANSFORM_MATRIX_ON
-                                                       : Key::INPUT_TRANSFORM_MATRIX_OFF)
-            .set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK,
-                 description.hasOutputTransformMatrix() || description.hasColorMatrix()
-                         ? Key::OUTPUT_TRANSFORM_MATRIX_ON
-                         : Key::OUTPUT_TRANSFORM_MATRIX_OFF)
-            .set(Key::Key::DISPLAY_COLOR_TRANSFORM_MATRIX_MASK,
-                 description.hasDisplayColorMatrix() ? Key::DISPLAY_COLOR_TRANSFORM_MATRIX_ON
-                                                     : Key::DISPLAY_COLOR_TRANSFORM_MATRIX_OFF)
-            .set(Key::ROUNDED_CORNERS_MASK,
-                 description.cornerRadius > 0 ? Key::ROUNDED_CORNERS_ON : Key::ROUNDED_CORNERS_OFF)
-            .set(Key::SHADOW_MASK, description.drawShadows ? Key::SHADOW_ON : Key::SHADOW_OFF);
-
-    if (needs.hasTransformMatrix() ||
-        (description.inputTransferFunction != description.outputTransferFunction)) {
-        switch (description.inputTransferFunction) {
-            case Description::TransferFunction::LINEAR:
-            default:
-                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_LINEAR);
-                break;
-            case Description::TransferFunction::SRGB:
-                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_SRGB);
-                break;
-            case Description::TransferFunction::ST2084:
-                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_ST2084);
-                break;
-            case Description::TransferFunction::HLG:
-                needs.set(Key::INPUT_TF_MASK, Key::INPUT_TF_HLG);
-                break;
-        }
-
-        switch (description.outputTransferFunction) {
-            case Description::TransferFunction::LINEAR:
-            default:
-                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_LINEAR);
-                break;
-            case Description::TransferFunction::SRGB:
-                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_SRGB);
-                break;
-            case Description::TransferFunction::ST2084:
-                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_ST2084);
-                break;
-            case Description::TransferFunction::HLG:
-                needs.set(Key::OUTPUT_TF_MASK, Key::OUTPUT_TF_HLG);
-                break;
-        }
-    }
-
-    return needs;
-}
-
-// Generate EOTF that converts signal values to relative display light,
-// both normalized to [0, 1].
-void ProgramCache::generateEOTF(Formatter& fs, const Key& needs) {
-    switch (needs.getInputTF()) {
-        case Key::INPUT_TF_SRGB:
-            fs << R"__SHADER__(
-                float EOTF_sRGB(float srgb) {
-                    return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
-                }
-
-                vec3 EOTF_sRGB(const vec3 srgb) {
-                    return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
-                }
-
-                vec3 EOTF(const vec3 srgb) {
-                    return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
-                }
-            )__SHADER__";
-            break;
-        case Key::INPUT_TF_ST2084:
-            fs << R"__SHADER__(
-                vec3 EOTF(const highp vec3 color) {
-                    const highp float m1 = (2610.0 / 4096.0) / 4.0;
-                    const highp float m2 = (2523.0 / 4096.0) * 128.0;
-                    const highp float c1 = (3424.0 / 4096.0);
-                    const highp float c2 = (2413.0 / 4096.0) * 32.0;
-                    const highp float c3 = (2392.0 / 4096.0) * 32.0;
-
-                    highp vec3 tmp = pow(clamp(color, 0.0, 1.0), 1.0 / vec3(m2));
-                    tmp = max(tmp - c1, 0.0) / (c2 - c3 * tmp);
-                    return pow(tmp, 1.0 / vec3(m1));
-                }
-            )__SHADER__";
-            break;
-        case Key::INPUT_TF_HLG:
-            fs << R"__SHADER__(
-                highp float EOTF_channel(const highp float channel) {
-                    const highp float a = 0.17883277;
-                    const highp float b = 0.28466892;
-                    const highp float c = 0.55991073;
-                    return channel <= 0.5 ? channel * channel / 3.0 :
-                            (exp((channel - c) / a) + b) / 12.0;
-                }
-
-                vec3 EOTF(const highp vec3 color) {
-                    return vec3(EOTF_channel(color.r), EOTF_channel(color.g),
-                            EOTF_channel(color.b));
-                }
-            )__SHADER__";
-            break;
-        default:
-            fs << R"__SHADER__(
-                vec3 EOTF(const vec3 linear) {
-                    return linear;
-                }
-            )__SHADER__";
-            break;
-    }
-}
-
-void ProgramCache::generateToneMappingProcess(Formatter& fs, const Key& needs) {
-    // Convert relative light to absolute light.
-    switch (needs.getInputTF()) {
-        case Key::INPUT_TF_ST2084:
-            fs << R"__SHADER__(
-                highp vec3 ScaleLuminance(highp vec3 color) {
-                    return color * 10000.0;
-                }
-            )__SHADER__";
-            break;
-        case Key::INPUT_TF_HLG:
-            fs << R"__SHADER__(
-                highp vec3 ScaleLuminance(highp vec3 color) {
-                    // The formula is:
-                    // alpha * pow(Y, gamma - 1.0) * color + beta;
-                    // where alpha is 1000.0, gamma is 1.2, beta is 0.0.
-                    return color * 1000.0 * pow(color.y, 0.2);
-                }
-            )__SHADER__";
-            break;
-        default:
-            fs << R"__SHADER__(
-                highp vec3 ScaleLuminance(highp vec3 color) {
-                    return color * displayMaxLuminance;
-                }
-            )__SHADER__";
-            break;
-    }
-
-    // Tone map absolute light to display luminance range.
-    switch (needs.getInputTF()) {
-        case Key::INPUT_TF_ST2084:
-        case Key::INPUT_TF_HLG:
-            switch (needs.getOutputTF()) {
-                case Key::OUTPUT_TF_HLG:
-                    // Right now when mixed PQ and HLG contents are presented,
-                    // HLG content will always be converted to PQ. However, for
-                    // completeness, we simply clamp the value to [0.0, 1000.0].
-                    fs << R"__SHADER__(
-                        highp vec3 ToneMap(highp vec3 color) {
-                            return clamp(color, 0.0, 1000.0);
-                        }
-                    )__SHADER__";
-                    break;
-                case Key::OUTPUT_TF_ST2084:
-                    fs << R"__SHADER__(
-                        highp vec3 ToneMap(highp vec3 color) {
-                            return color;
-                        }
-                    )__SHADER__";
-                    break;
-                default:
-                    fs << R"__SHADER__(
-                        highp vec3 ToneMap(highp vec3 color) {
-                            float maxMasteringLumi = maxMasteringLuminance;
-                            float maxContentLumi = maxContentLuminance;
-                            float maxInLumi = min(maxMasteringLumi, maxContentLumi);
-                            float maxOutLumi = displayMaxLuminance;
-
-                            float nits = color.y;
-
-                            // clamp to max input luminance
-                            nits = clamp(nits, 0.0, maxInLumi);
-
-                            // scale [0.0, maxInLumi] to [0.0, maxOutLumi]
-                            if (maxInLumi <= maxOutLumi) {
-                                return color * (maxOutLumi / maxInLumi);
-                            } else {
-                                // three control points
-                                const float x0 = 10.0;
-                                const float y0 = 17.0;
-                                float x1 = maxOutLumi * 0.75;
-                                float y1 = x1;
-                                float x2 = x1 + (maxInLumi - x1) / 2.0;
-                                float y2 = y1 + (maxOutLumi - y1) * 0.75;
-
-                                // horizontal distances between the last three control points
-                                float h12 = x2 - x1;
-                                float h23 = maxInLumi - x2;
-                                // tangents at the last three control points
-                                float m1 = (y2 - y1) / h12;
-                                float m3 = (maxOutLumi - y2) / h23;
-                                float m2 = (m1 + m3) / 2.0;
-
-                                if (nits < x0) {
-                                    // scale [0.0, x0] to [0.0, y0] linearly
-                                    float slope = y0 / x0;
-                                    return color * slope;
-                                } else if (nits < x1) {
-                                    // scale [x0, x1] to [y0, y1] linearly
-                                    float slope = (y1 - y0) / (x1 - x0);
-                                    nits = y0 + (nits - x0) * slope;
-                                } else if (nits < x2) {
-                                    // scale [x1, x2] to [y1, y2] using Hermite interp
-                                    float t = (nits - x1) / h12;
-                                    nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +
-                                            (y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t;
-                                } else {
-                                    // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp
-                                    float t = (nits - x2) / h23;
-                                    nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +
-                                            (maxOutLumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t;
-                                }
-                            }
-
-                            // color.y is greater than x0 and is thus non-zero
-                            return color * (nits / color.y);
-                        }
-                    )__SHADER__";
-                    break;
-            }
-            break;
-        default:
-            // inverse tone map; the output luminance can be up to maxOutLumi.
-            fs << R"__SHADER__(
-                highp vec3 ToneMap(highp vec3 color) {
-                    const float maxOutLumi = 3000.0;
-
-                    const float x0 = 5.0;
-                    const float y0 = 2.5;
-                    float x1 = displayMaxLuminance * 0.7;
-                    float y1 = maxOutLumi * 0.15;
-                    float x2 = displayMaxLuminance * 0.9;
-                    float y2 = maxOutLumi * 0.45;
-                    float x3 = displayMaxLuminance;
-                    float y3 = maxOutLumi;
-
-                    float c1 = y1 / 3.0;
-                    float c2 = y2 / 2.0;
-                    float c3 = y3 / 1.5;
-
-                    float nits = color.y;
-
-                    float scale;
-                    if (nits <= x0) {
-                        // scale [0.0, x0] to [0.0, y0] linearly
-                        const float slope = y0 / x0;
-                        return color * slope;
-                    } else if (nits <= x1) {
-                        // scale [x0, x1] to [y0, y1] using a curve
-                        float t = (nits - x0) / (x1 - x0);
-                        nits = (1.0 - t) * (1.0 - t) * y0 + 2.0 * (1.0 - t) * t * c1 + t * t * y1;
-                    } else if (nits <= x2) {
-                        // scale [x1, x2] to [y1, y2] using a curve
-                        float t = (nits - x1) / (x2 - x1);
-                        nits = (1.0 - t) * (1.0 - t) * y1 + 2.0 * (1.0 - t) * t * c2 + t * t * y2;
-                    } else {
-                        // scale [x2, x3] to [y2, y3] using a curve
-                        float t = (nits - x2) / (x3 - x2);
-                        nits = (1.0 - t) * (1.0 - t) * y2 + 2.0 * (1.0 - t) * t * c3 + t * t * y3;
-                    }
-
-                    // color.y is greater than x0 and is thus non-zero
-                    return color * (nits / color.y);
-                }
-            )__SHADER__";
-            break;
-    }
-
-    // convert absolute light to relative light.
-    switch (needs.getOutputTF()) {
-        case Key::OUTPUT_TF_ST2084:
-            fs << R"__SHADER__(
-                highp vec3 NormalizeLuminance(highp vec3 color) {
-                    return color / 10000.0;
-                }
-            )__SHADER__";
-            break;
-        case Key::OUTPUT_TF_HLG:
-            fs << R"__SHADER__(
-                highp vec3 NormalizeLuminance(highp vec3 color) {
-                    return color / 1000.0 * pow(color.y / 1000.0, -0.2 / 1.2);
-                }
-            )__SHADER__";
-            break;
-        default:
-            fs << R"__SHADER__(
-                highp vec3 NormalizeLuminance(highp vec3 color) {
-                    return color / displayMaxLuminance;
-                }
-            )__SHADER__";
-            break;
-    }
-}
-
-// Generate OOTF that modifies the relative scence light to relative display light.
-void ProgramCache::generateOOTF(Formatter& fs, const ProgramCache::Key& needs) {
-    if (!needs.needsToneMapping()) {
-        fs << R"__SHADER__(
-            highp vec3 OOTF(const highp vec3 color) {
-                return color;
-            }
-        )__SHADER__";
-    } else {
-        generateToneMappingProcess(fs, needs);
-        fs << R"__SHADER__(
-            highp vec3 OOTF(const highp vec3 color) {
-                return NormalizeLuminance(ToneMap(ScaleLuminance(color)));
-            }
-        )__SHADER__";
-    }
-}
-
-// Generate OETF that converts relative display light to signal values,
-// both normalized to [0, 1]
-void ProgramCache::generateOETF(Formatter& fs, const Key& needs) {
-    switch (needs.getOutputTF()) {
-        case Key::OUTPUT_TF_SRGB:
-            fs << R"__SHADER__(
-                float OETF_sRGB(const float linear) {
-                    return linear <= 0.0031308 ?
-                            linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
-                }
-
-                vec3 OETF_sRGB(const vec3 linear) {
-                    return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
-                }
-
-                vec3 OETF(const vec3 linear) {
-                    return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
-                }
-            )__SHADER__";
-            break;
-        case Key::OUTPUT_TF_ST2084:
-            fs << R"__SHADER__(
-                vec3 OETF(const vec3 linear) {
-                    const highp float m1 = (2610.0 / 4096.0) / 4.0;
-                    const highp float m2 = (2523.0 / 4096.0) * 128.0;
-                    const highp float c1 = (3424.0 / 4096.0);
-                    const highp float c2 = (2413.0 / 4096.0) * 32.0;
-                    const highp float c3 = (2392.0 / 4096.0) * 32.0;
-
-                    highp vec3 tmp = pow(linear, vec3(m1));
-                    tmp = (c1 + c2 * tmp) / (1.0 + c3 * tmp);
-                    return pow(tmp, vec3(m2));
-                }
-            )__SHADER__";
-            break;
-        case Key::OUTPUT_TF_HLG:
-            fs << R"__SHADER__(
-                highp float OETF_channel(const highp float channel) {
-                    const highp float a = 0.17883277;
-                    const highp float b = 0.28466892;
-                    const highp float c = 0.55991073;
-                    return channel <= 1.0 / 12.0 ? sqrt(3.0 * channel) :
-                            a * log(12.0 * channel - b) + c;
-                }
-
-                vec3 OETF(const highp vec3 color) {
-                    return vec3(OETF_channel(color.r), OETF_channel(color.g),
-                            OETF_channel(color.b));
-                }
-            )__SHADER__";
-            break;
-        default:
-            fs << R"__SHADER__(
-                vec3 OETF(const vec3 linear) {
-                    return linear;
-                }
-            )__SHADER__";
-            break;
-    }
-}
-
-String8 ProgramCache::generateVertexShader(const Key& needs) {
-    Formatter vs;
-    if (needs.hasTextureCoords()) {
-        vs << "attribute vec4 texCoords;"
-           << "varying vec2 outTexCoords;";
-    }
-    if (needs.hasRoundedCorners()) {
-        vs << "attribute lowp vec4 cropCoords;";
-        vs << "varying lowp vec2 outCropCoords;";
-    }
-    if (needs.drawShadows()) {
-        vs << "attribute lowp vec4 shadowColor;";
-        vs << "varying lowp vec4 outShadowColor;";
-        vs << "attribute lowp vec4 shadowParams;";
-        vs << "varying lowp vec3 outShadowParams;";
-    }
-    vs << "attribute vec4 position;"
-       << "uniform mat4 projection;"
-       << "uniform mat4 texture;"
-       << "void main(void) {" << indent << "gl_Position = projection * position;";
-    if (needs.hasTextureCoords()) {
-        vs << "outTexCoords = (texture * texCoords).st;";
-    }
-    if (needs.hasRoundedCorners()) {
-        vs << "outCropCoords = cropCoords.st;";
-    }
-    if (needs.drawShadows()) {
-        vs << "outShadowColor = shadowColor;";
-        vs << "outShadowParams = shadowParams.xyz;";
-    }
-    vs << dedent << "}";
-    return vs.getString();
-}
-
-String8 ProgramCache::generateFragmentShader(const Key& needs) {
-    Formatter fs;
-    if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
-        fs << "#extension GL_OES_EGL_image_external : require";
-    }
-
-    // default precision is required-ish in fragment shaders
-    fs << "precision mediump float;";
-
-    if (needs.getTextureTarget() == Key::TEXTURE_EXT) {
-        fs << "uniform samplerExternalOES sampler;";
-    } else if (needs.getTextureTarget() == Key::TEXTURE_2D) {
-        fs << "uniform sampler2D sampler;";
-    }
-
-    if (needs.hasTextureCoords()) {
-        fs << "varying highp vec2 outTexCoords;";
-    }
-
-    if (needs.hasRoundedCorners()) {
-        // Rounded corners implementation using a signed distance function.
-        fs << R"__SHADER__(
-            uniform float cornerRadius;
-            uniform vec2 cropCenter;
-            varying vec2 outCropCoords;
-
-            /**
-             * This function takes the current crop coordinates and calculates an alpha value based
-             * on the corner radius and distance from the crop center.
-             */
-            float applyCornerRadius(vec2 cropCoords)
-            {
-                vec2 position = cropCoords - cropCenter;
-                // Scale down the dist vector here, as otherwise large corner
-                // radii can cause floating point issues when computing the norm
-                vec2 dist = (abs(position) - cropCenter + vec2(cornerRadius)) / 16.0;
-                // Once we've found the norm, then scale back up.
-                float plane = length(max(dist, vec2(0.0))) * 16.0;
-                return 1.0 - clamp(plane - cornerRadius, 0.0, 1.0);
-            }
-            )__SHADER__";
-    }
-
-    if (needs.drawShadows()) {
-        fs << R"__SHADER__(
-            varying lowp vec4 outShadowColor;
-            varying lowp vec3 outShadowParams;
-
-            /**
-             * Returns the shadow color.
-             */
-            vec4 getShadowColor()
-            {
-                lowp float d = length(outShadowParams.xy);
-                vec2 uv = vec2(outShadowParams.z * (1.0 - d), 0.5);
-                lowp float factor = texture2D(sampler, uv).a;
-                return outShadowColor * factor;
-            }
-            )__SHADER__";
-    }
-
-    if (needs.getTextureTarget() == Key::TEXTURE_OFF || needs.hasAlpha()) {
-        fs << "uniform vec4 color;";
-    }
-
-    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) ||
-        needs.hasDisplayColorMatrix()) {
-        if (needs.needsToneMapping()) {
-            fs << "uniform float displayMaxLuminance;";
-            fs << "uniform float maxMasteringLuminance;";
-            fs << "uniform float maxContentLuminance;";
-        }
-
-        if (needs.hasInputTransformMatrix()) {
-            fs << "uniform mat4 inputTransformMatrix;";
-            fs << R"__SHADER__(
-                highp vec3 InputTransform(const highp vec3 color) {
-                    return clamp(vec3(inputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0);
-                }
-            )__SHADER__";
-        } else {
-            fs << R"__SHADER__(
-                highp vec3 InputTransform(const highp vec3 color) {
-                    return color;
-                }
-            )__SHADER__";
-        }
-
-        // the transformation from a wider colorspace to a narrower one can
-        // result in >1.0 or <0.0 pixel values
-        if (needs.hasOutputTransformMatrix()) {
-            fs << "uniform mat4 outputTransformMatrix;";
-            fs << R"__SHADER__(
-                highp vec3 OutputTransform(const highp vec3 color) {
-                    return clamp(vec3(outputTransformMatrix * vec4(color, 1.0)), 0.0, 1.0);
-                }
-            )__SHADER__";
-        } else {
-            fs << R"__SHADER__(
-                highp vec3 OutputTransform(const highp vec3 color) {
-                    return clamp(color, 0.0, 1.0);
-                }
-            )__SHADER__";
-        }
-
-        if (needs.hasDisplayColorMatrix()) {
-            fs << "uniform mat4 displayColorMatrix;";
-            fs << R"__SHADER__(
-                highp vec3 DisplayColorMatrix(const highp vec3 color) {
-                    return clamp(vec3(displayColorMatrix * vec4(color, 1.0)), 0.0, 1.0);
-                }
-            )__SHADER__";
-        } else {
-            fs << R"__SHADER__(
-                highp vec3 DisplayColorMatrix(const highp vec3 color) {
-                    return color;
-                }
-            )__SHADER__";
-        }
-
-        generateEOTF(fs, needs);
-        generateOOTF(fs, needs);
-        generateOETF(fs, needs);
-    }
-
-    fs << "void main(void) {" << indent;
-    if (needs.drawShadows()) {
-        fs << "gl_FragColor = getShadowColor();";
-    } else {
-        if (needs.isTexturing()) {
-            fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
-        } else {
-            fs << "gl_FragColor.rgb = color.rgb;";
-            fs << "gl_FragColor.a = 1.0;";
-        }
-        if (needs.isOpaque()) {
-            fs << "gl_FragColor.a = 1.0;";
-        }
-    }
-
-    if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF()) ||
-        needs.hasDisplayColorMatrix()) {
-        if (!needs.isOpaque() && needs.isPremultiplied()) {
-            // un-premultiply if needed before linearization
-            // avoid divide by 0 by adding 0.5/256 to the alpha channel
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
-        }
-        fs << "gl_FragColor.rgb = "
-              "DisplayColorMatrix(OETF(OutputTransform(OOTF(InputTransform(EOTF(gl_FragColor.rgb)))"
-              ")));";
-
-        if (!needs.isOpaque() && needs.isPremultiplied()) {
-            // and re-premultiply if needed after gamma correction
-            fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
-        }
-    }
-
-    /*
-     * Whether applying layer alpha before or after color transform doesn't matter,
-     * as long as we can undo premultiplication. But we cannot un-premultiply
-     * for color transform if the layer alpha = 0, e.g. 0 / (0 + 0.0019) = 0.
-     */
-    if (!needs.drawShadows()) {
-        if (needs.hasAlpha()) {
-            // modulate the current alpha value with alpha set
-            if (needs.isPremultiplied()) {
-                // ... and the color too if we're premultiplied
-                fs << "gl_FragColor *= color.a;";
-            } else {
-                fs << "gl_FragColor.a *= color.a;";
-            }
-        }
-    }
-
-    if (needs.hasRoundedCorners()) {
-        if (needs.isPremultiplied()) {
-            fs << "gl_FragColor *= vec4(applyCornerRadius(outCropCoords));";
-        } else {
-            fs << "gl_FragColor.a *= applyCornerRadius(outCropCoords);";
-        }
-    }
-
-    fs << dedent << "}";
-    return fs.getString();
-}
-
-std::unique_ptr<Program> ProgramCache::generateProgram(const Key& needs) {
-    ATRACE_CALL();
-
-    // vertex shader
-    String8 vs = generateVertexShader(needs);
-
-    // fragment shader
-    String8 fs = generateFragmentShader(needs);
-
-    return std::make_unique<Program>(needs, vs.string(), fs.string());
-}
-
-void ProgramCache::useProgram(EGLContext context, const Description& description) {
-    // generate the key for the shader based on the description
-    Key needs(computeKey(description));
-
-    // look-up the program in the cache
-    auto& cache = mCaches[context];
-    auto it = cache.find(needs);
-    if (it == cache.end()) {
-        // we didn't find our program, so generate one...
-        nsecs_t time = systemTime();
-        it = cache.emplace(needs, generateProgram(needs)).first;
-        time = systemTime() - time;
-
-        ALOGV(">>> generated new program for context %p: needs=%08X, time=%u ms (%zu programs)",
-              context, needs.mKey, uint32_t(ns2ms(time)), cache.size());
-    }
-
-    // here we have a suitable program for this description
-    std::unique_ptr<Program>& program = it->second;
-    if (program->isValid()) {
-        program->use();
-        program->setUniforms(description);
-    }
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/ProgramCache.h b/libs/renderengine/gl/ProgramCache.h
deleted file mode 100644
index 83fef8e..0000000
--- a/libs/renderengine/gl/ProgramCache.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H
-#define SF_RENDER_ENGINE_PROGRAMCACHE_H
-
-#include <memory>
-#include <unordered_map>
-
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <renderengine/private/Description.h>
-#include <utils/Singleton.h>
-#include <utils/TypeHelpers.h>
-
-namespace android {
-
-class String8;
-
-namespace renderengine {
-
-struct Description;
-
-namespace gl {
-
-class Formatter;
-class Program;
-
-/*
- * This class generates GLSL programs suitable to handle a given
- * Description. It's responsible for figuring out what to
- * generate from a Description.
- * It also maintains a cache of these Programs.
- */
-class ProgramCache : public Singleton<ProgramCache> {
-public:
-    /*
-     * Key is used to retrieve a Program in the cache.
-     * A Key is generated from a Description.
-     */
-    class Key {
-        friend class ProgramCache;
-        typedef uint32_t key_t;
-        key_t mKey;
-
-    public:
-        enum {
-            BLEND_SHIFT = 0,
-            BLEND_MASK = 1 << BLEND_SHIFT,
-            BLEND_PREMULT = 1 << BLEND_SHIFT,
-            BLEND_NORMAL = 0 << BLEND_SHIFT,
-
-            OPACITY_SHIFT = 1,
-            OPACITY_MASK = 1 << OPACITY_SHIFT,
-            OPACITY_OPAQUE = 1 << OPACITY_SHIFT,
-            OPACITY_TRANSLUCENT = 0 << OPACITY_SHIFT,
-
-            ALPHA_SHIFT = 2,
-            ALPHA_MASK = 1 << ALPHA_SHIFT,
-            ALPHA_LT_ONE = 1 << ALPHA_SHIFT,
-            ALPHA_EQ_ONE = 0 << ALPHA_SHIFT,
-
-            TEXTURE_SHIFT = 3,
-            TEXTURE_MASK = 3 << TEXTURE_SHIFT,
-            TEXTURE_OFF = 0 << TEXTURE_SHIFT,
-            TEXTURE_EXT = 1 << TEXTURE_SHIFT,
-            TEXTURE_2D = 2 << TEXTURE_SHIFT,
-
-            ROUNDED_CORNERS_SHIFT = 5,
-            ROUNDED_CORNERS_MASK = 1 << ROUNDED_CORNERS_SHIFT,
-            ROUNDED_CORNERS_OFF = 0 << ROUNDED_CORNERS_SHIFT,
-            ROUNDED_CORNERS_ON = 1 << ROUNDED_CORNERS_SHIFT,
-
-            INPUT_TRANSFORM_MATRIX_SHIFT = 6,
-            INPUT_TRANSFORM_MATRIX_MASK = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
-            INPUT_TRANSFORM_MATRIX_OFF = 0 << INPUT_TRANSFORM_MATRIX_SHIFT,
-            INPUT_TRANSFORM_MATRIX_ON = 1 << INPUT_TRANSFORM_MATRIX_SHIFT,
-
-            OUTPUT_TRANSFORM_MATRIX_SHIFT = 7,
-            OUTPUT_TRANSFORM_MATRIX_MASK = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
-            OUTPUT_TRANSFORM_MATRIX_OFF = 0 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
-            OUTPUT_TRANSFORM_MATRIX_ON = 1 << OUTPUT_TRANSFORM_MATRIX_SHIFT,
-
-            INPUT_TF_SHIFT = 8,
-            INPUT_TF_MASK = 3 << INPUT_TF_SHIFT,
-            INPUT_TF_LINEAR = 0 << INPUT_TF_SHIFT,
-            INPUT_TF_SRGB = 1 << INPUT_TF_SHIFT,
-            INPUT_TF_ST2084 = 2 << INPUT_TF_SHIFT,
-            INPUT_TF_HLG = 3 << INPUT_TF_SHIFT,
-
-            OUTPUT_TF_SHIFT = 10,
-            OUTPUT_TF_MASK = 3 << OUTPUT_TF_SHIFT,
-            OUTPUT_TF_LINEAR = 0 << OUTPUT_TF_SHIFT,
-            OUTPUT_TF_SRGB = 1 << OUTPUT_TF_SHIFT,
-            OUTPUT_TF_ST2084 = 2 << OUTPUT_TF_SHIFT,
-            OUTPUT_TF_HLG = 3 << OUTPUT_TF_SHIFT,
-
-            SHADOW_SHIFT = 13,
-            SHADOW_MASK = 1 << SHADOW_SHIFT,
-            SHADOW_OFF = 0 << SHADOW_SHIFT,
-            SHADOW_ON = 1 << SHADOW_SHIFT,
-
-            DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT = 14,
-            DISPLAY_COLOR_TRANSFORM_MATRIX_MASK = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
-            DISPLAY_COLOR_TRANSFORM_MATRIX_OFF = 0 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
-            DISPLAY_COLOR_TRANSFORM_MATRIX_ON = 1 << DISPLAY_COLOR_TRANSFORM_MATRIX_SHIFT,
-        };
-
-        inline Key() : mKey(0) {}
-        inline Key(const Key& rhs) : mKey(rhs.mKey) {}
-
-        inline Key& set(key_t mask, key_t value) {
-            mKey = (mKey & ~mask) | value;
-            return *this;
-        }
-
-        inline bool isTexturing() const { return (mKey & TEXTURE_MASK) != TEXTURE_OFF; }
-        inline bool hasTextureCoords() const { return isTexturing() && !drawShadows(); }
-        inline int getTextureTarget() const { return (mKey & TEXTURE_MASK); }
-        inline bool isPremultiplied() const { return (mKey & BLEND_MASK) == BLEND_PREMULT; }
-        inline bool isOpaque() const { return (mKey & OPACITY_MASK) == OPACITY_OPAQUE; }
-        inline bool hasAlpha() const { return (mKey & ALPHA_MASK) == ALPHA_LT_ONE; }
-        inline bool hasRoundedCorners() const {
-            return (mKey & ROUNDED_CORNERS_MASK) == ROUNDED_CORNERS_ON;
-        }
-        inline bool drawShadows() const { return (mKey & SHADOW_MASK) == SHADOW_ON; }
-        inline bool hasInputTransformMatrix() const {
-            return (mKey & INPUT_TRANSFORM_MATRIX_MASK) == INPUT_TRANSFORM_MATRIX_ON;
-        }
-        inline bool hasOutputTransformMatrix() const {
-            return (mKey & OUTPUT_TRANSFORM_MATRIX_MASK) == OUTPUT_TRANSFORM_MATRIX_ON;
-        }
-        inline bool hasDisplayColorMatrix() const {
-            return (mKey & DISPLAY_COLOR_TRANSFORM_MATRIX_MASK) ==
-                    DISPLAY_COLOR_TRANSFORM_MATRIX_ON;
-        }
-        inline bool hasTransformMatrix() const {
-            return hasInputTransformMatrix() || hasOutputTransformMatrix();
-        }
-        inline int getInputTF() const { return (mKey & INPUT_TF_MASK); }
-        inline int getOutputTF() const { return (mKey & OUTPUT_TF_MASK); }
-
-        // When HDR and non-HDR contents are mixed, or different types of HDR contents are
-        // mixed, we will do a tone mapping process to tone map the input content to output
-        // content. Currently, the following conversions handled, they are:
-        // * SDR -> HLG
-        // * SDR -> PQ
-        // * HLG -> PQ
-        inline bool needsToneMapping() const {
-            int inputTF = getInputTF();
-            int outputTF = getOutputTF();
-
-            // Return false when converting from SDR to SDR.
-            if (inputTF == Key::INPUT_TF_SRGB && outputTF == Key::OUTPUT_TF_LINEAR) {
-                return false;
-            }
-            if (inputTF == Key::INPUT_TF_LINEAR && outputTF == Key::OUTPUT_TF_SRGB) {
-                return false;
-            }
-
-            inputTF >>= Key::INPUT_TF_SHIFT;
-            outputTF >>= Key::OUTPUT_TF_SHIFT;
-            return inputTF != outputTF;
-        }
-
-        // for use by std::unordered_map
-
-        bool operator==(const Key& other) const { return mKey == other.mKey; }
-
-        struct Hash {
-            size_t operator()(const Key& key) const { return static_cast<size_t>(key.mKey); }
-        };
-    };
-
-    ProgramCache() = default;
-    ~ProgramCache() = default;
-
-    // Generate shaders to populate the cache
-    void primeCache(const EGLContext context, bool toneMapperShaderOnly);
-
-    size_t getSize(const EGLContext context) { return mCaches[context].size(); }
-
-    // useProgram lookup a suitable program in the cache or generates one
-    // if none can be found.
-    void useProgram(const EGLContext context, const Description& description);
-
-    void purgeCaches() { mCaches.clear(); }
-
-private:
-    // compute a cache Key from a Description
-    static Key computeKey(const Description& description);
-    // Generate EOTF based from Key.
-    static void generateEOTF(Formatter& fs, const Key& needs);
-    // Generate necessary tone mapping methods for OOTF.
-    static void generateToneMappingProcess(Formatter& fs, const Key& needs);
-    // Generate OOTF based from Key.
-    static void generateOOTF(Formatter& fs, const Key& needs);
-    // Generate OETF based from Key.
-    static void generateOETF(Formatter& fs, const Key& needs);
-    // generates a program from the Key
-    static std::unique_ptr<Program> generateProgram(const Key& needs);
-    // generates the vertex shader from the Key
-    static String8 generateVertexShader(const Key& needs);
-    // generates the fragment shader from the Key
-    static String8 generateFragmentShader(const Key& needs);
-
-    // Key/Value map used for caching Programs. Currently the cache
-    // is never shrunk (and the GL program objects are never deleted).
-    std::unordered_map<EGLContext, std::unordered_map<Key, std::unique_ptr<Program>, Key::Hash>>
-            mCaches;
-};
-
-} // namespace gl
-} // namespace renderengine
-
-ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
-
-} // namespace android
-
-#endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */
diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp
deleted file mode 100644
index 3455e08..0000000
--- a/libs/renderengine/gl/filters/BlurFilter.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "BlurFilter.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-#include <ui/GraphicTypes.h>
-#include <cstdint>
-
-#include <utils/Trace.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-BlurFilter::BlurFilter(GLESRenderEngine& engine)
-      : mEngine(engine),
-        mCompositionFbo(engine),
-        mPingFbo(engine),
-        mPongFbo(engine),
-        mMixProgram(engine),
-        mBlurProgram(engine) {
-    mMixProgram.compile(getVertexShader(), getMixFragShader());
-    mMPosLoc = mMixProgram.getAttributeLocation("aPosition");
-    mMUvLoc = mMixProgram.getAttributeLocation("aUV");
-    mMTextureLoc = mMixProgram.getUniformLocation("uTexture");
-    mMCompositionTextureLoc = mMixProgram.getUniformLocation("uCompositionTexture");
-    mMMixLoc = mMixProgram.getUniformLocation("uMix");
-
-    mBlurProgram.compile(getVertexShader(), getFragmentShader());
-    mBPosLoc = mBlurProgram.getAttributeLocation("aPosition");
-    mBUvLoc = mBlurProgram.getAttributeLocation("aUV");
-    mBTextureLoc = mBlurProgram.getUniformLocation("uTexture");
-    mBOffsetLoc = mBlurProgram.getUniformLocation("uOffset");
-
-    static constexpr auto size = 2.0f;
-    static constexpr auto translation = 1.0f;
-    const GLfloat vboData[] = {
-        // Vertex data
-        translation - size, -translation - size,
-        translation - size, -translation + size,
-        translation + size, -translation + size,
-        // UV data
-        0.0f, 0.0f - translation,
-        0.0f, size - translation,
-        size, size - translation
-    };
-    mMeshBuffer.allocateBuffers(vboData, 12 /* size */);
-}
-
-status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display, uint32_t radius) {
-    ATRACE_NAME("BlurFilter::setAsDrawTarget");
-    mRadius = radius;
-    mDisplayX = display.physicalDisplay.left;
-    mDisplayY = display.physicalDisplay.top;
-
-    if (mDisplayWidth < display.physicalDisplay.width() ||
-        mDisplayHeight < display.physicalDisplay.height()) {
-        ATRACE_NAME("BlurFilter::allocatingTextures");
-
-        mDisplayWidth = display.physicalDisplay.width();
-        mDisplayHeight = display.physicalDisplay.height();
-        mCompositionFbo.allocateBuffers(mDisplayWidth, mDisplayHeight);
-
-        const uint32_t fboWidth = floorf(mDisplayWidth * kFboScale);
-        const uint32_t fboHeight = floorf(mDisplayHeight * kFboScale);
-        mPingFbo.allocateBuffers(fboWidth, fboHeight);
-        mPongFbo.allocateBuffers(fboWidth, fboHeight);
-
-        if (mPingFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
-            ALOGE("Invalid ping buffer");
-            return mPingFbo.getStatus();
-        }
-        if (mPongFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
-            ALOGE("Invalid pong buffer");
-            return mPongFbo.getStatus();
-        }
-        if (mCompositionFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
-            ALOGE("Invalid composition buffer");
-            return mCompositionFbo.getStatus();
-        }
-        if (!mBlurProgram.isValid()) {
-            ALOGE("Invalid shader");
-            return GL_INVALID_OPERATION;
-        }
-    }
-
-    mCompositionFbo.bind();
-    glViewport(0, 0, mCompositionFbo.getBufferWidth(), mCompositionFbo.getBufferHeight());
-    return NO_ERROR;
-}
-
-void BlurFilter::drawMesh(GLuint uv, GLuint position) {
-
-    glEnableVertexAttribArray(uv);
-    glEnableVertexAttribArray(position);
-    mMeshBuffer.bind();
-    glVertexAttribPointer(position, 2 /* size */, GL_FLOAT, GL_FALSE,
-                          2 * sizeof(GLfloat) /* stride */, 0 /* offset */);
-    glVertexAttribPointer(uv, 2 /* size */, GL_FLOAT, GL_FALSE, 0 /* stride */,
-                          (GLvoid*)(6 * sizeof(GLfloat)) /* offset */);
-    mMeshBuffer.unbind();
-
-    // draw mesh
-    glDrawArrays(GL_TRIANGLES, 0 /* first */, 3 /* count */);
-}
-
-status_t BlurFilter::prepare() {
-    ATRACE_NAME("BlurFilter::prepare");
-
-    // Kawase is an approximation of Gaussian, but it behaves differently from it.
-    // A radius transformation is required for approximating them, and also to introduce
-    // non-integer steps, necessary to smoothly interpolate large radii.
-    const auto radius = mRadius / 6.0f;
-
-    // Calculate how many passes we'll do, based on the radius.
-    // Too many passes will make the operation expensive.
-    const auto passes = min(kMaxPasses, (uint32_t)ceil(radius));
-
-    const float radiusByPasses = radius / (float)passes;
-    const float stepX = radiusByPasses / (float)mCompositionFbo.getBufferWidth();
-    const float stepY = radiusByPasses / (float)mCompositionFbo.getBufferHeight();
-
-    // Let's start by downsampling and blurring the composited frame simultaneously.
-    mBlurProgram.useProgram();
-    glActiveTexture(GL_TEXTURE0);
-    glUniform1i(mBTextureLoc, 0);
-    glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
-    glUniform2f(mBOffsetLoc, stepX, stepY);
-    glViewport(0, 0, mPingFbo.getBufferWidth(), mPingFbo.getBufferHeight());
-    mPingFbo.bind();
-    drawMesh(mBUvLoc, mBPosLoc);
-
-    // And now we'll ping pong between our textures, to accumulate the result of various offsets.
-    GLFramebuffer* read = &mPingFbo;
-    GLFramebuffer* draw = &mPongFbo;
-    glViewport(0, 0, draw->getBufferWidth(), draw->getBufferHeight());
-    for (auto i = 1; i < passes; i++) {
-        ATRACE_NAME("BlurFilter::renderPass");
-        draw->bind();
-
-        glBindTexture(GL_TEXTURE_2D, read->getTextureName());
-        glUniform2f(mBOffsetLoc, stepX * i, stepY * i);
-
-        drawMesh(mBUvLoc, mBPosLoc);
-
-        // Swap buffers for next iteration
-        auto tmp = draw;
-        draw = read;
-        read = tmp;
-    }
-    mLastDrawTarget = read;
-
-    return NO_ERROR;
-}
-
-status_t BlurFilter::render(bool multiPass) {
-    ATRACE_NAME("BlurFilter::render");
-
-    // Now let's scale our blur up. It will be interpolated with the larger composited
-    // texture for the first frames, to hide downscaling artifacts.
-    GLfloat mix = fmin(1.0, mRadius / kMaxCrossFadeRadius);
-
-    // When doing multiple passes, we cannot try to read mCompositionFbo, given that we'll
-    // be writing onto it. Let's disable the crossfade, otherwise we'd need 1 extra frame buffer,
-    // as large as the screen size.
-    if (mix >= 1 || multiPass) {
-        mLastDrawTarget->bindAsReadBuffer();
-        glBlitFramebuffer(0, 0, mLastDrawTarget->getBufferWidth(),
-                          mLastDrawTarget->getBufferHeight(), mDisplayX, mDisplayY, mDisplayWidth,
-                          mDisplayHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
-        return NO_ERROR;
-    }
-
-    mMixProgram.useProgram();
-    glUniform1f(mMMixLoc, mix);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, mLastDrawTarget->getTextureName());
-    glUniform1i(mMTextureLoc, 0);
-    glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
-    glUniform1i(mMCompositionTextureLoc, 1);
-
-    drawMesh(mMUvLoc, mMPosLoc);
-
-    glUseProgram(0);
-    glActiveTexture(GL_TEXTURE0);
-    mEngine.checkErrors("Drawing blur mesh");
-    return NO_ERROR;
-}
-
-string BlurFilter::getVertexShader() const {
-    return R"SHADER(#version 300 es
-        precision mediump float;
-
-        in vec2 aPosition;
-        in highp vec2 aUV;
-        out highp vec2 vUV;
-
-        void main() {
-            vUV = aUV;
-            gl_Position = vec4(aPosition, 0.0, 1.0);
-        }
-    )SHADER";
-}
-
-string BlurFilter::getFragmentShader() const {
-    return R"SHADER(#version 300 es
-        precision mediump float;
-
-        uniform sampler2D uTexture;
-        uniform vec2 uOffset;
-
-        in highp vec2 vUV;
-        out vec4 fragColor;
-
-        void main() {
-            fragColor  = texture(uTexture, vUV, 0.0);
-            fragColor += texture(uTexture, vUV + vec2( uOffset.x,  uOffset.y), 0.0);
-            fragColor += texture(uTexture, vUV + vec2( uOffset.x, -uOffset.y), 0.0);
-            fragColor += texture(uTexture, vUV + vec2(-uOffset.x,  uOffset.y), 0.0);
-            fragColor += texture(uTexture, vUV + vec2(-uOffset.x, -uOffset.y), 0.0);
-
-            fragColor = vec4(fragColor.rgb * 0.2, 1.0);
-        }
-    )SHADER";
-}
-
-string BlurFilter::getMixFragShader() const {
-    string shader = R"SHADER(#version 300 es
-        precision mediump float;
-
-        in highp vec2 vUV;
-        out vec4 fragColor;
-
-        uniform sampler2D uCompositionTexture;
-        uniform sampler2D uTexture;
-        uniform float uMix;
-
-        void main() {
-            vec4 blurred = texture(uTexture, vUV);
-            vec4 composition = texture(uCompositionTexture, vUV);
-            fragColor = mix(composition, blurred, uMix);
-        }
-    )SHADER";
-    return shader;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h
deleted file mode 100644
index 593a8fd..0000000
--- a/libs/renderengine/gl/filters/BlurFilter.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2019 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
-
-#include <ui/GraphicTypes.h>
-#include "../GLESRenderEngine.h"
-#include "../GLFramebuffer.h"
-#include "../GLVertexBuffer.h"
-#include "GenericProgram.h"
-
-using namespace std;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-/**
- * This is an implementation of a Kawase blur, as described in here:
- * https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/
- * 00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_notes.pdf
- */
-class BlurFilter {
-public:
-    // Downsample FBO to improve performance
-    static constexpr float kFboScale = 0.25f;
-    // Maximum number of render passes
-    static constexpr uint32_t kMaxPasses = 4;
-    // To avoid downscaling artifacts, we interpolate the blurred fbo with the full composited
-    // image, up to this radius.
-    static constexpr float kMaxCrossFadeRadius = 30.0f;
-
-    explicit BlurFilter(GLESRenderEngine& engine);
-    virtual ~BlurFilter(){};
-
-    // Set up render targets, redirecting output to offscreen texture.
-    status_t setAsDrawTarget(const DisplaySettings&, uint32_t radius);
-    // Execute blur passes, rendering to offscreen texture.
-    status_t prepare();
-    // Render blur to the bound framebuffer (screen).
-    status_t render(bool multiPass);
-
-private:
-    uint32_t mRadius;
-    void drawMesh(GLuint uv, GLuint position);
-    string getVertexShader() const;
-    string getFragmentShader() const;
-    string getMixFragShader() const;
-
-    GLESRenderEngine& mEngine;
-    // Frame buffer holding the composited background.
-    GLFramebuffer mCompositionFbo;
-    // Frame buffers holding the blur passes.
-    GLFramebuffer mPingFbo;
-    GLFramebuffer mPongFbo;
-    uint32_t mDisplayWidth = 0;
-    uint32_t mDisplayHeight = 0;
-    uint32_t mDisplayX = 0;
-    uint32_t mDisplayY = 0;
-    // Buffer holding the final blur pass.
-    GLFramebuffer* mLastDrawTarget;
-
-    // VBO containing vertex and uv data of a fullscreen triangle.
-    GLVertexBuffer mMeshBuffer;
-
-    GenericProgram mMixProgram;
-    GLuint mMPosLoc;
-    GLuint mMUvLoc;
-    GLuint mMMixLoc;
-    GLuint mMTextureLoc;
-    GLuint mMCompositionTextureLoc;
-
-    GenericProgram mBlurProgram;
-    GLuint mBPosLoc;
-    GLuint mBUvLoc;
-    GLuint mBTextureLoc;
-    GLuint mBOffsetLoc;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/filters/GenericProgram.cpp b/libs/renderengine/gl/filters/GenericProgram.cpp
deleted file mode 100644
index bb35889..0000000
--- a/libs/renderengine/gl/filters/GenericProgram.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#include "GenericProgram.h"
-
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GenericProgram::GenericProgram(GLESRenderEngine& engine) : mEngine(engine) {}
-
-GenericProgram::~GenericProgram() {
-    if (mVertexShaderHandle != 0) {
-        if (mProgramHandle != 0) {
-            glDetachShader(mProgramHandle, mVertexShaderHandle);
-        }
-        glDeleteShader(mVertexShaderHandle);
-    }
-
-    if (mFragmentShaderHandle != 0) {
-        if (mProgramHandle != 0) {
-            glDetachShader(mProgramHandle, mFragmentShaderHandle);
-        }
-        glDeleteShader(mFragmentShaderHandle);
-    }
-
-    if (mProgramHandle != 0) {
-        glDeleteProgram(mProgramHandle);
-    }
-}
-
-void GenericProgram::compile(string vertexShader, string fragmentShader) {
-    mVertexShaderHandle = compileShader(GL_VERTEX_SHADER, vertexShader);
-    mFragmentShaderHandle = compileShader(GL_FRAGMENT_SHADER, fragmentShader);
-    if (mVertexShaderHandle == 0 || mFragmentShaderHandle == 0) {
-        ALOGE("Aborting program creation.");
-        return;
-    }
-    mProgramHandle = createAndLink(mVertexShaderHandle, mFragmentShaderHandle);
-    mEngine.checkErrors("Linking program");
-}
-
-void GenericProgram::useProgram() const {
-    glUseProgram(mProgramHandle);
-}
-
-GLuint GenericProgram::compileShader(GLuint type, string src) const {
-    const GLuint shader = glCreateShader(type);
-    if (shader == 0) {
-        mEngine.checkErrors("Creating shader");
-        return 0;
-    }
-    const GLchar* charSrc = (const GLchar*)src.c_str();
-    glShaderSource(shader, 1, &charSrc, nullptr);
-    glCompileShader(shader);
-
-    GLint isCompiled = 0;
-    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
-    if (isCompiled == GL_FALSE) {
-        GLint maxLength = 0;
-        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
-        string errorLog;
-        errorLog.reserve(maxLength);
-        glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data());
-        glDeleteShader(shader);
-        ALOGE("Error compiling shader: %s", errorLog.c_str());
-        return 0;
-    }
-    return shader;
-}
-GLuint GenericProgram::createAndLink(GLuint vertexShader, GLuint fragmentShader) const {
-    const GLuint program = glCreateProgram();
-    mEngine.checkErrors("Creating program");
-
-    glAttachShader(program, vertexShader);
-    glAttachShader(program, fragmentShader);
-    glLinkProgram(program);
-    mEngine.checkErrors("Linking program");
-    return program;
-}
-
-GLuint GenericProgram::getUniformLocation(const string name) const {
-    if (mProgramHandle == 0) {
-        ALOGE("Can't get location of %s on an invalid program.", name.c_str());
-        return -1;
-    }
-    return glGetUniformLocation(mProgramHandle, (const GLchar*)name.c_str());
-}
-
-GLuint GenericProgram::getAttributeLocation(const string name) const {
-    if (mProgramHandle == 0) {
-        ALOGE("Can't get location of %s on an invalid program.", name.c_str());
-        return -1;
-    }
-    return glGetAttribLocation(mProgramHandle, (const GLchar*)name.c_str());
-}
-
-bool GenericProgram::isValid() const {
-    return mProgramHandle != 0;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/filters/GenericProgram.h b/libs/renderengine/gl/filters/GenericProgram.h
deleted file mode 100644
index 6da2a5a..0000000
--- a/libs/renderengine/gl/filters/GenericProgram.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2019 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
-
-#include <ui/GraphicTypes.h>
-#include "../GLESRenderEngine.h"
-#include "../GLFramebuffer.h"
-
-using namespace std;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GenericProgram {
-public:
-    explicit GenericProgram(GLESRenderEngine& renderEngine);
-    ~GenericProgram();
-    void compile(string vertexShader, string fragmentShader);
-    bool isValid() const;
-    void useProgram() const;
-    GLuint getAttributeLocation(const string name) const;
-    GLuint getUniformLocation(const string name) const;
-
-private:
-    GLuint compileShader(GLuint type, const string src) const;
-    GLuint createAndLink(GLuint vertexShader, GLuint fragmentShader) const;
-
-    GLESRenderEngine& mEngine;
-    GLuint mVertexShaderHandle = 0;
-    GLuint mFragmentShaderHandle = 0;
-    GLuint mProgramHandle = 0;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/Framebuffer.h b/libs/renderengine/include/renderengine/Framebuffer.h
deleted file mode 100644
index 6511127..0000000
--- a/libs/renderengine/include/renderengine/Framebuffer.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <cstdint>
-
-struct ANativeWindowBuffer;
-
-namespace android {
-namespace renderengine {
-
-class Framebuffer {
-public:
-    virtual ~Framebuffer() = default;
-
-    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
-                                       const bool useFramebufferCache) = 0;
-};
-
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index b501c40..28aa4dd 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -46,10 +46,6 @@
     // Fence that will fire when the buffer is ready to be bound.
     sp<Fence> fence = nullptr;
 
-    // Texture identifier to bind the external texture to.
-    // TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
-    uint32_t textureName = 0;
-
     // Whether to use filtering when rendering the texture.
     bool useTextureFiltering = false;
 
@@ -182,7 +178,6 @@
 // compositionengine/impl/ClientCompositionRequestCache.cpp
 static inline bool operator==(const Buffer& lhs, const Buffer& rhs) {
     return lhs.buffer == rhs.buffer && lhs.fence == rhs.fence &&
-            lhs.textureName == rhs.textureName &&
             lhs.useTextureFiltering == rhs.useTextureFiltering &&
             lhs.textureTransform == rhs.textureTransform &&
             lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha &&
@@ -237,7 +232,6 @@
         << (settings.buffer.get() ? decodePixelFormat(settings.buffer->getPixelFormat()).c_str()
                                   : "");
     *os << "\n    .fence = " << settings.fence.get();
-    *os << "\n    .textureName = " << settings.textureName;
     *os << "\n    .useTextureFiltering = " << settings.useTextureFiltering;
     *os << "\n    .textureTransform = ";
     PrintMatrix(settings.textureTransform, os);
diff --git a/libs/renderengine/include/renderengine/Mesh.h b/libs/renderengine/include/renderengine/Mesh.h
deleted file mode 100644
index 167f13f..0000000
--- a/libs/renderengine/include/renderengine/Mesh.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_RENDER_ENGINE_MESH_H
-#define SF_RENDER_ENGINE_MESH_H
-
-#include <vector>
-
-#include <stdint.h>
-
-namespace android {
-namespace renderengine {
-
-class Mesh {
-public:
-    class Builder;
-
-    enum Primitive {
-        TRIANGLES = 0x0004,      // GL_TRIANGLES
-        TRIANGLE_STRIP = 0x0005, // GL_TRIANGLE_STRIP
-        TRIANGLE_FAN = 0x0006    // GL_TRIANGLE_FAN
-    };
-
-    ~Mesh() = default;
-
-    /*
-     * VertexArray handles the stride automatically.
-     */
-    template <typename TYPE>
-    class VertexArray {
-        friend class Mesh;
-        float* mData;
-        size_t mStride;
-        size_t mOffset = 0;
-        VertexArray(float* data, size_t stride) : mData(data), mStride(stride) {}
-
-    public:
-        // Returns a vertex array at an offset so its easier to append attributes from
-        // multiple sources.
-        VertexArray(VertexArray<TYPE>& other, size_t offset)
-              : mData(other.mData), mStride(other.mStride), mOffset(offset) {}
-
-        TYPE& operator[](size_t index) {
-            return *reinterpret_cast<TYPE*>(&mData[(index + mOffset) * mStride]);
-        }
-        TYPE const& operator[](size_t index) const {
-            return *reinterpret_cast<TYPE const*>(&mData[(index + mOffset) * mStride]);
-        }
-    };
-
-    template <typename TYPE>
-    VertexArray<TYPE> getPositionArray() {
-        return VertexArray<TYPE>(getPositions(), mStride);
-    }
-
-    template <typename TYPE>
-    VertexArray<TYPE> getTexCoordArray() {
-        return VertexArray<TYPE>(getTexCoords(), mStride);
-    }
-
-    template <typename TYPE>
-    VertexArray<TYPE> getCropCoordArray() {
-        return VertexArray<TYPE>(getCropCoords(), mStride);
-    }
-
-    template <typename TYPE>
-    VertexArray<TYPE> getShadowColorArray() {
-        return VertexArray<TYPE>(getShadowColor(), mStride);
-    }
-
-    template <typename TYPE>
-    VertexArray<TYPE> getShadowParamsArray() {
-        return VertexArray<TYPE>(getShadowParams(), mStride);
-    }
-
-    uint16_t* getIndicesArray() { return getIndices(); }
-
-    Primitive getPrimitive() const;
-
-    // returns a pointer to the vertices positions
-    float const* getPositions() const;
-
-    // returns a pointer to the vertices texture coordinates
-    float const* getTexCoords() const;
-
-    // returns a pointer to the vertices crop coordinates
-    float const* getCropCoords() const;
-
-    // returns a pointer to colors
-    float const* getShadowColor() const;
-
-    // returns a pointer to the shadow params
-    float const* getShadowParams() const;
-
-    // returns a pointer to indices
-    uint16_t const* getIndices() const;
-
-    // number of vertices in this mesh
-    size_t getVertexCount() const;
-
-    // dimension of vertices
-    size_t getVertexSize() const;
-
-    // dimension of texture coordinates
-    size_t getTexCoordsSize() const;
-
-    size_t getShadowParamsSize() const;
-
-    size_t getShadowColorSize() const;
-
-    size_t getIndexCount() const;
-
-    // return stride in bytes
-    size_t getByteStride() const;
-
-    // return stride in floats
-    size_t getStride() const;
-
-private:
-    Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize,
-         size_t cropCoordsSize, size_t shadowColorSize, size_t shadowParamsSize, size_t indexCount);
-    Mesh(const Mesh&);
-    Mesh& operator=(const Mesh&);
-    Mesh const& operator=(const Mesh&) const;
-
-    float* getPositions();
-    float* getTexCoords();
-    float* getCropCoords();
-    float* getShadowColor();
-    float* getShadowParams();
-    uint16_t* getIndices();
-
-    std::vector<float> mVertices;
-    size_t mVertexCount;
-    size_t mVertexSize;
-    size_t mTexCoordsSize;
-    size_t mCropCoordsSize;
-    size_t mShadowColorSize;
-    size_t mShadowParamsSize;
-    size_t mStride;
-    Primitive mPrimitive;
-    std::vector<uint16_t> mIndices;
-    size_t mIndexCount;
-};
-
-class Mesh::Builder {
-public:
-    Builder& setPrimitive(Primitive primitive) {
-        mPrimitive = primitive;
-        return *this;
-    };
-    Builder& setVertices(size_t vertexCount, size_t vertexSize) {
-        mVertexCount = vertexCount;
-        mVertexSize = vertexSize;
-        return *this;
-    };
-    Builder& setTexCoords(size_t texCoordsSize) {
-        mTexCoordsSize = texCoordsSize;
-        return *this;
-    };
-    Builder& setCropCoords(size_t cropCoordsSize) {
-        mCropCoordsSize = cropCoordsSize;
-        return *this;
-    };
-    Builder& setShadowAttrs() {
-        mShadowParamsSize = 3;
-        mShadowColorSize = 4;
-        return *this;
-    };
-    Builder& setIndices(size_t indexCount) {
-        mIndexCount = indexCount;
-        return *this;
-    };
-    Mesh build() const {
-        return Mesh{mPrimitive,      mVertexCount,     mVertexSize,       mTexCoordsSize,
-                    mCropCoordsSize, mShadowColorSize, mShadowParamsSize, mIndexCount};
-    }
-
-private:
-    size_t mVertexCount = 0;
-    size_t mVertexSize = 0;
-    size_t mTexCoordsSize = 0;
-    size_t mCropCoordsSize = 0;
-    size_t mShadowColorSize = 0;
-    size_t mShadowParamsSize = 0;
-    size_t mIndexCount = 0;
-    Primitive mPrimitive;
-};
-
-} // namespace renderengine
-} // namespace android
-#endif /* SF_RENDER_ENGINE_MESH_H */
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 83af252..80aa4c6 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -22,8 +22,6 @@
 #include <math/mat4.h>
 #include <renderengine/DisplaySettings.h>
 #include <renderengine/ExternalTexture.h>
-#include <renderengine/Framebuffer.h>
-#include <renderengine/Image.h>
 #include <renderengine/LayerSettings.h>
 #include <stdint.h>
 #include <sys/types.h>
@@ -95,8 +93,6 @@
     };
 
     enum class RenderEngineType {
-        GLES = 1,
-        THREADED = 2,
         SKIA_GL = 3,
         SKIA_GL_THREADED = 4,
         SKIA_VK = 5,
@@ -116,9 +112,6 @@
     // dump the extension strings. always call the base class.
     virtual void dump(std::string& result) = 0;
 
-    virtual void genTextures(size_t count, uint32_t* names) = 0;
-    virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
-
     // queries that are required to be thread safe
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
@@ -171,8 +164,6 @@
     // being drawn, then the implementation is free to silently ignore this call.
     virtual void cleanupPostRender() = 0;
 
-    virtual void cleanFramebufferCache() = 0;
-
     // Returns the priority this context was actually created with. Note: this
     // may not be the same as specified at context creation time, due to
     // implementation limits on the number of contexts that can be created at a
@@ -204,7 +195,7 @@
     virtual void setEnableTracing(bool /*tracingEnabled*/) {}
 
 protected:
-    RenderEngine() : RenderEngine(RenderEngineType::GLES) {}
+    RenderEngine() : RenderEngine(RenderEngineType::SKIA_GL) {}
 
     RenderEngine(RenderEngineType type) : mRenderEngineType(type) {}
 
diff --git a/libs/renderengine/include/renderengine/Texture.h b/libs/renderengine/include/renderengine/Texture.h
deleted file mode 100644
index c69ace0..0000000
--- a/libs/renderengine/include/renderengine/Texture.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_RENDER_ENGINE_TEXTURE_H
-#define SF_RENDER_ENGINE_TEXTURE_H
-
-#include <stdint.h>
-
-#include <math/mat4.h>
-
-namespace android {
-namespace renderengine {
-
-class Texture {
-public:
-    enum Target { TEXTURE_2D = 0x0DE1, TEXTURE_EXTERNAL = 0x8D65 };
-
-    Texture();
-    Texture(Target textureTarget, uint32_t textureName);
-    ~Texture();
-
-    void init(Target textureTarget, uint32_t textureName);
-
-    void setMatrix(float const* matrix);
-    void setFiltering(bool enabled);
-    void setDimensions(size_t width, size_t height);
-
-    uint32_t getTextureName() const;
-    uint32_t getTextureTarget() const;
-
-    const mat4& getMatrix() const;
-    bool getFiltering() const;
-    size_t getWidth() const;
-    size_t getHeight() const;
-
-private:
-    uint32_t mTextureName;
-    uint32_t mTextureTarget;
-    size_t mWidth;
-    size_t mHeight;
-    bool mFiltering;
-    mat4 mTextureMatrix;
-};
-
-} // namespace renderengine
-} // namespace android
-#endif /* SF_RENDER_ENGINE_TEXTURE_H */
diff --git a/libs/renderengine/include/renderengine/mock/Framebuffer.h b/libs/renderengine/include/renderengine/mock/Framebuffer.h
deleted file mode 100644
index dfb6a4e..0000000
--- a/libs/renderengine/include/renderengine/mock/Framebuffer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <gmock/gmock.h>
-#include <renderengine/Framebuffer.h>
-
-namespace android {
-namespace renderengine {
-namespace mock {
-
-class Framebuffer : public renderengine::Framebuffer {
-public:
-    Framebuffer();
-    ~Framebuffer() override;
-
-    MOCK_METHOD3(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool, const bool));
-};
-
-} // namespace mock
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/mock/Image.h b/libs/renderengine/include/renderengine/mock/Image.h
deleted file mode 100644
index 2b0eed1..0000000
--- a/libs/renderengine/include/renderengine/mock/Image.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <gmock/gmock.h>
-#include <renderengine/Image.h>
-
-namespace android {
-namespace renderengine {
-namespace mock {
-
-class Image : public renderengine::Image {
-public:
-    Image();
-    ~Image() override;
-
-    MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer* buffer, bool isProtected));
-};
-
-} // namespace mock
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index d3035e2..7881190 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -19,9 +19,7 @@
 #include <gmock/gmock.h>
 #include <renderengine/DisplaySettings.h>
 #include <renderengine/LayerSettings.h>
-#include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
-#include <renderengine/Texture.h>
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/Region.h>
@@ -37,9 +35,6 @@
 
     MOCK_METHOD0(primeCache, std::future<void>());
     MOCK_METHOD1(dump, void(std::string&));
-    MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
-    MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
-    MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
     MOCK_CONST_METHOD0(getMaxTextureSize, size_t());
     MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
     MOCK_CONST_METHOD0(isProtected, bool());
@@ -55,7 +50,6 @@
                  void(const std::shared_ptr<std::promise<FenceResult>>&&, const DisplaySettings&,
                       const std::vector<LayerSettings>&, const std::shared_ptr<ExternalTexture>&,
                       const bool, base::unique_fd&&));
-    MOCK_METHOD0(cleanFramebufferCache, void());
     MOCK_METHOD0(getContextPriority, int());
     MOCK_METHOD0(supportsBackgroundBlur, bool());
     MOCK_METHOD1(onActiveDisplaySizeChanged, void(ui::Size));
diff --git a/libs/renderengine/include/renderengine/private/Description.h b/libs/renderengine/include/renderengine/private/Description.h
deleted file mode 100644
index 2873ad7..0000000
--- a/libs/renderengine/include/renderengine/private/Description.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2013 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.
- */
-
-#ifndef SF_RENDER_ENGINE_DESCRIPTION_H_
-#define SF_RENDER_ENGINE_DESCRIPTION_H_
-
-#include <renderengine/Texture.h>
-#include <ui/GraphicTypes.h>
-
-namespace android {
-namespace renderengine {
-
-/*
- * This is the structure that holds the state of the rendering engine.
- * This class is used to generate a corresponding GLSL program and set the
- * appropriate uniform.
- */
-struct Description {
-    enum class TransferFunction : int {
-        LINEAR,
-        SRGB,
-        ST2084,
-        HLG, // Hybrid Log-Gamma for HDR.
-    };
-
-    static TransferFunction dataSpaceToTransferFunction(ui::Dataspace dataSpace);
-
-    Description() = default;
-    ~Description() = default;
-
-    bool hasInputTransformMatrix() const;
-    bool hasOutputTransformMatrix() const;
-    bool hasColorMatrix() const;
-    bool hasDisplayColorMatrix() const;
-
-    // whether textures are premultiplied
-    bool isPremultipliedAlpha = false;
-    // whether this layer is marked as opaque
-    bool isOpaque = true;
-
-    // corner radius of the layer
-    float cornerRadius = 0;
-
-    // Size of the rounded rectangle we are cropping to
-    half2 cropSize;
-
-    // Texture this layer uses
-    Texture texture;
-    bool textureEnabled = false;
-
-    // color used when texturing is disabled or when setting alpha.
-    half4 color;
-
-    // transfer functions for the input/output
-    TransferFunction inputTransferFunction = TransferFunction::LINEAR;
-    TransferFunction outputTransferFunction = TransferFunction::LINEAR;
-
-    float displayMaxLuminance;
-    float maxMasteringLuminance;
-    float maxContentLuminance;
-
-    // projection matrix
-    mat4 projectionMatrix;
-
-    // The color matrix will be applied in linear space right before OETF.
-    mat4 colorMatrix;
-    // The display color matrix will be applied in gamma space after OETF
-    mat4 displayColorMatrix;
-    mat4 inputTransformMatrix;
-    mat4 outputTransformMatrix;
-
-    // True if this layer will draw a shadow.
-    bool drawShadows = false;
-};
-
-} // namespace renderengine
-} // namespace android
-
-#endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */
diff --git a/libs/renderengine/mock/Framebuffer.cpp b/libs/renderengine/mock/Framebuffer.cpp
deleted file mode 100644
index fbdcaab..0000000
--- a/libs/renderengine/mock/Framebuffer.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <renderengine/mock/Framebuffer.h>
-
-namespace android {
-namespace renderengine {
-namespace mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
-
-} // namespace mock
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/mock/Image.cpp b/libs/renderengine/mock/Image.cpp
deleted file mode 100644
index 57f4346..0000000
--- a/libs/renderengine/mock/Image.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#include <renderengine/mock/Image.h>
-
-namespace android {
-namespace renderengine {
-namespace mock {
-
-// The Google Mock documentation recommends explicit non-header instantiations
-// for better compile time performance.
-Image::Image() = default;
-Image::~Image() = default;
-
-} // namespace mock
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLExtensions.cpp b/libs/renderengine/skia/GLExtensions.cpp
similarity index 96%
rename from libs/renderengine/gl/GLExtensions.cpp
rename to libs/renderengine/skia/GLExtensions.cpp
index 3dd534e..32da303 100644
--- a/libs/renderengine/gl/GLExtensions.cpp
+++ b/libs/renderengine/skia/GLExtensions.cpp
@@ -23,11 +23,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::GLExtensions)
+ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::skia::GLExtensions)
 
 namespace android {
 namespace renderengine {
-namespace gl {
+namespace skia {
 
 namespace {
 
@@ -134,6 +134,6 @@
     return mEGLExtensions.string();
 }
 
-} // namespace gl
+} // namespace skia
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/gl/GLExtensions.h b/libs/renderengine/skia/GLExtensions.h
similarity index 98%
rename from libs/renderengine/gl/GLExtensions.h
rename to libs/renderengine/skia/GLExtensions.h
index e415ff3..0cb1bda 100644
--- a/libs/renderengine/gl/GLExtensions.h
+++ b/libs/renderengine/skia/GLExtensions.h
@@ -29,7 +29,7 @@
 
 namespace android {
 namespace renderengine {
-namespace gl {
+namespace skia {
 
 class GLExtensions : public Singleton<GLExtensions> {
 public:
@@ -81,7 +81,7 @@
     GLExtensions& operator=(const GLExtensions&);
 };
 
-} // namespace gl
+} // namespace skia
 } // namespace renderengine
 } // namespace android
 
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 92181d8..e253ad5 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -36,17 +36,26 @@
 #include <memory>
 #include <numeric>
 
-#include "../gl/GLExtensions.h"
+#include "GLExtensions.h"
 #include "log/log_main.h"
 
-bool checkGlError(const char* op, int lineNumber);
-
 namespace android {
 namespace renderengine {
 namespace skia {
 
 using base::StringAppendF;
 
+static bool checkGlError(const char* op, int lineNumber) {
+    bool errorFound = false;
+    GLint error = glGetError();
+    while (error != GL_NO_ERROR) {
+        errorFound = true;
+        error = glGetError();
+        ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
+    }
+    return errorFound;
+}
+
 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
                                          EGLint wanted, EGLConfig* outConfig) {
     EGLint numConfigs = -1, n = 0;
@@ -149,7 +158,7 @@
         LOG_ALWAYS_FATAL("eglQueryString(EGL_EXTENSIONS) failed");
     }
 
-    auto& extensions = gl::GLExtensions::getInstance();
+    auto& extensions = GLExtensions::getInstance();
     extensions.initWithEGLStrings(eglVersion, eglExtensions);
 
     // The code assumes that ES2 or later is available if this extension is
@@ -342,8 +351,8 @@
 }
 
 bool SkiaGLRenderEngine::waitGpuFence(base::borrowed_fd fenceFd) {
-    if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
-        !gl::GLExtensions::getInstance().hasWaitSync()) {
+    if (!GLExtensions::getInstance().hasNativeFenceSync() ||
+        !GLExtensions::getInstance().hasWaitSync()) {
         return false;
     }
 
@@ -378,7 +387,7 @@
 
 base::unique_fd SkiaGLRenderEngine::flush() {
     ATRACE_CALL();
-    if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
+    if (!GLExtensions::getInstance().hasNativeFenceSync()) {
         return base::unique_fd();
     }
 
@@ -469,13 +478,13 @@
 
 std::optional<RenderEngine::ContextPriority> SkiaGLRenderEngine::createContextPriority(
         const RenderEngineCreationArgs& args) {
-    if (!gl::GLExtensions::getInstance().hasContextPriority()) {
+    if (!GLExtensions::getInstance().hasContextPriority()) {
         return std::nullopt;
     }
 
     switch (args.contextPriority) {
         case RenderEngine::ContextPriority::REALTIME:
-            if (gl::GLExtensions::getInstance().hasRealtimePriority()) {
+            if (GLExtensions::getInstance().hasRealtimePriority()) {
                 return RenderEngine::ContextPriority::REALTIME;
             } else {
                 ALOGI("Realtime priority unsupported, degrading gracefully to high priority");
@@ -519,7 +528,7 @@
 }
 
 void SkiaGLRenderEngine::appendBackendSpecificInfoToDump(std::string& result) {
-    const gl::GLExtensions& extensions = gl::GLExtensions::getInstance();
+    const GLExtensions& extensions = GLExtensions::getInstance();
     StringAppendF(&result, "\n ------------RE GLES------------\n");
     StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
     StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 2225d5f..4dd5590 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -20,7 +20,6 @@
 
 #include "SkiaRenderEngine.h"
 
-#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <GrBackendSemaphore.h>
 #include <GrContextOptions.h>
 #include <SkBlendMode.h>
@@ -55,13 +54,14 @@
 #include <android-base/stringprintf.h>
 #include <gui/FenceMonitor.h>
 #include <gui/TraceUtils.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
 #include <pthread.h>
 #include <src/core/SkTraceEventCommon.h>
 #include <sync/sync.h>
 #include <ui/BlurRegion.h>
-#include <ui/DataspaceUtils.h>
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/HdrRenderTypeUtils.h>
 #include <utils/Trace.h>
 
 #include <cmath>
@@ -1025,7 +1025,10 @@
             // Most HDR standards require at least 10-bits of color depth for source content, so we
             // can just extract the transfer function rather than dig into precise gralloc layout.
             // Furthermore, we can assume that the only 8-bit target we support is RGBA8888.
-            const bool requiresDownsample = isHdrDataspace(layer.sourceDataspace) &&
+            const bool requiresDownsample =
+                    getHdrRenderType(layer.sourceDataspace,
+                                     std::optional<ui::PixelFormat>(static_cast<ui::PixelFormat>(
+                                             buffer->getPixelFormat()))) != HdrRenderType::SDR &&
                     buffer->getPixelFormat() == PIXEL_FORMAT_RGBA_8888;
             if (layerDimmingRatio <= kDimmingThreshold || requiresDownsample) {
                 paint.setDither(true);
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index 7b4a0a0..d4fc959 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -64,15 +64,12 @@
 
     std::future<void> primeCache() override final;
     void cleanupPostRender() override final;
-    void cleanFramebufferCache() override final{ }
     bool supportsBackgroundBlur() override final {
         return mBlurFilter != nullptr;
     }
     void onActiveDisplaySizeChanged(ui::Size size) override final;
     int reportShadersCompiled();
 
-    virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override final{};
-    virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override final{};
     virtual void setEnableTracing(bool tracingEnabled) override final;
 
     void useProtectedContext(bool useProtectedContext) override;
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 1ad0fa6..5eec305 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -278,9 +278,6 @@
         if (WRITE_BUFFER_TO_FILE_ON_FAILURE && ::testing::Test::HasFailure()) {
             writeBufferToFile("/data/texture_out_");
         }
-        for (uint32_t texName : mTexNames) {
-            mRE->deleteTextures(1, &texName);
-        }
         const ::testing::TestInfo* const test_info =
                 ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
@@ -623,8 +620,6 @@
 
     std::unique_ptr<renderengine::RenderEngine> mRE;
     std::shared_ptr<renderengine::ExternalTexture> mBuffer;
-
-    std::vector<uint32_t> mTexNames;
 };
 
 void RenderEngineTest::initializeRenderEngine() {
@@ -668,9 +663,6 @@
     static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
                           RenderEngineTest* fixture) {
         const auto buf = fixture->allocateSourceBuffer(1, 1);
-        uint32_t texName;
-        fixture->mRE->genTextures(1, &texName);
-        fixture->mTexNames.push_back(texName);
 
         uint8_t* pixels;
         buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -690,7 +682,6 @@
         buf->getBuffer()->unlock();
 
         layer.source.buffer.buffer = buf;
-        layer.source.buffer.textureName = texName;
         layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
         OpaquenessVariant::setOpaqueBit(layer);
     }
@@ -1239,9 +1230,6 @@
     // Here will allocate a checker board texture, but transform texture
     // coordinates so that only the upper left is applied.
     const auto buf = allocateSourceBuffer(2, 2);
-    uint32_t texName;
-    RenderEngineTest::mRE->genTextures(1, &texName);
-    this->mTexNames.push_back(texName);
 
     uint8_t* pixels;
     buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -1262,7 +1250,6 @@
     buf->getBuffer()->unlock();
 
     layer.source.buffer.buffer = buf;
-    layer.source.buffer.textureName = texName;
     // Transform coordinates to only be inside the red quadrant.
     layer.source.buffer.textureTransform = mat4::scale(vec4(0.2f, 0.2f, 1.f, 1.f));
     layer.alpha = 1.0f;
@@ -1288,9 +1275,6 @@
 
     renderengine::LayerSettings layer;
     const auto buf = allocateSourceBuffer(1, 1);
-    uint32_t texName;
-    RenderEngineTest::mRE->genTextures(1, &texName);
-    this->mTexNames.push_back(texName);
 
     uint8_t* pixels;
     buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -1302,7 +1286,6 @@
     buf->getBuffer()->unlock();
 
     layer.source.buffer.buffer = buf;
-    layer.source.buffer.textureName = texName;
     layer.source.buffer.usePremultipliedAlpha = true;
     layer.alpha = 0.5f;
     layer.geometry.boundaries = Rect(1, 1).toFloatRect();
@@ -1327,9 +1310,6 @@
 
     renderengine::LayerSettings layer;
     const auto buf = allocateSourceBuffer(1, 1);
-    uint32_t texName;
-    RenderEngineTest::mRE->genTextures(1, &texName);
-    this->mTexNames.push_back(texName);
 
     uint8_t* pixels;
     buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
@@ -1341,7 +1321,6 @@
     buf->getBuffer()->unlock();
 
     layer.source.buffer.buffer = buf;
-    layer.source.buffer.textureName = texName;
     layer.source.buffer.usePremultipliedAlpha = false;
     layer.alpha = 0.5f;
     layer.geometry.boundaries = Rect(1, 1).toFloatRect();
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index fe3a16d..281a502 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -36,7 +36,7 @@
     void SetUp() override {
         mThreadedRE = renderengine::threaded::RenderEngineThreaded::create(
                 [this]() { return std::unique_ptr<renderengine::RenderEngine>(mRenderEngine); },
-                renderengine::RenderEngine::RenderEngineType::THREADED);
+                renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED);
     }
 
     std::unique_ptr<renderengine::threaded::RenderEngineThreaded> mThreadedRE;
@@ -57,18 +57,6 @@
     mThreadedRE->getContextPriority();
 }
 
-TEST_F(RenderEngineThreadedTest, genTextures) {
-    uint32_t texName;
-    EXPECT_CALL(*mRenderEngine, genTextures(1, &texName));
-    mThreadedRE->genTextures(1, &texName);
-}
-
-TEST_F(RenderEngineThreadedTest, deleteTextures) {
-    uint32_t texName;
-    EXPECT_CALL(*mRenderEngine, deleteTextures(1, &texName));
-    mThreadedRE->deleteTextures(1, &texName);
-}
-
 TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) {
     size_t size = 20;
     EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size));
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 6a1561a..3bc9e6d 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -27,8 +27,6 @@
 #include <processgroup/processgroup.h>
 #include <utils/Trace.h>
 
-#include "gl/GLESRenderEngine.h"
-
 using namespace std::chrono_literals;
 
 namespace android {
@@ -175,46 +173,6 @@
     result.assign(resultFuture.get());
 }
 
-void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
-    ATRACE_CALL();
-    // This is a no-op in SkiaRenderEngine.
-    if (getRenderEngineType() != RenderEngineType::THREADED) {
-        return;
-    }
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::genTextures");
-            instance.genTextures(count, names);
-            resultPromise.set_value();
-        });
-    }
-    mCondition.notify_one();
-    resultFuture.wait();
-}
-
-void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
-    ATRACE_CALL();
-    // This is a no-op in SkiaRenderEngine.
-    if (getRenderEngineType() != RenderEngineType::THREADED) {
-        return;
-    }
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::deleteTextures");
-            instance.deleteTextures(count, names);
-            resultPromise.set_value();
-        });
-    }
-    mCondition.notify_one();
-    resultFuture.wait();
-}
-
 void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
                                                     bool isRenderable) {
     ATRACE_CALL();
@@ -313,20 +271,6 @@
     return resultFuture;
 }
 
-void RenderEngineThreaded::cleanFramebufferCache() {
-    ATRACE_CALL();
-    // This function is designed so it can run asynchronously, so we do not need to wait
-    // for the futures.
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::cleanFramebufferCache");
-            instance.cleanFramebufferCache();
-        });
-    }
-    mCondition.notify_one();
-}
-
 int RenderEngineThreaded::getContextPriority() {
     std::promise<int> resultPromise;
     std::future<int> resultFuture = resultPromise.get_future();
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 6eb108e..a7ecab2 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -46,8 +46,6 @@
 
     void dump(std::string& result) override;
 
-    void genTextures(size_t count, uint32_t* names) override;
-    void deleteTextures(size_t count, uint32_t const* names) override;
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
@@ -60,7 +58,6 @@
                                         const bool useFramebufferCache,
                                         base::unique_fd&& bufferFence) override;
 
-    void cleanFramebufferCache() override;
     int getContextPriority() override;
     bool supportsBackgroundBlur() override;
     void onActiveDisplaySizeChanged(ui::Size size) override;
diff --git a/libs/ui/include_types/ui/DataspaceUtils.h b/libs/ui/include_types/ui/DataspaceUtils.h
deleted file mode 100644
index a461cb4..0000000
--- a/libs/ui/include_types/ui/DataspaceUtils.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 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
-
-#include <ui/GraphicTypes.h>
-
-namespace android {
-
-inline bool isHdrDataspace(ui::Dataspace dataspace) {
-    const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
-
-    return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/libs/ui/include_types/ui/HdrRenderTypeUtils.h b/libs/ui/include_types/ui/HdrRenderTypeUtils.h
new file mode 100644
index 0000000..b0af878
--- /dev/null
+++ b/libs/ui/include_types/ui/HdrRenderTypeUtils.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 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
+
+#include <ui/GraphicTypes.h>
+
+namespace android {
+
+enum class HdrRenderType {
+    SDR,         // just render to SDR
+    DISPLAY_HDR, // HDR by extended brightness
+    GENERIC_HDR  // tonemapped HDR
+};
+
+/***
+ * A helper function to classify how we treat the result based on params.
+ *
+ * @param dataspace the dataspace
+ * @param pixelFormat optional, in case there is no source buffer.
+ * @param hdrSdrRatio default is 1.f, render engine side doesn't take care of it.
+ * @return HdrRenderType
+ */
+inline HdrRenderType getHdrRenderType(ui::Dataspace dataspace,
+                                      std::optional<ui::PixelFormat> pixelFormat,
+                                      float hdrSdrRatio = 1.f) {
+    const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
+    const auto range = dataspace & HAL_DATASPACE_RANGE_MASK;
+
+    if (transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG) {
+        return HdrRenderType::GENERIC_HDR;
+    }
+
+    static const auto BT2020_LINEAR_EXT = static_cast<ui::Dataspace>(HAL_DATASPACE_STANDARD_BT2020 |
+                                                                     HAL_DATASPACE_TRANSFER_LINEAR |
+                                                                     HAL_DATASPACE_RANGE_EXTENDED);
+
+    if ((dataspace == BT2020_LINEAR_EXT || dataspace == ui::Dataspace::V0_SCRGB) &&
+        pixelFormat.has_value() && pixelFormat.value() == ui::PixelFormat::RGBA_FP16) {
+        return HdrRenderType::GENERIC_HDR;
+    }
+
+    // Extended range layer with an hdr/sdr ratio of > 1.01f can "self-promote" to HDR.
+    if (range == HAL_DATASPACE_RANGE_EXTENDED && hdrSdrRatio > 1.01f) {
+        return HdrRenderType::DISPLAY_HDR;
+    }
+
+    return HdrRenderType::SDR;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 831b64d..8ce017d 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -164,9 +164,9 @@
 }
 
 cc_test {
-    name: "DataspaceUtils_test",
+    name: "HdrRenderTypeUtils_test",
     shared_libs: ["libui"],
-    srcs: ["DataspaceUtils_test.cpp"],
+    srcs: ["HdrRenderTypeUtils_test.cpp"],
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/libs/ui/tests/DataspaceUtils_test.cpp b/libs/ui/tests/DataspaceUtils_test.cpp
deleted file mode 100644
index 3e09671..0000000
--- a/libs/ui/tests/DataspaceUtils_test.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "DataspaceUtilsTest"
-
-#include <gtest/gtest.h>
-#include <ui/DataspaceUtils.h>
-
-namespace android {
-
-class DataspaceUtilsTest : public testing::Test {};
-
-TEST_F(DataspaceUtilsTest, isHdrDataspace) {
-    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_HLG));
-    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_ITU_PQ));
-    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_PQ));
-    EXPECT_TRUE(isHdrDataspace(ui::Dataspace::BT2020_HLG));
-
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB_LINEAR));
-    // scRGB defines a very wide gamut but not an expanded luminance range
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB_LINEAR));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SRGB));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_SCRGB));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_JFIF));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_625));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT601_525));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::V0_BT709));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3_LINEAR));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DCI_P3));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3_LINEAR));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_P3));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::ADOBE_RGB));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_LINEAR));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::BT2020_ITU));
-    EXPECT_FALSE(isHdrDataspace(ui::Dataspace::DISPLAY_BT2020));
-}
-
-} // namespace android
diff --git a/libs/ui/tests/HdrRenderTypeUtils_test.cpp b/libs/ui/tests/HdrRenderTypeUtils_test.cpp
new file mode 100644
index 0000000..efe819d
--- /dev/null
+++ b/libs/ui/tests/HdrRenderTypeUtils_test.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "HdrRenderTypeUtilsTest"
+
+#include <gtest/gtest.h>
+#include <ui/HdrRenderTypeUtils.h>
+
+namespace android {
+
+class HdrRenderTypeUtilsTest : public testing::Test {};
+
+TEST_F(HdrRenderTypeUtilsTest, getHdrRenderType) {
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU_HLG, std::nullopt),
+              HdrRenderType::GENERIC_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU_PQ, std::nullopt),
+              HdrRenderType::GENERIC_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_PQ, std::nullopt), HdrRenderType::GENERIC_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_HLG, std::nullopt),
+              HdrRenderType::GENERIC_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB,
+                               std::optional<ui::PixelFormat>(ui::PixelFormat::RGBA_FP16)),
+              HdrRenderType::GENERIC_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB,
+                               std::optional<ui::PixelFormat>(ui::PixelFormat::RGBA_8888), 2.f),
+              HdrRenderType::DISPLAY_HDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB_LINEAR,
+                               std::optional<ui::PixelFormat>(ui::PixelFormat::RGBA_8888), 2.f),
+              HdrRenderType::DISPLAY_HDR);
+
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SRGB_LINEAR, std::nullopt), HdrRenderType::SDR);
+    // scRGB defines a very wide gamut but not an expanded luminance range
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB_LINEAR, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SCRGB, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_SRGB, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_JFIF, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT601_625, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT601_525, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::V0_BT709, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::DCI_P3_LINEAR, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::DCI_P3, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_P3_LINEAR, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_P3, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::ADOBE_RGB, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_LINEAR, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::BT2020_ITU, std::nullopt), HdrRenderType::SDR);
+    EXPECT_EQ(getHdrRenderType(ui::Dataspace::DISPLAY_BT2020, std::nullopt), HdrRenderType::SDR);
+}
+
+} // namespace android
diff --git a/libs/ultrahdr/fuzzer/ultrahdr_enc_fuzzer.cpp b/libs/ultrahdr/fuzzer/ultrahdr_enc_fuzzer.cpp
index bf9b031..2d59e8b 100644
--- a/libs/ultrahdr/fuzzer/ultrahdr_enc_fuzzer.cpp
+++ b/libs/ultrahdr/fuzzer/ultrahdr_enc_fuzzer.cpp
@@ -161,10 +161,8 @@
                 fillP010Buffer(bufferUVHdr.get(), width, height / 2, uvStride);
             }
         } else {
-            size_t map_width = static_cast<size_t>(
-                    floor((width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
-            size_t map_height = static_cast<size_t>(
-                    floor((height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
+            size_t map_width = width / kMapDimensionScaleFactor;
+            size_t map_height = height / kMapDimensionScaleFactor;
             // init 400 image
             grayImg.width = map_width;
             grayImg.height = map_height;
@@ -207,7 +205,7 @@
                 fill420Buffer(bufferYSdr.get(), width, height, yStride);
                 size_t yuv420UVSize = uvStride * yuv420Img.height / 2 * 2;
                 bufferUVSdr = std::make_unique<uint8_t[]>(yuv420UVSize);
-                yuv420Img.chroma_data = bufferYSdr.get();
+                yuv420Img.chroma_data = bufferUVSdr.get();
                 yuv420Img.chroma_stride = uvStride;
                 fill420Buffer(bufferUVSdr.get(), width / 2, height / 2, uvStride);
                 fill420Buffer(bufferUVSdr.get() + uvStride * height / 2, width / 2, height / 2,
diff --git a/libs/ultrahdr/jpegr.cpp b/libs/ultrahdr/jpegr.cpp
index dc439d7..ae81845 100644
--- a/libs/ultrahdr/jpegr.cpp
+++ b/libs/ultrahdr/jpegr.cpp
@@ -801,10 +801,8 @@
 
   size_t image_width = yuv420_image_ptr->width;
   size_t image_height = yuv420_image_ptr->height;
-  size_t map_width = static_cast<size_t>(
-          floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
-  size_t map_height = static_cast<size_t>(
-          floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
+  size_t map_width = image_width / kMapDimensionScaleFactor;
+  size_t map_height = image_height / kMapDimensionScaleFactor;
 
   dest->data = new uint8_t[map_width * map_height];
   dest->width = map_width;
@@ -984,10 +982,8 @@
   // TODO: remove once map scaling factor is computed based on actual map dims
   size_t image_width = yuv420_image_ptr->width;
   size_t image_height = yuv420_image_ptr->height;
-  size_t map_width = static_cast<size_t>(
-          floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
-  size_t map_height = static_cast<size_t>(
-          floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor));
+  size_t map_width = image_width / kMapDimensionScaleFactor;
+  size_t map_height = image_height / kMapDimensionScaleFactor;
   if (map_width != gainmap_image_ptr->width || map_height != gainmap_image_ptr->height) {
     ALOGE("gain map dimensions and primary image dimensions are not to scale, computed gain map "
           "resolution is %dx%d, received gain map resolution is %dx%d",
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 18f6dbc..d551213 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -87,6 +87,7 @@
     srcs: [":libinputflinger_sources"],
     shared_libs: [
         "android.hardware.input.processor-V1-ndk",
+        "com.android.server.inputflinger-ndk",
         "libbase",
         "libbinder",
         "libbinder_ndk",
@@ -107,6 +108,14 @@
         "libpalmrejection",
         "libui-types",
     ],
+    generated_headers: [
+        "cxx-bridge-header",
+        "inputflinger_rs_bootstrap_bridge_header",
+    ],
+    header_libs: ["inputflinger_rs_bootstrap_cxx_headers"],
+    generated_sources: ["inputflinger_rs_bootstrap_bridge_code"],
+    whole_static_libs: ["libinputflinger_rs"],
+    export_shared_lib_headers: ["com.android.server.inputflinger-ndk"],
     target: {
         android: {
             shared_libs: [
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index c903564..da79ae3 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -23,22 +23,22 @@
 #include "InputReaderFactory.h"
 #include "UnwantedInteractionBlocker.h"
 
+#include <aidl/com/android/server/inputflinger/IInputFlingerRust.h>
+#include <android/binder_interface_utils.h>
 #include <android/sysprop/InputProperties.sysprop.h>
 #include <binder/IPCThreadState.h>
-
+#include <inputflinger_bootstrap.rs.h>
 #include <log/log.h>
-#include <unordered_map>
-
 #include <private/android_filesystem_config.h>
 
 namespace android {
 
-static const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
+namespace {
+
+const bool ENABLE_INPUT_DEVICE_USAGE_METRICS =
         sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
 
-using gui::FocusRequest;
-
-static int32_t exceptionCodeFromStatusT(status_t status) {
+int32_t exceptionCodeFromStatusT(status_t status) {
     switch (status) {
         case OK:
             return binder::Status::EX_NONE;
@@ -57,6 +57,58 @@
     }
 }
 
+// Convert a binder interface into a raw pointer to an AIBinder.
+using IInputFlingerRustBootstrapCallback = aidl::com::android::server::inputflinger::
+        IInputFlingerRust::IInputFlingerRustBootstrapCallback;
+IInputFlingerRustBootstrapCallbackAIBinder* binderToPointer(
+        IInputFlingerRustBootstrapCallback& interface) {
+    ndk::SpAIBinder spAIBinder = interface.asBinder();
+    auto* ptr = spAIBinder.get();
+    AIBinder_incStrong(ptr);
+    return ptr;
+}
+
+// Create the Rust component of InputFlinger that uses AIDL interfaces as a the foreign function
+// interface (FFI). The bootstraping process for IInputFlingerRust is as follows:
+//   - Create BnInputFlingerRustBootstrapCallback in C++.
+//   - Use the cxxbridge ffi interface to call the Rust function `create_inputflinger_rust()`, and
+//     pass the callback binder object as a raw pointer.
+//   - The Rust implementation will create the implementation of IInputFlingerRust, and pass it
+//     to C++ through the callback.
+//   - After the Rust function returns, the binder interface provided to the callback will be the
+//     only strong reference to the IInputFlingerRust.
+std::shared_ptr<IInputFlingerRust> createInputFlingerRust() {
+    using namespace aidl::com::android::server::inputflinger;
+
+    class Callback : public IInputFlingerRust::BnInputFlingerRustBootstrapCallback {
+        ndk::ScopedAStatus onProvideInputFlingerRust(
+                const std::shared_ptr<IInputFlingerRust>& inputFlingerRust) override {
+            mService = inputFlingerRust;
+            return ndk::ScopedAStatus::ok();
+        }
+
+    public:
+        std::shared_ptr<IInputFlingerRust> consumeInputFlingerRust() {
+            auto service = mService;
+            mService.reset();
+            return service;
+        }
+
+    private:
+        std::shared_ptr<IInputFlingerRust> mService;
+    };
+
+    auto callback = ndk::SharedRefBase::make<Callback>();
+    create_inputflinger_rust(binderToPointer(*callback));
+    auto service = callback->consumeInputFlingerRust();
+    LOG_ALWAYS_FATAL_IF(!service,
+                        "create_inputflinger_rust did not provide the IInputFlingerRust "
+                        "implementation through the callback.");
+    return service;
+}
+
+} // namespace
+
 /**
  * The event flow is via the "InputListener" interface, as follows:
  *   InputReader
@@ -67,6 +119,8 @@
  */
 InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
                            InputDispatcherPolicyInterface& dispatcherPolicy) {
+    mInputFlingerRust = createInputFlingerRust();
+
     mDispatcher = createInputDispatcher(dispatcherPolicy);
 
     if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
@@ -190,7 +244,7 @@
     return NO_ERROR;
 }
 
-binder::Status InputManager::setFocusedWindow(const FocusRequest& request) {
+binder::Status InputManager::setFocusedWindow(const gui::FocusRequest& request) {
     mDispatcher->setFocusedWindow(request);
     return binder::Status::ok();
 }
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 9dc285f..528d2aa 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -30,6 +30,7 @@
 #include <input/Input.h>
 #include <input/InputTransport.h>
 
+#include <aidl/com/android/server/inputflinger/IInputFlingerRust.h>
 #include <android/os/BnInputFlinger.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -37,6 +38,8 @@
 
 using android::os::BnInputFlinger;
 
+using aidl::com::android::server::inputflinger::IInputFlingerRust;
+
 namespace android {
 class InputChannel;
 class InputDispatcherThread;
@@ -132,6 +135,8 @@
     std::unique_ptr<InputDeviceMetricsCollectorInterface> mCollector;
 
     std::unique_ptr<InputDispatcherInterface> mDispatcher;
+
+    std::shared_ptr<IInputFlingerRust> mInputFlingerRust;
 };
 
 } // namespace android
diff --git a/services/inputflinger/aidl/Android.bp b/services/inputflinger/aidl/Android.bp
new file mode 100644
index 0000000..314c433
--- /dev/null
+++ b/services/inputflinger/aidl/Android.bp
@@ -0,0 +1,31 @@
+// Copyright 2023 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.
+
+aidl_interface {
+    name: "com.android.server.inputflinger",
+    srcs: ["**/*.aidl"],
+    unstable: true,
+    host_supported: true,
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+}
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
new file mode 100644
index 0000000..8e826fd
--- /dev/null
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package com.android.server.inputflinger;
+
+/**
+ * A local AIDL interface used as a foreign function interface (ffi) to
+ * communicate with the Rust component of inputflinger.
+ *
+ * NOTE: Since we use this as a local interface, all processing happens on the
+ * calling thread.
+ */
+interface IInputFlingerRust {
+
+   /**
+    * An interface used to get a strong reference to IInputFlingerRust on boot.
+    */
+    interface IInputFlingerRustBootstrapCallback {
+        void onProvideInputFlingerRust(in IInputFlingerRust inputFlingerRust);
+    }
+}
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index ec0388d..de99fc7 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -256,14 +256,14 @@
 
 const char* InputDriver::inputGetPropertyKey(input_property_t* property) {
     if (property != nullptr) {
-        return property->key.string();
+        return property->key.c_str();
     }
     return nullptr;
 }
 
 const char* InputDriver::inputGetPropertyValue(input_property_t* property) {
     if (property != nullptr) {
-        return property->value.string();
+        return property->value.c_str();
     }
     return nullptr;
 }
@@ -281,7 +281,7 @@
 }
 
 void InputDriver::dump(String8& result) {
-    result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
+    result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.c_str());
 }
 
 } // namespace android
diff --git a/services/inputflinger/host/InputFlinger.cpp b/services/inputflinger/host/InputFlinger.cpp
index 2da2a70..d974c43 100644
--- a/services/inputflinger/host/InputFlinger.cpp
+++ b/services/inputflinger/host/InputFlinger.cpp
@@ -57,7 +57,7 @@
     } else {
         dumpInternal(result);
     }
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     return OK;
 }
 
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 08600b2..7f63355 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -77,7 +77,7 @@
       : mContext(this),
         mEventHub(eventHub),
         mPolicy(policy),
-        mQueuedListener(listener),
+        mNextListener(listener),
         mGlobalMetaState(AMETA_NONE),
         mLedMetaState(AMETA_NONE),
         mGeneration(1),
@@ -140,7 +140,7 @@
         mReaderIsAliveCondition.notify_all();
 
         if (!events.empty()) {
-            notifyArgs += processEventsLocked(events.data(), events.size());
+            mPendingArgs += processEventsLocked(events.data(), events.size());
         }
 
         if (mNextTimeout != LLONG_MAX) {
@@ -150,16 +150,18 @@
                     ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
                 }
                 mNextTimeout = LLONG_MAX;
-                notifyArgs += timeoutExpiredLocked(now);
+                mPendingArgs += timeoutExpiredLocked(now);
             }
         }
 
         if (oldGeneration != mGeneration) {
             inputDevicesChanged = true;
             inputDevices = getInputDevicesLocked();
-            notifyArgs.emplace_back(
+            mPendingArgs.emplace_back(
                     NotifyInputDevicesChangedArgs{mContext.getNextId(), inputDevices});
         }
+
+        std::swap(notifyArgs, mPendingArgs);
     } // release lock
 
     // Send out a message that the describes the changed input devices.
@@ -175,8 +177,6 @@
         }
     }
 
-    notifyAll(std::move(notifyArgs));
-
     // Flush queued events out to the listener.
     // This must happen outside of the lock because the listener could potentially call
     // back into the InputReader's methods, such as getScanCodeState, or become blocked
@@ -184,7 +184,9 @@
     // resulting in a deadlock.  This situation is actually quite plausible because the
     // listener is actually the input dispatcher, which calls into the window manager,
     // which occasionally calls into the input reader.
-    mQueuedListener.flush();
+    for (const NotifyArgs& args : notifyArgs) {
+        mNextListener.notify(args);
+    }
 }
 
 std::list<NotifyArgs> InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
@@ -236,8 +238,8 @@
     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
     std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
 
-    notifyAll(device->configure(when, mConfig, /*changes=*/{}));
-    notifyAll(device->reset(when));
+    mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
+    mPendingArgs += device->reset(when);
 
     if (device->isIgnored()) {
         ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
@@ -310,12 +312,10 @@
         notifyExternalStylusPresenceChangedLocked();
     }
 
-    std::list<NotifyArgs> resetEvents;
     if (device->hasEventHubDevices()) {
-        resetEvents += device->configure(when, mConfig, /*changes=*/{});
+        mPendingArgs += device->configure(when, mConfig, /*changes=*/{});
     }
-    resetEvents += device->reset(when);
-    notifyAll(std::move(resetEvents));
+    mPendingArgs += device->reset(when);
 }
 
 std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
@@ -387,7 +387,7 @@
     updateGlobalMetaStateLocked();
 
     // Enqueue configuration changed.
-    mQueuedListener.notifyConfigurationChanged({mContext.getNextId(), when});
+    mPendingArgs.emplace_back(NotifyConfigurationChangedArgs{mContext.getNextId(), when});
 }
 
 void InputReader::refreshConfigurationLocked(ConfigurationChanges changes) {
@@ -409,7 +409,7 @@
     } else {
         for (auto& devicePair : mDevices) {
             std::shared_ptr<InputDevice>& device = devicePair.second;
-            notifyAll(device->configure(now, mConfig, changes));
+            mPendingArgs += device->configure(now, mConfig, changes);
         }
     }
 
@@ -419,18 +419,13 @@
                   "There was no change in the pointer capture state.");
         } else {
             mCurrentPointerCaptureRequest = mConfig.pointerCaptureRequest;
-            mQueuedListener.notifyPointerCaptureChanged(
-                    {mContext.getNextId(), now, mCurrentPointerCaptureRequest});
+            mPendingArgs.emplace_back(
+                    NotifyPointerCaptureChangedArgs{mContext.getNextId(), now,
+                                                    mCurrentPointerCaptureRequest});
         }
     }
 }
 
-void InputReader::notifyAll(std::list<NotifyArgs>&& argsList) {
-    for (const NotifyArgs& args : argsList) {
-        mQueuedListener.notify(args);
-    }
-}
-
 void InputReader::updateGlobalMetaStateLocked() {
     mGlobalMetaState = 0;
 
@@ -690,7 +685,7 @@
 
     InputDevice* device = findInputDeviceLocked(deviceId);
     if (device) {
-        notifyAll(device->vibrate(sequence, repeat, token));
+        mPendingArgs += device->vibrate(sequence, repeat, token);
     }
 }
 
@@ -699,7 +694,7 @@
 
     InputDevice* device = findInputDeviceLocked(deviceId);
     if (device) {
-        notifyAll(device->cancelVibrate(token));
+        mPendingArgs += device->cancelVibrate(token);
     }
 }
 
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 01ec7c1..e21715e 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -174,7 +174,14 @@
     // in parallel to passing it to the InputReader.
     std::shared_ptr<EventHubInterface> mEventHub;
     sp<InputReaderPolicyInterface> mPolicy;
-    QueuedInputListener mQueuedListener;
+
+    // The next stage that should receive the events generated inside InputReader.
+    InputListenerInterface& mNextListener;
+    // As various events are generated inside InputReader, they are stored inside this list. The
+    // list can only be accessed with the lock, so the events inside it are well-ordered.
+    // Once the reader is done working, these events will be swapped into a temporary storage and
+    // sent to the 'mNextListener' without holding the lock.
+    std::list<NotifyArgs> mPendingArgs GUARDED_BY(mLock);
 
     InputReaderConfiguration mConfig GUARDED_BY(mLock);
 
@@ -242,8 +249,6 @@
     ConfigurationChanges mConfigurationChangesToRefresh GUARDED_BY(mLock);
     void refreshConfigurationLocked(ConfigurationChanges changes) REQUIRES(mLock);
 
-    void notifyAll(std::list<NotifyArgs>&& argsList);
-
     PointerCaptureRequest mCurrentPointerCaptureRequest GUARDED_BY(mLock);
 
     // state queries
diff --git a/services/inputflinger/rust/Android.bp b/services/inputflinger/rust/Android.bp
new file mode 100644
index 0000000..23c1691
--- /dev/null
+++ b/services/inputflinger/rust/Android.bp
@@ -0,0 +1,52 @@
+// Copyright 2023 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.
+
+// Generate the C++ code that Rust calls into.
+genrule {
+    name: "inputflinger_rs_bootstrap_bridge_code",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) >> $(out)",
+    srcs: ["lib.rs"],
+    out: ["inputflinger_rs_bootstrap_cxx_generated.cc"],
+}
+
+// Generate a C++ header containing the C++ bindings
+// to the Rust exported functions in lib.rs.
+genrule {
+    name: "inputflinger_rs_bootstrap_bridge_header",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
+    srcs: ["lib.rs"],
+    out: ["inputflinger_bootstrap.rs.h"],
+}
+
+rust_ffi_static {
+    name: "libinputflinger_rs",
+    crate_name: "inputflinger",
+    srcs: ["lib.rs"],
+    rustlibs: [
+        "libcxx",
+        "com.android.server.inputflinger-rust",
+        "libbinder_rs",
+        "liblog_rust",
+        "liblogger",
+    ],
+    host_supported: true,
+}
+
+cc_library_headers {
+    name: "inputflinger_rs_bootstrap_cxx_headers",
+    host_supported: true,
+    export_include_dirs: ["ffi"],
+}
diff --git a/libs/renderengine/include/renderengine/Image.h b/services/inputflinger/rust/ffi/InputFlingerBootstrap.h
similarity index 63%
rename from libs/renderengine/include/renderengine/Image.h
rename to services/inputflinger/rust/ffi/InputFlingerBootstrap.h
index 3bb4731..eb79ab5 100644
--- a/libs/renderengine/include/renderengine/Image.h
+++ b/services/inputflinger/rust/ffi/InputFlingerBootstrap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2023 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.
@@ -16,16 +16,6 @@
 
 #pragma once
 
-struct ANativeWindowBuffer;
+#include <android/binder_parcel.h>
 
-namespace android {
-namespace renderengine {
-
-class Image {
-public:
-    virtual ~Image() = default;
-    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) = 0;
-};
-
-} // namespace renderengine
-} // namespace android
+using IInputFlingerRustBootstrapCallbackAIBinder = AIBinder;
diff --git a/services/inputflinger/rust/lib.rs b/services/inputflinger/rust/lib.rs
new file mode 100644
index 0000000..c0561d7
--- /dev/null
+++ b/services/inputflinger/rust/lib.rs
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2023 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.
+ */
+
+//! # The rust component of InputFlinger
+//!
+//! We use cxxbridge to create IInputFlingerRust - the Rust component of inputflinger - and
+//! pass it back to C++ as a local AIDL interface.
+
+use binder::{
+    unstable_api::{AIBinder, new_spibinder,},
+    BinderFeatures, Interface, StatusCode, Strong,
+};
+use com_android_server_inputflinger::aidl::com::android::server::inputflinger::IInputFlingerRust::{
+    BnInputFlingerRust, IInputFlingerRust,
+    IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback,
+};
+use log::debug;
+
+const LOG_TAG: &str = "inputflinger_bootstrap";
+
+#[cxx::bridge]
+mod ffi {
+    extern "C++" {
+        include!("InputFlingerBootstrap.h");
+        type IInputFlingerRustBootstrapCallbackAIBinder;
+    }
+
+    extern "Rust" {
+        unsafe fn create_inputflinger_rust(
+            callback: *mut IInputFlingerRustBootstrapCallbackAIBinder,
+        );
+    }
+}
+
+/// Create the IInputFlingerRust implementation.
+/// This is the singular entry point from C++ into Rust.
+/// The `callback` parameter must be a valid pointer to an AIBinder implementation of
+/// the `IInputFlingerRustBootstrapCallback` interface. The IInputFlingerRust implementation that
+/// is created will be passed back through the callback from within this function.
+/// NOTE: This function must not hold a strong reference to the callback beyond its scope.
+///
+/// # Safety
+///
+/// This function is safe iff `callback` is a valid pointer to an `AIBinder` interface of type
+/// `IInputFlingerRustBootstrapCallback`. The pointer must have had its reference count manually
+/// incremented using `AIBinder_incStrong`. See `binder::unstable_api::new_spibinder`.
+unsafe fn create_inputflinger_rust(callback: *mut ffi::IInputFlingerRustBootstrapCallbackAIBinder) {
+    logger::init(
+        logger::Config::default().with_tag_on_device(LOG_TAG).with_min_level(log::Level::Trace),
+    );
+
+    let callback = callback as *mut AIBinder;
+    if callback.is_null() {
+        panic!("create_inputflinger_rust cannot be called with a null callback");
+    }
+
+    let Some(callback) = new_spibinder(callback) else {
+            panic!("Failed to get SpAIBinder from raw callback pointer");
+        };
+
+    let callback: Result<Strong<dyn IInputFlingerRustBootstrapCallback>, StatusCode> =
+        callback.into_interface();
+    match callback {
+        Ok(callback) => {
+            debug!("Creating InputFlingerRust");
+            let service =
+                BnInputFlingerRust::new_binder(InputFlingerRust {}, BinderFeatures::default());
+            callback.onProvideInputFlingerRust(&service).unwrap();
+        }
+        Err(status) => {
+            panic!("Failed to convert AIBinder into the callback interface: {}", status);
+        }
+    }
+}
+
+struct InputFlingerRust {}
+
+impl Interface for InputFlingerRust {}
+
+impl IInputFlingerRust for InputFlingerRust {}
+
+impl Drop for InputFlingerRust {
+    fn drop(&mut self) {
+        debug!("Destroying InputFlingerRust");
+    }
+}
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 78420c0..41c98ef 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -158,7 +158,8 @@
     return mConfig;
 }
 
-const std::vector<InputDeviceInfo>& FakeInputReaderPolicy::getInputDevices() const {
+const std::vector<InputDeviceInfo> FakeInputReaderPolicy::getInputDevices() const {
+    std::scoped_lock lock(mLock);
     return mInputDevices;
 }
 
@@ -228,7 +229,7 @@
 
 void FakeInputReaderPolicy::notifyInputDevicesChanged(
         const std::vector<InputDeviceInfo>& inputDevices) {
-    std::scoped_lock<std::mutex> lock(mLock);
+    std::scoped_lock lock(mLock);
     mInputDevices = inputDevices;
     mInputDevicesChanged = true;
     mDevicesChangedCondition.notify_all();
@@ -256,7 +257,7 @@
 }
 
 void FakeInputReaderPolicy::notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) {
-    std::scoped_lock<std::mutex> lock(mLock);
+    std::scoped_lock lock(mLock);
     mStylusGestureNotified = deviceId;
 }
 
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index e03d28d..48912a6 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -64,7 +64,7 @@
     void removeDisabledDevice(int32_t deviceId);
     void setPointerController(std::shared_ptr<FakePointerController> controller);
     const InputReaderConfiguration& getReaderConfiguration() const;
-    const std::vector<InputDeviceInfo>& getInputDevices() const;
+    const std::vector<InputDeviceInfo> getInputDevices() const;
     TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
                                                            ui::Rotation surfaceRotation);
     void setTouchAffineTransformation(const TouchAffineTransformation t);
@@ -91,7 +91,7 @@
     void waitForInputDevices(std::function<void(bool)> processDevicesChanged);
     void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) override;
 
-    std::mutex mLock;
+    mutable std::mutex mLock;
     std::condition_variable mDevicesChangedCondition;
 
     InputReaderConfiguration mConfig;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 1b19870..72fe2af 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1829,6 +1829,38 @@
     ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
 }
 
+/**
+ * Some drivers historically have reported axis values outside of the range specified in the
+ * evdev axis info. Ensure we don't crash when this happens. For example, a driver may report a
+ * pressure value greater than the reported maximum, since it unclear what specific meaning the
+ * maximum value for pressure has (beyond the maximum value that can be produced by a sensor),
+ * and no units for pressure (resolution) is specified by the evdev documentation.
+ */
+TEST_P(TouchIntegrationTest, AcceptsAxisValuesOutsideReportedRange) {
+    const Point centerPoint = mDevice->getCenterPoint();
+
+    // Down with pressure outside the reported range
+    mDevice->sendSlot(FIRST_SLOT);
+    mDevice->sendTrackingId(FIRST_TRACKING_ID);
+    mDevice->sendDown(centerPoint);
+    mDevice->sendPressure(UinputTouchScreen::RAW_PRESSURE_MAX + 2);
+    mDevice->sendSync();
+    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
+            WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
+
+    // Move to a point outside the reported range
+    mDevice->sendMove(Point(DISPLAY_WIDTH, DISPLAY_HEIGHT) + Point(1, 1));
+    mDevice->sendSync();
+    ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
+            WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
+
+    // Up
+    mDevice->sendUp();
+    mDevice->sendSync();
+    ASSERT_NO_FATAL_FAILURE(
+            mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
+}
+
 TEST_P(TouchIntegrationTest, NotifiesPolicyWhenStylusGestureStarted) {
     const Point centerPoint = mDevice->getCenterPoint();
 
diff --git a/services/inputflinger/tests/UinputDevice.cpp b/services/inputflinger/tests/UinputDevice.cpp
index 7ceaccf..19f7bb4 100644
--- a/services/inputflinger/tests/UinputDevice.cpp
+++ b/services/inputflinger/tests/UinputDevice.cpp
@@ -177,6 +177,7 @@
     ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
     ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
     ioctl(fd, UI_SET_ABSBIT, ABS_MT_TOOL_TYPE);
+    ioctl(fd, UI_SET_ABSBIT, ABS_MT_PRESSURE);
     ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT);
     if (!mPhysicalPort.empty()) {
         ioctl(fd, UI_SET_PHYS, mPhysicalPort.c_str());
@@ -194,6 +195,8 @@
     device->absmax[ABS_MT_TRACKING_ID] = RAW_ID_MAX;
     device->absmin[ABS_MT_TOOL_TYPE] = MT_TOOL_FINGER;
     device->absmax[ABS_MT_TOOL_TYPE] = MT_TOOL_MAX;
+    device->absmin[ABS_MT_PRESSURE] = RAW_PRESSURE_MIN;
+    device->absmax[ABS_MT_PRESSURE] = RAW_PRESSURE_MAX;
 }
 
 void UinputTouchScreen::sendSlot(int32_t slot) {
@@ -206,6 +209,7 @@
 
 void UinputTouchScreen::sendDown(const Point& point) {
     injectEvent(EV_KEY, BTN_TOUCH, 1);
+    injectEvent(EV_ABS, ABS_MT_PRESSURE, RAW_PRESSURE_MAX);
     injectEvent(EV_ABS, ABS_MT_POSITION_X, point.x);
     injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
 }
@@ -215,6 +219,10 @@
     injectEvent(EV_ABS, ABS_MT_POSITION_Y, point.y);
 }
 
+void UinputTouchScreen::sendPressure(int32_t pressure) {
+    injectEvent(EV_ABS, ABS_MT_PRESSURE, pressure);
+}
+
 void UinputTouchScreen::sendPointerUp() {
     sendTrackingId(0xffffffff);
 }
diff --git a/services/inputflinger/tests/UinputDevice.h b/services/inputflinger/tests/UinputDevice.h
index 5b07465..e7010c3 100644
--- a/services/inputflinger/tests/UinputDevice.h
+++ b/services/inputflinger/tests/UinputDevice.h
@@ -189,6 +189,7 @@
     void sendTrackingId(int32_t trackingId);
     void sendDown(const Point& point);
     void sendMove(const Point& point);
+    void sendPressure(int32_t pressure);
     void sendPointerUp();
     void sendUp();
     void sendToolType(int32_t toolType);
diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
index 752257b..bdaa1d0 100644
--- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp
@@ -41,8 +41,7 @@
 }
 
 inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) {
-    return lhs.textureName == rhs.textureName &&
-            lhs.useTextureFiltering == rhs.useTextureFiltering &&
+    return lhs.useTextureFiltering == rhs.useTextureFiltering &&
             lhs.textureTransform == rhs.textureTransform &&
             lhs.usePremultipliedAlpha == rhs.usePremultipliedAlpha &&
             lhs.isOpaque == rhs.isOpaque && lhs.maxLuminanceNits == rhs.maxLuminanceNits;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index b492b6a..4fe6927 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include <DisplayHardware/Hal.h>
 #include <android-base/stringprintf.h>
 #include <compositionengine/DisplayColorProfile.h>
@@ -26,7 +25,7 @@
 #include <cstdint>
 #include "system/graphics-base-v1.0.h"
 
-#include <ui/DataspaceUtils.h>
+#include <ui/HdrRenderTypeUtils.h>
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic push
@@ -312,15 +311,26 @@
         }
     }
 
+    auto pixelFormat = layerFEState->buffer ? std::make_optional(static_cast<ui::PixelFormat>(
+                                                      layerFEState->buffer->getPixelFormat()))
+                                            : std::nullopt;
+
+    auto hdrRenderType =
+            getHdrRenderType(outputState.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
+
     // Determine the output dependent dataspace for this layer. If it is
     // colorspace agnostic, it just uses the dataspace chosen for the output to
     // avoid the need for color conversion.
     // For now, also respect the colorspace agnostic flag if we're drawing to HDR, to avoid drastic
     // luminance shift. TODO(b/292162273): we should check if that's true though.
-    state.dataspace = layerFEState->isColorspaceAgnostic && !isHdrDataspace(outputState.dataspace)
+    state.dataspace = layerFEState->isColorspaceAgnostic && hdrRenderType == HdrRenderType::SDR
             ? outputState.dataspace
             : layerFEState->dataspace;
 
+    // re-get HdrRenderType after the dataspace gets changed.
+    hdrRenderType =
+            getHdrRenderType(state.dataspace, pixelFormat, layerFEState->desiredHdrSdrRatio);
+
     // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
     // We do this here instead of in buffer info so that dumpsys can still report layers that are
     // using the 170M transfer. Also we only do this if the colorspace is not agnostic for the
@@ -335,7 +345,7 @@
     // For hdr content, treat the white point as the display brightness - HDR content should not be
     // boosted or dimmed.
     // If the layer explicitly requests to disable dimming, then don't dim either.
-    if (isHdrDataspace(state.dataspace) ||
+    if (hdrRenderType == HdrRenderType::GENERIC_HDR ||
         getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
         getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) {
         state.dimmingRatio = 1.f;
@@ -344,8 +354,7 @@
         float layerBrightnessNits = getOutput().getState().sdrWhitePointNits;
         // RANGE_EXTENDED can "self-promote" to HDR, but is still rendered for a particular
         // range that we may need to re-adjust to the current display conditions
-        if ((state.dataspace & HAL_DATASPACE_RANGE_MASK) == HAL_DATASPACE_RANGE_EXTENDED &&
-            layerFEState->currentHdrSdrRatio > 1.01f) {
+        if (hdrRenderType == HdrRenderType::DISPLAY_HDR) {
             layerBrightnessNits *= layerFEState->currentHdrSdrRatio;
         }
         state.dimmingRatio =
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
index c26edb5..0788d1a 100644
--- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
@@ -54,7 +54,6 @@
     gui::LayerMetadata metadata;
     pid_t ownerPid;
     uid_t ownerUid;
-    uint32_t textureName;
     uint32_t sequence;
     bool addToRoot = true;
     wp<IBinder> parentHandle = nullptr;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index d42bce6..80bedf4 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -118,7 +118,6 @@
     sequence = static_cast<int32_t>(state.id);
     name = state.name;
     debugName = state.debugName;
-    textureName = state.textureName;
     premultipliedAlpha = state.premultipliedAlpha;
     inputInfo.name = state.name;
     inputInfo.id = static_cast<int32_t>(uniqueSequence);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 92d23e2..7537a39 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -64,7 +64,6 @@
     int32_t sequence;
     std::string name;
     std::string debugName;
-    uint32_t textureName;
     bool contentOpaque;
     bool layerOpaqueFlagSet;
     RoundedCornerState roundedCorner;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index d979c46..a5d5563 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -51,7 +51,6 @@
         name(args.name + "#" + std::to_string(args.sequence)),
         canBeRoot(args.addToRoot),
         layerCreationFlags(args.flags),
-        textureName(args.textureName),
         ownerUid(args.ownerUid),
         ownerPid(args.ownerPid),
         parentId(args.parentId),
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 0309302..8eff22b 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -95,7 +95,6 @@
     const std::string name;
     bool canBeRoot = false;
     const uint32_t layerCreationFlags;
-    const uint32_t textureName;
     // The owner of the layer. If created from a non system process, it will be the calling uid.
     // If created from a system process, the value can be passed in.
     const gui::Uid ownerUid;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 59a8825..30dce11 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -50,10 +50,10 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <system/graphics-base-v1.0.h>
-#include <ui/DataspaceUtils.h>
 #include <ui/DebugUtils.h>
 #include <ui/FloatRect.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/HdrRenderTypeUtils.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Transform.h>
@@ -149,7 +149,6 @@
                 args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))),
         mLayerCreationFlags(args.flags),
         mBorderEnabled(false),
-        mTextureName(args.textureName),
         mLegacyLayerFE(args.flinger->getFactory().createLayerFE(mName)) {
     ALOGV("Creating Layer %s", getDebugName());
 
@@ -214,7 +213,6 @@
 
     mSnapshot->sequence = sequence;
     mSnapshot->name = getDebugName();
-    mSnapshot->textureName = mTextureName;
     mSnapshot->premultipliedAlpha = mPremultipliedAlpha;
     mSnapshot->parentTransform = {};
 }
@@ -236,13 +234,6 @@
                                   mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFrameNumber,
                                   mBufferInfo.mFence);
     }
-    if (!isClone()) {
-        // The original layer and the clone layer share the same texture. Therefore, only one of
-        // the layers, in this case the original layer, needs to handle the deletion. The original
-        // layer and the clone should be removed at the same time so there shouldn't be any issue
-        // with the clone layer trying to use the deleted texture.
-        mFlinger->deleteTextureAsync(mTextureName);
-    }
     const int32_t layerId = getSequence();
     mFlinger->mTimeStats->onDestroy(layerId);
     mFlinger->mFrameTracer->onDestroy(layerId);
@@ -3624,7 +3615,6 @@
 
 sp<Layer> Layer::createClone(uint32_t mirrorRootId) {
     LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
-    args.textureName = mTextureName;
     sp<Layer> layer = mFlinger->getFactory().createBufferStateLayer(args);
     layer->setInitialValuesForClone(sp<Layer>::fromExisting(this), mirrorRootId);
     return layer;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index d1912e4..8a65d9d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -23,8 +23,6 @@
 #include <gui/WindowInfo.h>
 #include <layerproto/LayerProtoHeader.h>
 #include <math/vec4.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Texture.h>
 #include <sys/types.h>
 #include <ui/BlurRegion.h>
 #include <ui/FloatRect.h>
@@ -1193,8 +1191,6 @@
     void setTransformHintLegacy(ui::Transform::RotationFlags);
     void resetDrawingStateBufferInfo();
 
-    const uint32_t mTextureName;
-
     // Transform hint provided to the producer. This must be accessed holding
     // the mStateLock.
     ui::Transform::RotationFlags mTransformHintLegacy = ui::Transform::ROT_0;
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index 5ae52ab..a0024d5 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -223,7 +223,6 @@
     layerSettings.source.buffer.buffer = mSnapshot->externalTexture;
     layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque;
     layerSettings.source.buffer.fence = mSnapshot->acquireFence;
-    layerSettings.source.buffer.textureName = mSnapshot->textureName;
     layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
     bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
     bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index fb985f7..2bb8c3f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -148,8 +148,8 @@
 } // namespace
 
 auto RefreshRateSelector::createFrameRateModes(
-        std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange& renderRange) const
-        -> std::vector<FrameRateMode> {
+        const Policy& policy, std::function<bool(const DisplayMode&)>&& filterModes,
+        const FpsRange& renderRange) const -> std::vector<FrameRateMode> {
     struct Key {
         Fps fps;
         int32_t group;
@@ -202,11 +202,25 @@
                 ALOGV("%s: including %s (%s)", __func__, to_string(fps).c_str(),
                       to_string(mode->getFps()).c_str());
             } else {
-                // We might need to update the map as we found a lower refresh rate
-                if (isStrictlyLess(mode->getFps(), existingIter->second->second->getFps())) {
+                // If the primary physical range is a single rate, prefer to stay in that rate
+                // even if there is a lower physical refresh rate available. This would cause more
+                // cases to stay within the primary physical range
+                const Fps existingModeFps = existingIter->second->second->getFps();
+                const bool existingModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
+                        policy.primaryRanges.physical.includes(existingModeFps);
+                const bool newModeIsPrimaryRange = policy.primaryRangeIsSingleRate() &&
+                        policy.primaryRanges.physical.includes(mode->getFps());
+                if (newModeIsPrimaryRange == existingModeIsPrimaryRange) {
+                    // We might need to update the map as we found a lower refresh rate
+                    if (isStrictlyLess(mode->getFps(), existingModeFps)) {
+                        existingIter->second = it;
+                        ALOGV("%s: changing %s (%s) as we found a lower physical rate", __func__,
+                              to_string(fps).c_str(), to_string(mode->getFps()).c_str());
+                    }
+                } else if (newModeIsPrimaryRange) {
                     existingIter->second = it;
-                    ALOGV("%s: changing %s (%s)", __func__, to_string(fps).c_str(),
-                          to_string(mode->getFps()).c_str());
+                    ALOGV("%s: changing %s (%s) to stay in the primary range", __func__,
+                          to_string(fps).c_str(), to_string(mode->getFps()).c_str());
                 }
             }
         }
@@ -500,10 +514,8 @@
     // If the primary range consists of a single refresh rate then we can only
     // move out the of range if layers explicitly request a different refresh
     // rate.
-    const bool primaryRangeIsSingleRate =
-            isApproxEqual(policy->primaryRanges.physical.min, policy->primaryRanges.physical.max);
-
-    if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
+    if (!signals.touch && signals.idle &&
+        !(policy->primaryRangeIsSingleRate() && hasExplicitVoteLayers)) {
         ALOGV("Idle");
         const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending);
         ATRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str());
@@ -577,8 +589,11 @@
                 continue;
             }
 
-            const bool inPrimaryRange = policy->primaryRanges.render.includes(fps);
-            if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
+            const bool inPrimaryPhysicalRange =
+                    policy->primaryRanges.physical.includes(modePtr->getFps());
+            const bool inPrimaryRenderRange = policy->primaryRanges.render.includes(fps);
+            if (((policy->primaryRangeIsSingleRate() && !inPrimaryPhysicalRange) ||
+                 !inPrimaryRenderRange) &&
                 !(layer.focused &&
                   (layer.vote == LayerVoteType::ExplicitDefault ||
                    layer.vote == LayerVoteType::ExplicitExact))) {
@@ -689,7 +704,7 @@
         return score.overallScore == 0;
     });
 
-    if (primaryRangeIsSingleRate) {
+    if (policy->primaryRangeIsSingleRate()) {
         // If we never scored any layers, then choose the rate from the primary
         // range instead of picking a random score from the app range.
         if (noLayerScore) {
@@ -1236,14 +1251,14 @@
                     (supportsFrameRateOverride() || ranges.render.includes(mode.getFps()));
         };
 
-        auto frameRateModes = createFrameRateModes(filterModes, ranges.render);
+        auto frameRateModes = createFrameRateModes(*policy, filterModes, ranges.render);
         if (frameRateModes.empty()) {
             ALOGW("No matching frame rate modes for %s range. policy: %s", rangeName,
                   policy->toString().c_str());
             // TODO(b/292105422): Ideally DisplayManager should not send render ranges smaller than
             // the min supported. See b/292047939.
             //  For not we just ignore the render ranges.
-            frameRateModes = createFrameRateModes(filterModes, {});
+            frameRateModes = createFrameRateModes(*policy, filterModes, {});
         }
         LOG_ALWAYS_FATAL_IF(frameRateModes.empty(),
                             "No matching frame rate modes for %s range even after ignoring the "
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index 7af8d03..b25919e 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -101,6 +101,11 @@
         }
 
         bool operator!=(const Policy& other) const { return !(*this == other); }
+
+        bool primaryRangeIsSingleRate() const {
+            return isApproxEqual(primaryRanges.physical.min, primaryRanges.physical.max);
+        }
+
         std::string toString() const;
     };
 
@@ -468,8 +473,8 @@
     }
 
     std::vector<FrameRateMode> createFrameRateModes(
-            std::function<bool(const DisplayMode&)>&& filterModes, const FpsRange&) const
-            REQUIRES(mLock);
+            const Policy&, std::function<bool(const DisplayMode&)>&& filterModes,
+            const FpsRange&) const REQUIRES(mLock);
 
     // The display modes of the active display. The DisplayModeIterators below are pointers into
     // this container, so must be invalidated whenever the DisplayModes change. The Policy below
diff --git a/services/surfaceflinger/ScreenCaptureOutput.cpp b/services/surfaceflinger/ScreenCaptureOutput.cpp
index 0103843..ef9b457 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.cpp
+++ b/services/surfaceflinger/ScreenCaptureOutput.cpp
@@ -45,10 +45,9 @@
 std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) {
     std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
             ScreenCaptureOutput, compositionengine::CompositionEngine, const RenderArea&,
-            const compositionengine::Output::ColorProfile&, bool>(args.compositionEngine,
-                                                                  args.renderArea,
-                                                                  args.colorProfile,
-                                                                  args.regionSampling);
+            const compositionengine::Output::ColorProfile&,
+            bool>(args.compositionEngine, args.renderArea, args.colorProfile, args.regionSampling,
+                  args.dimInGammaSpaceForEnhancedScreenshots);
     output->editState().isSecure = args.renderArea.isSecure();
     output->setCompositionEnabled(true);
     output->setLayerFilter({args.layerStack});
@@ -81,8 +80,11 @@
 
 ScreenCaptureOutput::ScreenCaptureOutput(
         const RenderArea& renderArea, const compositionengine::Output::ColorProfile& colorProfile,
-        bool regionSampling)
-      : mRenderArea(renderArea), mColorProfile(colorProfile), mRegionSampling(regionSampling) {}
+        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots)
+      : mRenderArea(renderArea),
+        mColorProfile(colorProfile),
+        mRegionSampling(regionSampling),
+        mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots) {}
 
 void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) {
     auto& outputState = editState();
@@ -95,6 +97,14 @@
     auto clientCompositionDisplay =
             compositionengine::impl::Output::generateClientCompositionDisplaySettings();
     clientCompositionDisplay.clip = mRenderArea.getSourceCrop();
+
+    auto renderIntent = static_cast<ui::RenderIntent>(clientCompositionDisplay.renderIntent);
+    if (mDimInGammaSpaceForEnhancedScreenshots && renderIntent != ui::RenderIntent::COLORIMETRIC &&
+        renderIntent != ui::RenderIntent::TONE_MAP_COLORIMETRIC) {
+        clientCompositionDisplay.dimmingStage =
+                aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
+    }
+
     return clientCompositionDisplay;
 }
 
diff --git a/services/surfaceflinger/ScreenCaptureOutput.h b/services/surfaceflinger/ScreenCaptureOutput.h
index 159c2bf..fc095de 100644
--- a/services/surfaceflinger/ScreenCaptureOutput.h
+++ b/services/surfaceflinger/ScreenCaptureOutput.h
@@ -37,6 +37,7 @@
     float targetBrightness;
     bool regionSampling;
     bool treat170mAsSrgb;
+    bool dimInGammaSpaceForEnhancedScreenshots;
 };
 
 // ScreenCaptureOutput is used to compose a set of layers into a preallocated buffer.
@@ -47,7 +48,7 @@
 public:
     ScreenCaptureOutput(const RenderArea& renderArea,
                         const compositionengine::Output::ColorProfile& colorProfile,
-                        bool regionSampling);
+                        bool regionSampling, bool dimInGammaSpaceForEnhancedScreenshots);
 
     void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
 
@@ -63,6 +64,7 @@
     const RenderArea& mRenderArea;
     const compositionengine::Output::ColorProfile& mColorProfile;
     const bool mRegionSampling;
+    const bool mDimInGammaSpaceForEnhancedScreenshots;
 };
 
 std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ea4a95a..f8f0d79 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -81,7 +81,6 @@
 #include <scheduler/FrameTargeter.h>
 #include <sys/types.h>
 #include <ui/ColorSpace.h>
-#include <ui/DataspaceUtils.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayId.h>
 #include <ui/DisplayMode.h>
@@ -89,6 +88,7 @@
 #include <ui/DisplayState.h>
 #include <ui/DynamicDisplayInfo.h>
 #include <ui/GraphicBufferAllocator.h>
+#include <ui/HdrRenderTypeUtils.h>
 #include <ui/LayerStack.h>
 #include <ui/PixelFormat.h>
 #include <ui/StaticDisplayInfo.h>
@@ -452,6 +452,9 @@
     property_get("debug.sf.treat_170m_as_sRGB", value, "0");
     mTreat170mAsSrgb = atoi(value);
 
+    property_get("debug.sf.dim_in_gamma_in_enhanced_screenshots", value, 0);
+    mDimInGammaSpaceForEnhancedScreenshots = atoi(value);
+
     mIgnoreHwcPhysicalDisplayOrientation =
             base::GetBoolProperty("debug.sf.ignore_hwc_physical_display_orientation"s, false);
 
@@ -730,52 +733,12 @@
     }));
 }
 
-uint32_t SurfaceFlinger::getNewTexture() {
-    {
-        std::lock_guard lock(mTexturePoolMutex);
-        if (!mTexturePool.empty()) {
-            uint32_t name = mTexturePool.back();
-            mTexturePool.pop_back();
-            ATRACE_INT("TexturePoolSize", mTexturePool.size());
-            return name;
-        }
-
-        // The pool was too small, so increase it for the future
-        ++mTexturePoolSize;
-    }
-
-    // The pool was empty, so we need to get a new texture name directly using a
-    // blocking call to the main thread
-    auto genTextures = [this] {
-               uint32_t name = 0;
-               getRenderEngine().genTextures(1, &name);
-               return name;
-    };
-    if (std::this_thread::get_id() == mMainThreadId) {
-        return genTextures();
-    } else {
-        return mScheduler->schedule(genTextures).get();
-    }
-}
-
-void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
-    std::lock_guard lock(mTexturePoolMutex);
-    // We don't change the pool size, so the fix-up logic in postComposition will decide whether
-    // to actually delete this or not based on mTexturePoolSize
-    mTexturePool.push_back(texture);
-    ATRACE_INT("TexturePoolSize", mTexturePool.size());
-}
-
 static std::optional<renderengine::RenderEngine::RenderEngineType>
 chooseRenderEngineTypeViaSysProp() {
     char prop[PROPERTY_VALUE_MAX];
-    property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "");
+    property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "skiaglthreaded");
 
-    if (strcmp(prop, "gles") == 0) {
-        return renderengine::RenderEngine::RenderEngineType::GLES;
-    } else if (strcmp(prop, "threaded") == 0) {
-        return renderengine::RenderEngine::RenderEngineType::THREADED;
-    } else if (strcmp(prop, "skiagl") == 0) {
+    if (strcmp(prop, "skiagl") == 0) {
         return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
     } else if (strcmp(prop, "skiaglthreaded") == 0) {
         return renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED;
@@ -2791,7 +2754,14 @@
             return false;
         }
     }
-    if (isHdrDataspace(snapshot.dataspace)) {
+    // RANGE_EXTENDED layer may identify themselves as being "HDR"
+    // via a desired hdr/sdr ratio
+    auto pixelFormat = snapshot.buffer
+            ? std::make_optional(static_cast<ui::PixelFormat>(snapshot.buffer->getPixelFormat()))
+            : std::nullopt;
+
+    if (getHdrRenderType(snapshot.dataspace, pixelFormat, snapshot.desiredHdrSdrRatio) !=
+        HdrRenderType::SDR) {
         return true;
     }
     // If the layer is not allowed to be dimmed, treat it as HDR. WindowManager may disable
@@ -2801,12 +2771,6 @@
     if (!snapshot.dimmingEnabled) {
         return true;
     }
-    // RANGE_EXTENDED layers may identify themselves as being "HDR" via a desired sdr/hdr ratio
-    if ((snapshot.dataspace & (int32_t)Dataspace::RANGE_MASK) ==
-                (int32_t)Dataspace::RANGE_EXTENDED &&
-        snapshot.desiredHdrSdrRatio > 1.01f) {
-        return true;
-    }
     return false;
 }
 
@@ -3064,23 +3028,6 @@
     // Cleanup any outstanding resources due to rendering a prior frame.
     getRenderEngine().cleanupPostRender();
 
-    {
-        std::lock_guard lock(mTexturePoolMutex);
-        if (mTexturePool.size() < mTexturePoolSize) {
-            const size_t refillCount = mTexturePoolSize - mTexturePool.size();
-            const size_t offset = mTexturePool.size();
-            mTexturePool.resize(mTexturePoolSize);
-            getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
-            ATRACE_INT("TexturePoolSize", mTexturePool.size());
-        } else if (mTexturePool.size() > mTexturePoolSize) {
-            const size_t deleteCount = mTexturePool.size() - mTexturePoolSize;
-            const size_t offset = mTexturePoolSize;
-            getRenderEngine().deleteTextures(deleteCount, mTexturePool.data() + offset);
-            mTexturePool.resize(mTexturePoolSize);
-            ATRACE_INT("TexturePoolSize", mTexturePool.size());
-        }
-    }
-
     if (mNumTrustedPresentationListeners > 0) {
         // We avoid any reverse traversal upwards so this shouldn't be too expensive
         traverseLegacyLayers([&](Layer* layer) {
@@ -3578,8 +3525,6 @@
 
     // Recreate the DisplayDevice if the surface or sequence ID changed.
     if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) {
-        getRenderEngine().cleanFramebufferCache();
-
         if (const auto display = getDisplayDeviceLocked(displayToken)) {
             display->disconnect();
             if (display->isVirtual()) {
@@ -5559,7 +5504,6 @@
 
 status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
                                                 sp<Layer>* outLayer) {
-    args.textureName = getNewTexture();
     *outLayer = getFactory().createBufferStateLayer(args);
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
@@ -7858,7 +7802,9 @@
                                         .displayBrightnessNits = displayBrightnessNits,
                                         .targetBrightness = targetBrightness,
                                         .regionSampling = regionSampling,
-                                        .treat170mAsSrgb = mTreat170mAsSrgb});
+                                        .treat170mAsSrgb = mTreat170mAsSrgb,
+                                        .dimInGammaSpaceForEnhancedScreenshots =
+                                                mDimInGammaSpaceForEnhancedScreenshots});
 
         const float colorSaturation = grayscale ? 0 : 1;
         compositionengine::CompositionRefreshArgs refreshArgs{
@@ -7883,7 +7829,7 @@
     const bool renderEngineIsThreaded = [&]() {
         using Type = renderengine::RenderEngine::RenderEngineType;
         const auto type = mRenderEngine->getRenderEngineType();
-        return type == Type::THREADED || type == Type::SKIA_GL_THREADED;
+        return type == Type::SKIA_GL_THREADED;
     }();
     auto presentFuture = renderEngineIsThreaded ? ftl::defer(std::move(present)).share()
                                                 : ftl::yield(present()).share();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 80a5d32..4d17fa7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -277,13 +277,6 @@
     // The CompositionEngine encapsulates all composition related interfaces and actions.
     compositionengine::CompositionEngine& getCompositionEngine() const;
 
-    // Obtains a name from the texture pool, or, if the pool is empty, posts a
-    // synchronous message to the main thread to obtain one on the fly
-    uint32_t getNewTexture();
-
-    // utility function to delete a texture on the main thread
-    void deleteTextureAsync(uint32_t texture);
-
     renderengine::RenderEngine& getRenderEngine() const;
 
     void onLayerFirstRef(Layer*);
@@ -324,6 +317,11 @@
     // on this behavior to increase contrast for some media sources.
     bool mTreat170mAsSrgb = false;
 
+    // If true, then screenshots with an enhanced render intent will dim in gamma space.
+    // The purpose is to ensure that screenshots appear correct during system animations for devices
+    // that require that dimming must occur in gamma space.
+    bool mDimInGammaSpaceForEnhancedScreenshots = false;
+
     // Allows to ignore physical orientation provided through hwc API in favour of
     // 'ro.surface_flinger.primary_display_orientation'.
     // TODO(b/246793311): Clean up a temporary property
@@ -1275,13 +1273,6 @@
 
     TransactionCallbackInvoker mTransactionCallbackInvoker;
 
-    // We maintain a pool of pre-generated texture names to hand out to avoid
-    // layer creation needing to run on the main thread (which it would
-    // otherwise need to do to access RenderEngine).
-    std::mutex mTexturePoolMutex;
-    uint32_t mTexturePoolSize = 0;
-    std::vector<uint32_t> mTexturePool;
-
     std::atomic<size_t> mNumLayers = 0;
 
     // to linkToDeath
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index b2d4131..ed8bb7f 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -144,9 +144,6 @@
     mFlinger->scheduleRepaint();
     mFlinger->scheduleSample();
 
-    uint32_t texture = mFlinger->getNewTexture();
-    mFlinger->deleteTextureAsync(texture);
-
     sp<IBinder> handle = defaultServiceManager()->checkService(
             String16(mFdp.ConsumeRandomLengthString().c_str()));
     LayerHandle::getLayer(handle);
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 14fa492..bdbf243 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -31,8 +31,6 @@
 #include <gui/LayerMetadata.h>
 #include <log/log.h>
 #include <renderengine/mock/FakeExternalTexture.h>
-#include <renderengine/mock/Framebuffer.h>
-#include <renderengine/mock/Image.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <system/window.h>
 #include <utils/String8.h>
@@ -599,7 +597,6 @@
                     const renderengine::LayerSettings layer = layerSettings.back();
                     EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull()));
                     EXPECT_THAT(layer.source.buffer.fence, Not(IsNull()));
-                    EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName);
                     EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha);
                     EXPECT_EQ(false, layer.source.buffer.isOpaque);
                     EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
@@ -875,15 +872,11 @@
     using FlingerLayerType = sp<Layer>;
 
     static FlingerLayerType createLayer(CompositionTest* test) {
-        test->mFlinger.mutableTexturePool().push_back(DEFAULT_TEXTURE_ID);
-
-        FlingerLayerType layer =
-                Base::template createLayerWithFactory<Layer>(test, [test]() {
-                    LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
-                                           LayerProperties::LAYER_FLAGS, LayerMetadata());
-                    args.textureName = test->mFlinger.mutableTexturePool().back();
-                    return sp<Layer>::make(args);
-                });
+        FlingerLayerType layer = Base::template createLayerWithFactory<Layer>(test, [test]() {
+            LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
+                                   LayerProperties::LAYER_FLAGS, LayerMetadata());
+            return sp<Layer>::make(args);
+        });
 
         LayerProperties::setupLayerState(test, layer);
 
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index 60ad7a3..2d87ddd 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -78,7 +78,7 @@
               mDisplay->setDesiredActiveMode(
                       {scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
     ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
-    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, mDisplay->getDesiredActiveMode()->modeOpt);
+    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredActiveMode()->modeOpt);
     EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
 
     // Setting another mode should be cached but return None
@@ -86,7 +86,7 @@
               mDisplay->setDesiredActiveMode(
                       {scheduler::FrameRateMode{120_Hz, kMode120}, Event::None}));
     ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
-    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, mDisplay->getDesiredActiveMode()->modeOpt);
+    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, *mDisplay->getDesiredActiveMode()->modeOpt);
     EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
 }
 
@@ -105,7 +105,7 @@
               mDisplay->setDesiredActiveMode(
                       {scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
     ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
-    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, mDisplay->getDesiredActiveMode()->modeOpt);
+    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredActiveMode()->modeOpt);
     EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
 
     hal::VsyncPeriodChangeConstraints constraints{
@@ -136,7 +136,7 @@
               mDisplay->setDesiredActiveMode(
                       {scheduler::FrameRateMode{90_Hz, kMode90}, Event::None}));
     ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
-    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, mDisplay->getDesiredActiveMode()->modeOpt);
+    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getDesiredActiveMode()->modeOpt);
     EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
 
     hal::VsyncPeriodChangeConstraints constraints{
@@ -154,7 +154,7 @@
               mDisplay->setDesiredActiveMode(
                       {scheduler::FrameRateMode{120_Hz, kMode120}, Event::None}));
     ASSERT_NE(std::nullopt, mDisplay->getDesiredActiveMode());
-    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, mDisplay->getDesiredActiveMode()->modeOpt);
+    EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz, *mDisplay->getDesiredActiveMode()->modeOpt);
     EXPECT_EQ(Event::None, mDisplay->getDesiredActiveMode()->event);
 
     EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, *mDisplay->getUpcomingActiveMode().modeOpt);
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index aaf55fb..0397b99 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -3125,5 +3125,69 @@
                       {DisplayModeId(kModeId60), kLowerThanMin, kLowerThanMin}));
 }
 
+// b/296079213
+TEST_P(RefreshRateSelectorTest, frameRateOverrideInBlockingZone60_120) {
+    auto selector = createSelector(kModes_60_120, kModeId120);
+
+    const FpsRange only120 = {120_Hz, 120_Hz};
+    const FpsRange allRange = {0_Hz, 120_Hz};
+    EXPECT_EQ(SetPolicyResult::Changed,
+              selector.setDisplayManagerPolicy(
+                      {kModeId120, {only120, allRange}, {allRange, allRange}}));
+
+    std::vector<LayerRequirement> layers = {{.weight = 1.f}};
+    layers[0].name = "30Hz ExplicitExactOrMultiple";
+    layers[0].desiredRefreshRate = 30_Hz;
+    layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
+
+    if (GetParam() != Config::FrameRateOverride::Enabled) {
+        EXPECT_FRAME_RATE_MODE(kMode120, 120_Hz,
+                               selector.getBestScoredFrameRate(layers).frameRateMode);
+    } else {
+        EXPECT_FRAME_RATE_MODE(kMode120, 30_Hz,
+                               selector.getBestScoredFrameRate(layers).frameRateMode);
+    }
+}
+
+TEST_P(RefreshRateSelectorTest, frameRateOverrideInBlockingZone60_90) {
+    auto selector = createSelector(kModes_60_90, kModeId90);
+
+    const FpsRange only90 = {90_Hz, 90_Hz};
+    const FpsRange allRange = {0_Hz, 90_Hz};
+    EXPECT_EQ(SetPolicyResult::Changed,
+              selector.setDisplayManagerPolicy(
+                      {kModeId90, {only90, allRange}, {allRange, allRange}}));
+
+    std::vector<LayerRequirement> layers = {{.weight = 1.f}};
+    layers[0].name = "30Hz ExplicitExactOrMultiple";
+    layers[0].desiredRefreshRate = 30_Hz;
+    layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
+
+    if (GetParam() != Config::FrameRateOverride::Enabled) {
+        EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz,
+                               selector.getBestScoredFrameRate(layers).frameRateMode);
+    } else {
+        EXPECT_FRAME_RATE_MODE(kMode90, 30_Hz,
+                               selector.getBestScoredFrameRate(layers).frameRateMode);
+    }
+}
+
+TEST_P(RefreshRateSelectorTest, frameRateOverrideInBlockingZone60_90_NonDivisor) {
+    auto selector = createSelector(kModes_60_90, kModeId90);
+
+    const FpsRange only90 = {90_Hz, 90_Hz};
+    const FpsRange allRange = {0_Hz, 90_Hz};
+    EXPECT_EQ(SetPolicyResult::Changed,
+              selector.setDisplayManagerPolicy(
+                      {kModeId90, {only90, allRange}, {allRange, allRange}}));
+
+    std::vector<LayerRequirement> layers = {{.weight = 1.f}};
+    layers[0].name = "60Hz ExplicitExactOrMultiple";
+    layers[0].desiredRefreshRate = 60_Hz;
+    layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
+
+    EXPECT_FRAME_RATE_MODE(kMode90, 90_Hz, selector.getBestScoredFrameRate(layers).frameRateMode);
+}
+
 } // namespace
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e59d44d..02fa415 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -631,7 +631,6 @@
     auto& mutableVisibleRegionsDirty() { return mFlinger->mVisibleRegionsDirty; }
     auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
     auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
-    auto& mutableTexturePool() { return mFlinger->mTexturePool; }
     auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
     auto& mutableDebugDisableHWC() { return mFlinger->mDebugDisableHWC; }
     auto& mutableMaxRenderTargetSize() { return mFlinger->mMaxRenderTargetSize; }
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
index ef9cd9b..4cfdd58 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameRateMode.h
@@ -19,5 +19,7 @@
 #include <scheduler/FrameRateMode.h>
 
 // Use a C style macro to keep the line numbers printed in gtest
-#define EXPECT_FRAME_RATE_MODE(modePtr, fps, mode) \
-    EXPECT_EQ((scheduler::FrameRateMode{(fps), (modePtr)}), (mode))
+#define EXPECT_FRAME_RATE_MODE(_modePtr, _fps, _mode)                                \
+    EXPECT_EQ((scheduler::FrameRateMode{(_fps), (_modePtr)}), (_mode))               \
+            << "Expected " << (_fps) << " (" << (_modePtr)->getFps() << ") but was " \
+            << (_mode).fps << " (" << (_mode).modePtr->getFps() << ")"
diff --git a/services/vibratorservice/VibratorCallbackScheduler.cpp b/services/vibratorservice/VibratorCallbackScheduler.cpp
index f2870b0..7eda9ef 100644
--- a/services/vibratorservice/VibratorCallbackScheduler.cpp
+++ b/services/vibratorservice/VibratorCallbackScheduler.cpp
@@ -29,8 +29,11 @@
     return mExpiration <= std::chrono::steady_clock::now();
 }
 
-DelayedCallback::Timestamp DelayedCallback::getExpiration() const {
-    return mExpiration;
+std::chrono::milliseconds DelayedCallback::getWaitForExpirationDuration() const {
+    std::chrono::milliseconds delta = std::chrono::duration_cast<std::chrono::milliseconds>(
+            mExpiration - std::chrono::steady_clock::now());
+    // Return zero if this is already expired.
+    return delta > delta.zero() ? delta : delta.zero();
 }
 
 void DelayedCallback::run() const {
@@ -88,7 +91,9 @@
             mCondition.wait(mMutex);
         } else {
             // Wait until next callback expires, or a new one is scheduled.
-            mCondition.wait_until(mMutex, mQueue.top().getExpiration());
+            // Use the monotonic steady clock to wait for the measured delay interval via wait_for
+            // instead of using a wall clock via wait_until.
+            mCondition.wait_for(mMutex, mQueue.top().getWaitForExpirationDuration());
         }
     }
 }
diff --git a/services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h b/services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h
index 2c194b5..c8ec15d 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorCallbackScheduler.h
@@ -30,15 +30,13 @@
 // Wrapper for a callback to be executed after a delay.
 class DelayedCallback {
 public:
-    using Timestamp = std::chrono::time_point<std::chrono::steady_clock>;
-
     DelayedCallback(std::function<void()> callback, std::chrono::milliseconds delay)
           : mCallback(callback), mExpiration(std::chrono::steady_clock::now() + delay) {}
     ~DelayedCallback() = default;
 
     void run() const;
     bool isExpired() const;
-    Timestamp getExpiration() const;
+    std::chrono::milliseconds getWaitForExpirationDuration() const;
 
     // Compare by expiration time, where A < B when A expires first.
     bool operator<(const DelayedCallback& other) const;
@@ -46,7 +44,9 @@
 
 private:
     std::function<void()> mCallback;
-    Timestamp mExpiration;
+    // Use a steady monotonic clock to calculate the duration until expiration.
+    // This clock is not related to wall clock time and is most suitable for measuring intervals.
+    std::chrono::time_point<std::chrono::steady_clock> mExpiration;
 };
 
 // Schedules callbacks to be executed after a delay.
diff --git a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
index 106ab9e..426cd42 100644
--- a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
+++ b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
@@ -71,15 +71,21 @@
     }
 
     int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) {
-        time_point<steady_clock> expiration = steady_clock::now() + timeout + TEST_TIMEOUT;
+        time_point<steady_clock> expirationTime = steady_clock::now() + timeout + TEST_TIMEOUT;
         int32_t expiredCallbackCount = 0;
-        while (steady_clock::now() < expiration) {
+        while (steady_clock::now() < expirationTime) {
             std::lock_guard<std::mutex> lock(mMutex);
             expiredCallbackCount = mExpiredCallbacks.size();
             if (callbackCount <= expiredCallbackCount) {
                 return expiredCallbackCount;
             }
-            mCondition.wait_until(mMutex, expiration);
+            auto currentTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(
+                    expirationTime - steady_clock::now());
+            if (currentTimeout > currentTimeout.zero()) {
+                // Use the monotonic steady clock to wait for the requested timeout via wait_for
+                // instead of using a wall clock via wait_until.
+                mCondition.wait_for(mMutex, currentTimeout);
+            }
         }
         return expiredCallbackCount;
     }
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index 523f890..d0a9da1 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -113,7 +113,7 @@
                         static_cast<long>(client_pid_));
     touchpad_->dumpInternal(result);
   }
-  write(fd, result.string(), result.size());
+  write(fd, result.c_str(), result.size());
   return OK;
 }