Clean up and fix skia-RenderEngine tests

Skia-RenderEngine tests were accidentally exercising solely
GLESRenderEngine, so the wrong backend was being used. This patch:
* Correctly enables Skia-Renderengine tests
* Adds a downcasted pointer to GLESRenderEngine to access test-only
methods so that there's no loss of test coverage
* Disables Skia tests that rely on those GLES-specific test-only
methods, since those tests were behavior-specific anyways
* Correctly destroy the Skia RenderEngine instance
* Add fixes for the remaining failing tests. Fixes include:
** Fix SkImage caching to...actually cache
** Forcing the opaque bit must occur on the SkShader, rather than on the
SkColorFilter, so that the alpha channel is not sampled when computing
the src colors.
** When only a color transform is applied but color management is
enabled, converting between RGB primaries and linear XYZ reduces down to
an identity matrix, which avoids clamping artifacts in the shader.
** Apply source dataspace properly when there are solid colors
** Support for black clearRegions for SurfaceView

Bug: 173416417
Test: librenderengine_test
Change-Id: I530441a80039c7807931985665892017e4c48e76
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 0e74c63..d69c7ae 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -79,6 +79,7 @@
     name: "librenderengine_skia_sources",
     srcs: [
         "skia/AutoBackendTexture.cpp",
+        "skia/ColorSpaces.cpp",
         "skia/SkiaRenderEngine.cpp",
         "skia/SkiaGLRenderEngine.cpp",
         "skia/debug/CaptureTimer.cpp",
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
index 2ffb547..c535597 100644
--- a/libs/renderengine/skia/AutoBackendTexture.cpp
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -20,8 +20,7 @@
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <utils/Trace.h>
-
+#include "ColorSpaces.h"
 #include "log/log_main.h"
 #include "utils/Trace.h"
 
@@ -29,47 +28,6 @@
 namespace renderengine {
 namespace skia {
 
-// Converts an android dataspace to a supported SkColorSpace
-// Supported dataspaces are
-// 1. sRGB
-// 2. Display P3
-// 3. BT2020 PQ
-// 4. BT2020 HLG
-// Unknown primaries are mapped to BT709, and unknown transfer functions
-// are mapped to sRGB.
-static sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
-    skcms_Matrix3x3 gamut;
-    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
-        case HAL_DATASPACE_STANDARD_BT709:
-            gamut = SkNamedGamut::kSRGB;
-            break;
-        case HAL_DATASPACE_STANDARD_BT2020:
-            gamut = SkNamedGamut::kRec2020;
-            break;
-        case HAL_DATASPACE_STANDARD_DCI_P3:
-            gamut = SkNamedGamut::kDisplayP3;
-            break;
-        default:
-            ALOGV("Unsupported Gamut: %d, defaulting to sRGB", dataspace);
-            gamut = SkNamedGamut::kSRGB;
-            break;
-    }
-
-    switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
-        case HAL_DATASPACE_TRANSFER_LINEAR:
-            return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
-        case HAL_DATASPACE_TRANSFER_SRGB:
-            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
-        case HAL_DATASPACE_TRANSFER_ST2084:
-            return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
-        case HAL_DATASPACE_TRANSFER_HLG:
-            return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
-        default:
-            ALOGV("Unsupported Gamma: %d, defaulting to sRGB transfer", dataspace);
-            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
-    }
-}
-
 AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer,
                                        bool isRender) {
     ATRACE_CALL();
diff --git a/libs/renderengine/skia/ColorSpaces.cpp b/libs/renderengine/skia/ColorSpaces.cpp
new file mode 100644
index 0000000..ff4d348
--- /dev/null
+++ b/libs/renderengine/skia/ColorSpaces.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#include "ColorSpaces.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace) {
+    skcms_Matrix3x3 gamut;
+    switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
+        case HAL_DATASPACE_STANDARD_BT709:
+            gamut = SkNamedGamut::kSRGB;
+            break;
+        case HAL_DATASPACE_STANDARD_BT2020:
+            gamut = SkNamedGamut::kRec2020;
+            break;
+        case HAL_DATASPACE_STANDARD_DCI_P3:
+            gamut = SkNamedGamut::kDisplayP3;
+            break;
+        default:
+            gamut = SkNamedGamut::kSRGB;
+            break;
+    }
+
+    switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
+        case HAL_DATASPACE_TRANSFER_LINEAR:
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
+        case HAL_DATASPACE_TRANSFER_SRGB:
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
+        case HAL_DATASPACE_TRANSFER_ST2084:
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
+        case HAL_DATASPACE_TRANSFER_HLG:
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
+        default:
+            return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
+    }
+}
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/ColorSpaces.h b/libs/renderengine/skia/ColorSpaces.h
new file mode 100644
index 0000000..2cbdeb8
--- /dev/null
+++ b/libs/renderengine/skia/ColorSpaces.h
@@ -0,0 +1,38 @@
+/*
+ * 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 "SkColorSpace.h"
+#include "ui/GraphicTypes.h"
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+// Converts an android dataspace to a supported SkColorSpace
+// Supported dataspaces are
+// 1. sRGB
+// 2. Display P3
+// 3. BT2020 PQ
+// 4. BT2020 HLG
+// Unknown primaries are mapped to BT709, and unknown transfer functions
+// are mapped to sRGB.
+sk_sp<SkColorSpace> toSkColorSpace(ui::Dataspace dataspace);
+
+} // namespace skia
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index d9495a9..dc04f69 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -30,6 +30,7 @@
 #include <SkColorSpace.h>
 #include <SkImage.h>
 #include <SkImageFilters.h>
+#include <SkRegion.h>
 #include <SkShadowUtils.h>
 #include <SkSurface.h>
 #include <gl/GrGLInterface.h>
@@ -43,6 +44,7 @@
 #include <memory>
 
 #include "../gl/GLExtensions.h"
+#include "ColorSpaces.h"
 #include "SkBlendMode.h"
 #include "SkImageInfo.h"
 #include "filters/BlurFilter.h"
@@ -281,6 +283,44 @@
     if (args.supportsBackgroundBlur) {
         mBlurFilter = new BlurFilter();
     }
+    mCapture = std::make_unique<SkiaCapture>();
+}
+
+SkiaGLRenderEngine::~SkiaGLRenderEngine() {
+    std::lock_guard<std::mutex> lock(mRenderingMutex);
+    mRuntimeEffects.clear();
+    mProtectedTextureCache.clear();
+    mTextureCache.clear();
+
+    if (mBlurFilter) {
+        delete mBlurFilter;
+    }
+
+    mCapture = nullptr;
+
+    mGrContext->flushAndSubmit(true);
+    mGrContext->abandonContext();
+
+    if (mProtectedGrContext) {
+        mProtectedGrContext->flushAndSubmit(true);
+        mProtectedGrContext->abandonContext();
+    }
+
+    if (mPlaceholderSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mPlaceholderSurface);
+    }
+    if (mProtectedPlaceholderSurface != EGL_NO_SURFACE) {
+        eglDestroySurface(mEGLDisplay, mProtectedPlaceholderSurface);
+    }
+    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();
 }
 
 bool SkiaGLRenderEngine::supportsProtectedContent() const {
@@ -298,6 +338,7 @@
             useProtectedContext ? mProtectedPlaceholderSurface : mPlaceholderSurface;
     const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
     const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
+
     if (success) {
         mInProtectedContext = useProtectedContext;
     }
@@ -450,6 +491,7 @@
                                         const bool useFramebufferCache,
                                         base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
     ATRACE_NAME("SkiaGL::drawLayers");
+
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     if (layers.empty()) {
         ALOGV("Drawing empty layer stack");
@@ -488,7 +530,7 @@
     if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) {
         surfaceTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
         surfaceTextureRef->setTexture(
-                new AutoBackendTexture(mGrContext.get(), buffer->toAHardwareBuffer(), true));
+                new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true));
         if (useFramebufferCache) {
             ALOGD("Adding to cache");
             cache.insert({buffer->getId(), surfaceTextureRef});
@@ -498,10 +540,10 @@
     sk_sp<SkSurface> surface =
             surfaceTextureRef->getTexture()->getOrCreateSurface(mUseColorManagement
                                                                         ? display.outputDataspace
-                                                                        : ui::Dataspace::SRGB,
-                                                                mGrContext.get());
+                                                                        : ui::Dataspace::UNKNOWN,
+                                                                grContext.get());
 
-    SkCanvas* canvas = mCapture.tryCapture(surface.get());
+    SkCanvas* canvas = mCapture->tryCapture(surface.get());
     if (canvas == nullptr) {
         ALOGE("Cannot acquire canvas from Skia.");
         return BAD_VALUE;
@@ -510,7 +552,7 @@
     canvas->clear(SK_ColorTRANSPARENT);
     canvas->save();
 
-    if (mCapture.isCaptureRunning()) {
+    if (mCapture->isCaptureRunning()) {
         // Record display settings when capture is running.
         std::stringstream displaySettings;
         PrintTo(display, &displaySettings);
@@ -546,10 +588,33 @@
     canvas->rotate(toDegrees(display.orientation));
     canvas->translate(-clipWidth / 2, -clipHeight / 2);
     canvas->translate(-display.clip.left, -display.clip.top);
+
+    // TODO: clearRegion was required for SurfaceView when a buffer is not yet available but the
+    // view is still on-screen. The clear region could be re-specified as a black color layer,
+    // however.
+    if (!display.clearRegion.isEmpty()) {
+        size_t numRects = 0;
+        Rect const* rects = display.clearRegion.getArray(&numRects);
+        SkIRect skRects[numRects];
+        for (int i = 0; i < numRects; ++i) {
+            skRects[i] =
+                    SkIRect::MakeLTRB(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
+        }
+        SkRegion clearRegion;
+        SkPaint paint;
+        sk_sp<SkShader> shader =
+                SkShaders::Color(SkColor4f{.fR = 0., .fG = 0., .fB = 0., .fA = 1.0},
+                                 toSkColorSpace(mUseColorManagement ? display.outputDataspace
+                                                                    : ui::Dataspace::UNKNOWN));
+        paint.setShader(shader);
+        clearRegion.setRects(skRects, numRects);
+        canvas->drawRegion(clearRegion, paint);
+    }
+
     for (const auto& layer : layers) {
         canvas->save();
 
-        if (mCapture.isCaptureRunning()) {
+        if (mCapture->isCaptureRunning()) {
             // Record the name of the layer if the capture is running.
             std::stringstream layerSettings;
             PrintTo(*layer, &layerSettings);
@@ -588,6 +653,16 @@
             }
         }
 
+        const ui::Dataspace targetDataspace = mUseColorManagement
+                ? (needsLinearEffect(layer->colorTransform, layer->sourceDataspace,
+                                     display.outputDataspace)
+                           // If we need to map to linear space, then mark the source image with the
+                           // same colorspace as the destination surface so that Skia's color
+                           // management is a no-op.
+                           ? display.outputDataspace
+                           : layer->sourceDataspace)
+                : ui::Dataspace::UNKNOWN;
+
         if (layer->source.buffer.buffer) {
             ATRACE_NAME("DrawImage");
             const auto& item = layer->source.buffer;
@@ -597,31 +672,18 @@
                 imageTextureRef = iter->second;
             } else {
                 imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>();
-                imageTextureRef->setTexture(new AutoBackendTexture(mGrContext.get(),
+                imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(),
                                                                    item.buffer->toAHardwareBuffer(),
                                                                    false));
-                mTextureCache.insert({buffer->getId(), imageTextureRef});
+                mTextureCache.insert({item.buffer->getId(), imageTextureRef});
             }
 
             sk_sp<SkImage> image =
-                    imageTextureRef->getTexture()
-                            ->makeImage(mUseColorManagement
-                                                ? (needsLinearEffect(layer->colorTransform,
-                                                                     layer->sourceDataspace,
-                                                                     display.outputDataspace)
-                                                           // If we need to map to linear space,
-                                                           // then mark the source image with the
-                                                           // same colorspace as the destination
-                                                           // surface so that Skia's color
-                                                           // management is a no-op.
-                                                           ? display.outputDataspace
-                                                           : layer->sourceDataspace)
-                                                : ui::Dataspace::SRGB,
-                                        item.isOpaque ? kOpaque_SkAlphaType
-                                                      : (item.usePremultipliedAlpha
-                                                                 ? kPremul_SkAlphaType
-                                                                 : kUnpremul_SkAlphaType),
-                                        mGrContext.get());
+                    imageTextureRef->getTexture()->makeImage(targetDataspace,
+                                                             item.usePremultipliedAlpha
+                                                                     ? kPremul_SkAlphaType
+                                                                     : kUnpremul_SkAlphaType,
+                                                             grContext.get());
 
             auto texMatrix = getSkM44(item.textureTransform).asM33();
             // textureTansform was intended to be passed directly into a shader, so when
@@ -650,11 +712,35 @@
                 shader = image->makeShader(SkSamplingOptions(), matrix);
             }
 
+            // Handle opaque images - it's a little nonstandard how we do this.
+            // Fundamentally we need to support SurfaceControl.Builder#setOpaque:
+            // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
+            // The important language is that when isOpaque is set, opacity is not sampled from the
+            // alpha channel, but blending may still be supported on a transaction via setAlpha. So,
+            // here's the conundrum:
+            // 1. We can't force the SkImage alpha type to kOpaque_SkAlphaType, because it's treated
+            // as an internal hint - composition is undefined when there are alpha bits present.
+            // 2. We can try to lie about the pixel layout, but that only works for RGBA8888
+            // buffers, i.e., treating them as RGBx8888 instead. But we can't do the same for
+            // RGBA1010102 because RGBx1010102 is not supported as a pixel layout for SkImages. It's
+            // also not clear what to use for F16 either, and lying about the pixel layout is a bit
+            // of a hack anyways.
+            // 3. We can't change the blendmode to src, because while this satisfies the requirement
+            // for ignoring the alpha channel, it doesn't quite satisfy the blending requirement
+            // because src always clobbers the destination content.
+            //
+            // So, what we do here instead is an additive blend mode where we compose the input
+            // image with a solid black. This might need to be reassess if this does not support
+            // FP16 incredibly well, but FP16 end-to-end isn't well supported anyway at the moment.
+            if (item.isOpaque) {
+                shader = SkShaders::Blend(SkBlendMode::kPlus, shader,
+                                          SkShaders::Color(SkColors::kBlack,
+                                                           toSkColorSpace(targetDataspace)));
+            }
+
             paint.setShader(
                     createRuntimeEffectShader(shader, layer, display,
                                               !item.isOpaque && item.usePremultipliedAlpha));
-
-            // Make sure to take into the account the alpha set on the layer.
             paint.setAlphaf(layer->alpha);
         } else {
             ATRACE_NAME("DrawColor");
@@ -662,8 +748,8 @@
             sk_sp<SkShader> shader = SkShaders::Color(SkColor4f{.fR = color.r,
                                                                 .fG = color.g,
                                                                 .fB = color.b,
-                                                                layer->alpha},
-                                                      nullptr);
+                                                                .fA = layer->alpha},
+                                                      toSkColorSpace(targetDataspace));
             paint.setShader(createRuntimeEffectShader(shader, layer, display,
                                                       /* undoPremultipliedAlpha */ false));
         }
@@ -671,31 +757,6 @@
         sk_sp<SkColorFilter> filter =
                 SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform));
 
-        // Handle opaque images - it's a little nonstandard how we do this.
-        // Fundamentally we need to support SurfaceControl.Builder#setOpaque:
-        // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
-        // The important language is that when isOpaque is set, opacity is not sampled from the
-        // alpha channel, but blending may still be supported on a transaction via setAlpha. So,
-        // here's the conundrum:
-        // 1. We can't force the SkImage alpha type to kOpaque_SkAlphaType, because it's treated as
-        // an internal hint - composition is undefined when there are alpha bits present.
-        // 2. We can try to lie about the pixel layout, but that only works for RGBA8888 buffers,
-        // i.e., treating them as RGBx8888 instead. But we can't do the same for RGBA1010102 because
-        // RGBx1010102 is not supported as a pixel layout for SkImages. It's also not clear what to
-        // use for F16 either, and lying about the pixel layout is a bit of a hack anyways.
-        // 3. We can't change the blendmode to src, because while this satisfies the requirement for
-        // ignoring the alpha channel, it doesn't quite satisfy the blending requirement because
-        // src always clobbers the destination content.
-        //
-        // So, what we do here instead is an additive blend mode where we compose the input image
-        // with a solid black. This might need to be reassess if this does not support FP16
-        // incredibly well, but FP16 end-to-end isn't well supported anyway at the moment.
-        if (layer->source.buffer.buffer && layer->source.buffer.isOpaque) {
-            filter = SkColorFilters::Compose(filter,
-                                             SkColorFilters::Blend(SK_ColorBLACK,
-                                                                   SkBlendMode::kPlus));
-        }
-
         paint.setColorFilter(filter);
 
         for (const auto effectRegion : layer->blurRegions) {
@@ -721,7 +782,7 @@
         canvas->restore();
     }
     canvas->restore();
-    mCapture.endCapture();
+    mCapture->endCapture();
     {
         ATRACE_NAME("flush surface");
         surface->flush();
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 5384ec8..ed62a2a 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -34,9 +34,9 @@
 #include "SkImageInfo.h"
 #include "SkiaRenderEngine.h"
 #include "android-base/macros.h"
+#include "debug/SkiaCapture.h"
 #include "filters/BlurFilter.h"
-#include "skia/debug/SkiaCapture.h"
-#include "skia/filters/LinearEffect.h"
+#include "filters/LinearEffect.h"
 
 namespace android {
 namespace renderengine {
@@ -48,7 +48,7 @@
     SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt,
                        EGLSurface placeholder, EGLContext protectedContext,
                        EGLSurface protectedPlaceholder);
-    ~SkiaGLRenderEngine() override{};
+    ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex);
 
     void unbindExternalTextureBuffer(uint64_t bufferId) override;
     status_t drawLayers(const DisplaySettings& display,
@@ -127,7 +127,7 @@
 
     bool mInProtectedContext = false;
     // Object to capture commands send to Skia.
-    SkiaCapture mCapture;
+    std::unique_ptr<SkiaCapture> mCapture;
 };
 
 } // namespace skia
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 7680649..84af016 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -454,11 +454,18 @@
 
     effectBuilder.child("input") = shader;
 
-    ColorSpace inputColorSpace = toColorSpace(linearEffect.inputDataspace);
-    ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
+    if (linearEffect.inputDataspace == linearEffect.outputDataspace) {
+        effectBuilder.uniform("in_rgbToXyz") = mat4();
+        effectBuilder.uniform("in_xyzToRgb") = colorTransform;
+    } else {
+        ColorSpace inputColorSpace = toColorSpace(linearEffect.inputDataspace);
+        ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
 
-    effectBuilder.uniform("in_rgbToXyz") = mat4(inputColorSpace.getRGBtoXYZ());
-    effectBuilder.uniform("in_xyzToRgb") = colorTransform * mat4(outputColorSpace.getXYZtoRGB());
+        effectBuilder.uniform("in_rgbToXyz") = mat4(inputColorSpace.getRGBtoXYZ());
+        effectBuilder.uniform("in_xyzToRgb") =
+                colorTransform * mat4(outputColorSpace.getXYZtoRGB());
+    }
+
     effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
     effectBuilder.uniform("in_inputMaxLuminance") =
             std::min(maxMasteringLuminance, maxContentLuminance);
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index bcf389b..51c7028 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -14,17 +14,21 @@
 
 cc_test {
     name: "librenderengine_test",
-    defaults: ["surfaceflinger_defaults"],
+    defaults: ["skia_deps", "surfaceflinger_defaults"],
     test_suites: ["device-tests"],
     srcs: [
         "RenderEngineTest.cpp",
         "RenderEngineThreadedTest.cpp",
     ],
+    include_dirs: [
+        "external/skia/src/gpu",
+    ],
     static_libs: [
         "libgmock",
         "librenderengine",
         "librenderengine_mocks",
     ],
+
     shared_libs: [
         "libbase",
         "libcutils",
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 2b8063e..58afe6e 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -22,16 +22,18 @@
 #pragma clang diagnostic ignored "-Wconversion"
 #pragma clang diagnostic ignored "-Wextra"
 
-#include <chrono>
-#include <condition_variable>
-#include <fstream>
-
 #include <cutils/properties.h>
 #include <gtest/gtest.h>
 #include <renderengine/RenderEngine.h>
 #include <sync/sync.h>
 #include <ui/PixelFormat.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <fstream>
+
 #include "../gl/GLESRenderEngine.h"
+#include "../skia/SkiaGLRenderEngine.h"
 #include "../threaded/RenderEngineThreaded.h"
 
 constexpr int DEFAULT_DISPLAY_WIDTH = 128;
@@ -46,14 +48,26 @@
     virtual ~RenderEngineFactory() = default;
 
     virtual std::string name() = 0;
-    virtual std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() = 0;
+    virtual renderengine::RenderEngine::RenderEngineType type() = 0;
+    virtual std::unique_ptr<renderengine::RenderEngine> createRenderEngine() = 0;
+    virtual std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() {
+        return nullptr;
+    }
 };
 
 class GLESRenderEngineFactory : public RenderEngineFactory {
 public:
     std::string name() override { return "GLESRenderEngineFactory"; }
 
-    std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() override {
+    renderengine::RenderEngine::RenderEngineType type() {
+        return renderengine::RenderEngine::RenderEngineType::GLES;
+    }
+
+    std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
+        return createGLESRenderEngine();
+    }
+
+    std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() {
         renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
                         .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
@@ -63,7 +77,7 @@
                         .setPrecacheToneMapperShaderOnly(false)
                         .setSupportsBackgroundBlur(true)
                         .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
-                        .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::GLES)
+                        .setRenderEngineType(type())
                         .build();
         return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
     }
@@ -73,7 +87,15 @@
 public:
     std::string name() override { return "GLESCMRenderEngineFactory"; }
 
-    std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() override {
+    renderengine::RenderEngine::RenderEngineType type() {
+        return renderengine::RenderEngine::RenderEngineType::GLES;
+    }
+
+    std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
+        return createGLESRenderEngine();
+    }
+
+    std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() override {
         renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
                         .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
@@ -82,7 +104,7 @@
                         .setPrecacheToneMapperShaderOnly(false)
                         .setSupportsBackgroundBlur(true)
                         .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
-                        .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::GLES)
+                        .setRenderEngineType(type())
                         .setUseColorManagerment(true)
                         .build();
         return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
@@ -91,9 +113,13 @@
 
 class SkiaGLESRenderEngineFactory : public RenderEngineFactory {
 public:
-    std::string name() override { return "SkiaGLESRenderEngineFactory"; }
+    std::string name() override { return "SkiaGLRenderEngineFactory"; }
 
-    std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() override {
+    renderengine::RenderEngine::RenderEngineType type() {
+        return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
+    }
+
+    std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
         renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
                         .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
@@ -102,17 +128,21 @@
                         .setPrecacheToneMapperShaderOnly(false)
                         .setSupportsBackgroundBlur(true)
                         .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
-                        .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::SKIA_GL)
+                        .setRenderEngineType(type())
                         .build();
-        return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
+        return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
     }
 };
 
 class SkiaGLESCMRenderEngineFactory : public RenderEngineFactory {
 public:
-    std::string name() override { return "SkiaGLESCMRenderEngineFactory"; }
+    std::string name() override { return "SkiaGLCMRenderEngineFactory"; }
 
-    std::unique_ptr<renderengine::gl::GLESRenderEngine> createRenderEngine() override {
+    renderengine::RenderEngine::RenderEngineType type() {
+        return renderengine::RenderEngine::RenderEngineType::SKIA_GL;
+    }
+
+    std::unique_ptr<renderengine::RenderEngine> createRenderEngine() override {
         renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
                         .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
@@ -121,10 +151,10 @@
                         .setPrecacheToneMapperShaderOnly(false)
                         .setSupportsBackgroundBlur(true)
                         .setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
-                        .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::SKIA_GL)
+                        .setRenderEngineType(type())
                         .setUseColorManagerment(true)
                         .build();
-        return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
+        return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
     }
 };
 
@@ -134,7 +164,7 @@
         return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
                                  HAL_PIXEL_FORMAT_RGBA_8888, 1,
                                  GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
-                                         GRALLOC_USAGE_HW_RENDER,
+                                         GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE,
                                  "output");
     }
 
@@ -159,7 +189,9 @@
         }
         for (uint32_t texName : mTexNames) {
             mRE->deleteTextures(1, &texName);
-            EXPECT_FALSE(mRE->isTextureNameKnownForTesting(texName));
+            if (mGLESRE != nullptr) {
+                EXPECT_FALSE(mGLESRE->isTextureNameKnownForTesting(texName));
+            }
         }
         const ::testing::TestInfo* const test_info =
                 ::testing::UnitTest::GetInstance()->current_test_info();
@@ -351,12 +383,11 @@
     }
 
     void invokeDraw(renderengine::DisplaySettings settings,
-                    std::vector<const renderengine::LayerSettings*> layers,
-                    sp<GraphicBuffer> buffer) {
+                    std::vector<const renderengine::LayerSettings*> layers) {
         base::unique_fd fence;
         status_t status =
-                mRE->drawLayers(settings, layers, buffer, true, base::unique_fd(), &fence);
-        mCurrentBuffer = buffer;
+                mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence);
+        mCurrentBuffer = mBuffer;
 
         int fd = fence.release();
         if (fd >= 0) {
@@ -365,17 +396,15 @@
         }
 
         ASSERT_EQ(NO_ERROR, status);
-        if (layers.size() > 0) {
-            ASSERT_TRUE(mRE->isFramebufferImageCachedForTesting(buffer->getId()));
+        if (layers.size() > 0 && mGLESRE != nullptr) {
+            ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
         }
     }
 
     void drawEmptyLayers() {
         renderengine::DisplaySettings settings;
         std::vector<const renderengine::LayerSettings*> layers;
-        // Meaningless buffer since we don't do any drawing
-        sp<GraphicBuffer> buffer = new GraphicBuffer();
-        invokeDraw(settings, layers, buffer);
+        invokeDraw(settings, layers);
     }
 
     template <typename SourceVariant>
@@ -471,7 +500,12 @@
                                  const renderengine::ShadowSettings& shadow,
                                  const ubyte4& backgroundColor);
 
-    std::unique_ptr<renderengine::gl::GLESRenderEngine> mRE;
+    void initializeRenderEngine();
+
+    std::unique_ptr<renderengine::RenderEngine> mRE;
+    // GLESRenderEngine for testing GLES-specific behavior.
+    // Owened by mRE, but this is downcasted.
+    renderengine::gl::GLESRenderEngine* mGLESRE = nullptr;
 
     // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to
     // be freed *after* RenderEngine is destroyed, so that the EGL image is
@@ -483,6 +517,21 @@
     std::vector<uint32_t> mTexNames;
 };
 
+void RenderEngineTest::initializeRenderEngine() {
+    const auto& renderEngineFactory = GetParam();
+    if (renderEngineFactory->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+        // Only GLESRenderEngine exposes test-only methods. Provide a pointer to the
+        // GLESRenderEngine if we're using it so that we don't need to dynamic_cast
+        // every time.
+        std::unique_ptr<renderengine::gl::GLESRenderEngine> renderEngine =
+                renderEngineFactory->createGLESRenderEngine();
+        mGLESRE = renderEngine.get();
+        mRE = std::move(renderEngine);
+    } else {
+        mRE = renderEngineFactory->createRenderEngine();
+    }
+}
+
 struct ColorSourceVariant {
     static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
                           RenderEngineTest* /*fixture*/) {
@@ -509,7 +558,7 @@
     static uint8_t getAlphaChannel() {
         // The isOpaque bit will override the alpha channel, so this should be
         // arbitrary.
-        return 10;
+        return 50;
     }
 };
 
@@ -563,7 +612,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -606,7 +655,7 @@
     layer.alpha = 1.0f;
 
     layers.push_back(&layer);
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -659,7 +708,7 @@
     layers.push_back(&layerTwo);
     layers.push_back(&layerThree);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -747,7 +796,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -786,7 +835,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -816,7 +865,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -844,7 +893,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 template <typename SourceVariant>
@@ -904,7 +953,7 @@
     blurLayer.alpha = 0;
     layers.push_back(&blurLayer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 
     expectBufferColor(Rect(center - 1, center - 5, center, center + 5), 150, 150, 0, 255,
                       50 /* tolerance */);
@@ -929,7 +978,7 @@
     layerOne.alpha = 0.2;
 
     layersFirst.push_back(&layerOne);
-    invokeDraw(settings, layersFirst, mBuffer);
+    invokeDraw(settings, layersFirst);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
                            DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
@@ -945,7 +994,7 @@
     layerTwo.alpha = 1.0f;
 
     layersSecond.push_back(&layerTwo);
-    invokeDraw(settings, layersSecond, mBuffer);
+    invokeDraw(settings, layersSecond);
 
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
@@ -997,7 +1046,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 void RenderEngineTest::fillBufferTextureTransform() {
@@ -1036,7 +1085,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 void RenderEngineTest::fillBufferWithPremultiplyAlpha() {
@@ -1075,7 +1124,7 @@
 
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() {
@@ -1093,7 +1142,7 @@
     // fake layer, without bounds should not render anything
     renderengine::LayerSettings layer;
     layers.push_back(&layer);
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 void RenderEngineTest::clearRegion() {
@@ -1140,7 +1189,7 @@
                              casterColor.b / 255.0f, this);
     layers.push_back(&layer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds,
@@ -1171,7 +1220,7 @@
     shadowLayer.shadow = shadow;
     layers.push_back(&shadowLayer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 }
 
 INSTANTIATE_TEST_SUITE_P(PerRenderEngineType, RenderEngineTest,
@@ -1181,8 +1230,7 @@
                                          std::make_shared<SkiaGLESCMRenderEngineFactory>()));
 
 TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
     drawEmptyLayers();
 }
 
@@ -1210,16 +1258,15 @@
     std::vector<const renderengine::LayerSettings*> layers;
     layers.push_back(&bgLayer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 
     // Expect to see full opaque pixel (with inverted red from the transform).
-    expectBufferColor(Rect(0, 0, 1, 1), 0.f, backgroundColor.g, backgroundColor.b,
+    expectBufferColor(Rect(0, 0, 10, 10), 0.f, backgroundColor.g, backgroundColor.b,
                       backgroundColor.a);
 }
 
 TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1235,8 +1282,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_nullOutputFence) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1258,7 +1304,13 @@
 
 TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1275,355 +1327,264 @@
     status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr);
     mCurrentBuffer = mBuffer;
     ASSERT_EQ(NO_ERROR, status);
-    ASSERT_FALSE(mRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
+    ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId()));
     expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedBuffer<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillGreenBuffer<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBlueBuffer<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedTransparentBuffer<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferPhysicalOffset<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate0<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate90<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate180<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate270<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferLayerTransform<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferColorTransform<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferWithRoundedCorners<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferColorTransformZeroLayerAlpha<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferAndBlurBackground<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_overlayCorners_colorSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     overlayCorners<ColorSourceVariant>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferColorTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
-TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
 
+TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_opaqueBufferSource) {
+    initializeRenderEngine();
     fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferAndBlurBackground<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     overlayCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferColorTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferColorTransformZeroLayerAlpha_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferColorTransformZeroLayerAlpha<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferAndBlurBackground_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferAndBlurBackground<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_overlayCorners_bufferSource) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     overlayCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferTextureTransform();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferWithPremultiplyAlpha();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     fillBufferWithoutPremultiplyAlpha();
 }
 
 TEST_P(RenderEngineTest, drawLayers_clearRegion) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
-
+    initializeRenderEngine();
     clearRegion();
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1637,26 +1598,32 @@
     BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
 
     layers.push_back(&layer);
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
     uint64_t bufferId = layer.source.buffer.buffer->getId();
-    EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
+    EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId));
     std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
-            mRE->unbindExternalTextureBufferForTesting(bufferId);
+            mGLESRE->unbindExternalTextureBufferForTesting(bufferId);
     std::lock_guard<std::mutex> lock(barrier->mutex);
     ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
                                             [&]() REQUIRES(barrier->mutex) {
                                                 return barrier->isOpen;
                                             }));
-    EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
+    EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId));
     EXPECT_EQ(NO_ERROR, barrier->result);
 }
 
 TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
-            mRE->cacheExternalTextureBufferForTesting(nullptr);
+            mGLESRE->cacheExternalTextureBufferForTesting(nullptr);
     std::lock_guard<std::mutex> lock(barrier->mutex);
     ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
                                             [&]() REQUIRES(barrier->mutex) {
@@ -1668,12 +1635,18 @@
 
 TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
     uint64_t bufferId = buf->getId();
     std::shared_ptr<renderengine::gl::ImageManager::Barrier> barrier =
-            mRE->cacheExternalTextureBufferForTesting(buf);
+            mGLESRE->cacheExternalTextureBufferForTesting(buf);
     {
         std::lock_guard<std::mutex> lock(barrier->mutex);
         ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
@@ -1682,8 +1655,8 @@
                                                 }));
         EXPECT_EQ(NO_ERROR, barrier->result);
     }
-    EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
-    barrier = mRE->unbindExternalTextureBufferForTesting(bufferId);
+    EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId));
+    barrier = mGLESRE->unbindExternalTextureBufferForTesting(bufferId);
     {
         std::lock_guard<std::mutex> lock(barrier->mutex);
         ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5),
@@ -1692,12 +1665,11 @@
                                                 }));
         EXPECT_EQ(NO_ERROR, barrier->result);
     }
-    EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
+    EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId));
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 backgroundColor(255, 255, 255, 255);
     const float shadowLength = 5.0f;
@@ -1712,8 +1684,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_casterLayerMinSize) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 casterColor(255, 0, 0, 255);
     const ubyte4 backgroundColor(255, 255, 255, 255);
@@ -1732,8 +1703,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_casterColorLayer) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 casterColor(255, 0, 0, 255);
     const ubyte4 backgroundColor(255, 255, 255, 255);
@@ -1753,8 +1723,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_casterOpaqueBufferLayer) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 casterColor(255, 0, 0, 255);
     const ubyte4 backgroundColor(255, 255, 255, 255);
@@ -1775,8 +1744,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_casterWithRoundedCorner) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 casterColor(255, 0, 0, 255);
     const ubyte4 backgroundColor(255, 255, 255, 255);
@@ -1798,8 +1766,7 @@
 }
 
 TEST_P(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     const ubyte4 casterColor(255, 0, 0, 255);
     const ubyte4 backgroundColor(255, 255, 255, 255);
@@ -1827,7 +1794,13 @@
 
 TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
@@ -1859,7 +1832,13 @@
 
 TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) {
     const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+
+    if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
+        // GLES-specific test
+        return;
+    }
+
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
@@ -1883,20 +1862,19 @@
 
     uint64_t bufferId = layer.source.buffer.buffer->getId();
     uint32_t texName = layer.source.buffer.textureName;
-    EXPECT_TRUE(mRE->isImageCachedForTesting(bufferId));
-    EXPECT_EQ(bufferId, mRE->getBufferIdForTextureNameForTesting(texName));
+    EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId));
+    EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName));
 
     EXPECT_TRUE(mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL));
 
     // Now check that our view of memory is good.
-    EXPECT_FALSE(mRE->isImageCachedForTesting(bufferId));
-    EXPECT_EQ(std::nullopt, mRE->getBufferIdForTextureNameForTesting(bufferId));
-    EXPECT_TRUE(mRE->isTextureNameKnownForTesting(texName));
+    EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId));
+    EXPECT_EQ(std::nullopt, mGLESRE->getBufferIdForTextureNameForTesting(bufferId));
+    EXPECT_TRUE(mGLESRE->isTextureNameKnownForTesting(texName));
 }
 
 TEST_P(RenderEngineTest, testRoundedCornersCrop) {
-    const auto& renderEngineFactory = GetParam();
-    mRE = renderEngineFactory->createRenderEngine();
+    initializeRenderEngine();
 
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
@@ -1931,7 +1909,7 @@
 
     layers.push_back(&greenLayer);
 
-    invokeDraw(settings, layers, mBuffer);
+    invokeDraw(settings, layers);
 
     // Corners should be ignored...
     // Screen size: width is 128, height is 256.