SF: Separate RenderEngine into interface and impl

This allows the RenderEngine to be substituted by a GMock for tests.

RE::RenderEngine is now a pure virtual interface class.
RE::impl::RenderEngine is the normal/base implementation.

Similarly, RE::Image and RE::Surface are pure virtual interfaces.
RE::impl::Image and RE::impl::Surface are the normal implementations.

Test: Builds
Bug: None
Change-Id: Ib5e658df4bb4efc1a9c0ae95feaf0c1e052cdc94
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 4d4c9fc..3dbc136 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -200,7 +200,7 @@
 
     bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
 
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
@@ -817,7 +817,7 @@
     texCoords[2] = vec2(right, 1.0f - bottom);
     texCoords[3] = vec2(right, 1.0f - top);
 
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
                               getColor());
     engine.setSourceDataSpace(mCurrentState.dataSpace);
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 4d9b43f..46ec0e3 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -23,6 +23,7 @@
 
 #include "DispSync.h"
 #include "Layer.h"
+#include "RenderEngine/Image.h"
 #include "RenderEngine/RenderEngine.h"
 
 #include <inttypes.h>
@@ -56,8 +57,8 @@
 
 static const mat4 mtxIdentity;
 
-BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine,
-                                         uint32_t tex, Layer* layer)
+BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
+                                         RE::RenderEngine& engine, uint32_t tex, Layer* layer)
       : ConsumerBase(bq, false),
         mCurrentCrop(Rect::EMPTY_RECT),
         mCurrentTransform(0),
@@ -359,7 +360,7 @@
 
     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
         BLC_LOGE("bindTextureImage: no currently-bound texture");
-        mRE.bindExternalTextureImage(mTexName, RE::Image(mRE));
+        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
         return NO_INIT;
     }
 
@@ -367,7 +368,7 @@
     status_t err = mCurrentTextureImage->createIfNeeded(imageCrop);
     if (err != NO_ERROR) {
         BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
-        mRE.bindExternalTextureImage(mTexName, RE::Image(mRE));
+        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
         return UNKNOWN_ERROR;
     }
 
@@ -604,13 +605,15 @@
     ConsumerBase::dumpLocked(result, prefix);
 }
 
-BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, const RenderEngine& engine)
+BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine)
       : mGraphicBuffer(graphicBuffer),
-        mImage{engine},
+        mImage{engine.createImage()},
         mCreated(false),
         mCropWidth(0),
         mCropHeight(0) {}
 
+BufferLayerConsumer::Image::~Image() = default;
+
 status_t BufferLayerConsumer::Image::createIfNeeded(const Rect& imageCrop) {
     const int32_t cropWidth = imageCrop.width();
     const int32_t cropHeight = imageCrop.height();
@@ -618,9 +621,9 @@
         return OK;
     }
 
-    mCreated = mImage.setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
-                                            mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED,
-                                            cropWidth, cropHeight);
+    mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
+                                             mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED,
+                                             cropWidth, cropHeight);
     if (mCreated) {
         mCropWidth = cropWidth;
         mCropHeight = cropHeight;
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index a0272b3..11048d8 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_BUFFERLAYERCONSUMER_H
 #define ANDROID_BUFFERLAYERCONSUMER_H
 
-#include "RenderEngine/Image.h"
-
 #include <gui/BufferQueueDefs.h>
 #include <gui/ConsumerBase.h>
 #include <gui/HdrMetadata.h>
@@ -36,9 +34,13 @@
 
 class DispSync;
 class Layer;
-class RenderEngine;
 class String8;
 
+namespace RE {
+class RenderEngine;
+class Image;
+} // namespace RE
+
 /*
  * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue,
  * and makes them available to RenderEngine as a texture.
@@ -70,8 +72,8 @@
     // BufferLayerConsumer constructs a new BufferLayerConsumer object.  The
     // tex parameter indicates the name of the RenderEngine texture to which
     // images are to be streamed.
-    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine, uint32_t tex,
-                        Layer* layer);
+    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RE::RenderEngine& engine,
+                        uint32_t tex, Layer* layer);
 
     // Sets the contents changed listener. This should be used instead of
     // ConsumerBase::setFrameAvailableListener().
@@ -220,7 +222,7 @@
     // also only creating new RE::Images from buffers when required.
     class Image : public LightRefBase<Image> {
     public:
-        Image(sp<GraphicBuffer> graphicBuffer, const RenderEngine& engine);
+        Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine);
 
         Image(const Image& rhs) = delete;
         Image& operator=(const Image& rhs) = delete;
@@ -234,18 +236,18 @@
             return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
         }
 
-        const RE::Image& image() const { return mImage; }
+        const RE::Image& image() const { return *mImage; }
 
     private:
         // Only allow instantiation using ref counting.
         friend class LightRefBase<Image>;
-        virtual ~Image() = default;
+        virtual ~Image();
 
         // mGraphicBuffer is the buffer that was used to create this image.
         sp<GraphicBuffer> mGraphicBuffer;
 
         // mImage is the image created from mGraphicBuffer.
-        RE::Image mImage;
+        std::unique_ptr<RE::Image> mImage;
         bool mCreated;
         int32_t mCropWidth;
         int32_t mCropHeight;
@@ -349,7 +351,7 @@
     // setFilteringEnabled().
     bool mFilteringEnabled;
 
-    RenderEngine& mRE;
+    RE::RenderEngine& mRE;
 
     // mTexName is the name of the RenderEngine texture to which streamed
     // images will be bound when bindTexImage is called. It is set at
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 10e7790..80a90a7 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -48,7 +48,7 @@
     if (s.color.a > 0) {
         Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
         computeGeometry(renderArea, mesh, useIdentityTransform);
-        RenderEngine& engine(mFlinger->getRenderEngine());
+        auto& engine(mFlinger->getRenderEngine());
         engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
                                   true /* disableTexture */, s.color);
         engine.drawMesh(mesh);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index cf70529..d40666e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -84,7 +84,7 @@
       mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
-      mSurface{flinger->getRenderEngine()},
+      mSurface{flinger->getRenderEngine().createSurface()},
       mDisplayWidth(),
       mDisplayHeight(),
       mPageFlipCount(),
@@ -106,11 +106,11 @@
     /*
      * Create our display's surface
      */
-    mSurface.setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
-    mSurface.setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
-    mSurface.setNativeWindow(window);
-    mDisplayWidth = mSurface.queryWidth();
-    mDisplayHeight = mSurface.queryHeight();
+    mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
+    mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
+    mSurface->setNativeWindow(window);
+    mDisplayWidth = mSurface->queryWidth();
+    mDisplayHeight = mSurface->queryHeight();
 
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
@@ -207,7 +207,7 @@
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
     if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) {
-        mSurface.swapBuffers();
+        mSurface->swapBuffers();
     }
 
     status_t result = mDisplaySurface->advanceFrame();
@@ -222,7 +222,7 @@
 }
 
 bool DisplayDevice::makeCurrent() const {
-    bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface);
+    bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
     setViewportAndProjection();
     return success;
 }
@@ -360,14 +360,14 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
-    mSurface.setNativeWindow(nullptr);
+    mSurface->setNativeWindow(nullptr);
 
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
     ANativeWindow* const window = mNativeWindow.get();
-    mSurface.setNativeWindow(window);
-    mDisplayWidth = mSurface.queryWidth();
-    mDisplayHeight = mSurface.queryHeight();
+    mSurface->setNativeWindow(window);
+    mDisplayWidth = mSurface->queryWidth();
+    mDisplayHeight = mSurface->queryHeight();
 
     LOG_FATAL_IF(mDisplayWidth != newWidth,
                 "Unable to set new width to %d", newWidth);
@@ -474,9 +474,9 @@
                         "(%d:%d:%d:%d), orient=%2d (type=%08x), "
                         "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
                         mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
-                        mSurface.queryRedSize(), mSurface.queryGreenSize(), mSurface.queryBlueSize(),
-                        mSurface.queryAlphaSize(), mOrientation, tr.getType(),
-                        getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mSurface->queryRedSize(), mSurface->queryGreenSize(),
+                        mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
+                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
                         mVisibleLayersSortedByZ.size());
     result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
                         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index a470670..d5ed15f 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -187,7 +187,7 @@
     sp<ANativeWindow> mNativeWindow;
     sp<DisplaySurface> mDisplaySurface;
 
-    RE::Surface     mSurface;
+    std::unique_ptr<RE::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
     mutable uint32_t mPageFlipCount;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 067a09f..78dd40b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -719,7 +719,7 @@
 
 void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
                             float alpha) const {
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
     computeGeometry(renderArea, getBE().mMesh, false);
     engine.setupFillWithColor(red, green, blue, alpha);
     engine.drawMesh(getBE().mMesh);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c63399e..3671a2b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -90,7 +90,7 @@
         hwc_color_t color;
     } hwc;
     struct {
-        RenderEngine* renderEngine;
+        RE::RenderEngine* renderEngine;
         Mesh* mesh;
     } renderEngine;
 };
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 34d968d..9ecf8ce 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -105,6 +105,8 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+namespace RE {
+namespace impl {
 // ---------------------------------------------------------------------------
 
 GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
@@ -379,7 +381,9 @@
 }
 
 // ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace RE
+} // namespace android
 // ---------------------------------------------------------------------------
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index f3af547..6e86ea2 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -35,6 +35,9 @@
 class Mesh;
 class Texture;
 
+namespace RE {
+namespace impl {
+
 class GLES20RenderEngine : public RenderEngine {
     GLuint mProtectedTexName;
     GLint mMaxViewportDims[2];
@@ -105,7 +108,9 @@
 };
 
 // ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace RE
+} // namespace android
 // ---------------------------------------------------------------------------
 
 #endif /* SF_GLES20RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp
index 1f8e75a..0d06422 100644
--- a/services/surfaceflinger/RenderEngine/Image.cpp
+++ b/services/surfaceflinger/RenderEngine/Image.cpp
@@ -26,6 +26,10 @@
 namespace android {
 namespace RE {
 
+Image::~Image() = default;
+
+namespace impl {
+
 Image::Image(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
 
 Image::~Image() {
@@ -83,5 +87,6 @@
     return true;
 }
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/Image.h
index f55aa59..1ae7e09 100644
--- a/services/surfaceflinger/RenderEngine/Image.h
+++ b/services/surfaceflinger/RenderEngine/Image.h
@@ -24,30 +24,39 @@
 struct ANativeWindowBuffer;
 
 namespace android {
-
-class RenderEngine;
-
 namespace RE {
 
 class Image {
 public:
-    Image(const RenderEngine& engine);
-    ~Image();
+    virtual ~Image() = 0;
+    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected,
+                                       int32_t cropWidth, int32_t cropHeight) = 0;
+};
+
+namespace impl {
+
+class RenderEngine;
+
+class Image : public RE::Image {
+public:
+    explicit Image(const RenderEngine& engine);
+    ~Image() override;
 
     Image(const Image&) = delete;
     Image& operator=(const Image&) = delete;
 
     bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth,
-                               int32_t cropHeight);
+                               int32_t cropHeight) override;
 
 private:
     // methods internal to RenderEngine
-    friend class android::RenderEngine;
+    friend class RenderEngine;
     EGLSurface getEGLImage() const { return mEGLImage; }
 
     EGLDisplay mEGLDisplay;
     EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
 };
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 22016ed..4c878ae 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -37,8 +37,13 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+namespace RE {
 // ---------------------------------------------------------------------------
 
+RenderEngine::~RenderEngine() = default;
+
+namespace impl {
+
 std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
     // initialize EGL for the default display
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -137,9 +142,7 @@
 
 bool RenderEngine::overrideUseContextPriorityFromConfig(bool useContextPriority) {
     OptionalBool ret;
-    ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) {
-        ret = b;
-    });
+    ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) { ret = b; });
     if (ret.specified) {
         return ret.value;
     } else {
@@ -177,7 +180,22 @@
     return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
 }
 
-bool RenderEngine::setCurrentSurface(const RE::Surface& surface) {
+std::unique_ptr<RE::Surface> RenderEngine::createSurface() {
+    return std::make_unique<Surface>(*this);
+}
+
+std::unique_ptr<RE::Image> RenderEngine::createImage() {
+    return std::make_unique<Image>(*this);
+}
+
+bool RenderEngine::setCurrentSurface(const android::RE::Surface& surface) {
+    // Note: RE::Surface is an abstract interface. This implementation only ever
+    // creates RE::impl::Surface's, so it is safe to just cast to the actual
+    // type.
+    return setCurrentSurface(static_cast<const android::RE::impl::Surface&>(surface));
+}
+
+bool RenderEngine::setCurrentSurface(const android::RE::impl::Surface& surface) {
     bool success = true;
     EGLSurface eglSurface = surface.getEGLSurface();
     if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
@@ -349,7 +367,14 @@
     glDeleteTextures(count, names);
 }
 
-void RenderEngine::bindExternalTextureImage(uint32_t texName, const RE::Image& image) {
+void RenderEngine::bindExternalTextureImage(uint32_t texName, const android::RE::Image& image) {
+    // Note: RE::Image is an abstract interface. This implementation only ever
+    // creates RE::impl::Image's, so it is safe to just cast to the actual type.
+    return bindExternalTextureImage(texName, static_cast<const android::RE::impl::Image&>(image));
+}
+
+void RenderEngine::bindExternalTextureImage(uint32_t texName,
+                                            const android::RE::impl::Image& image) {
     const GLenum target = GL_TEXTURE_EXTERNAL_OES;
 
     glBindTexture(target, texName);
@@ -375,34 +400,33 @@
 
 // ---------------------------------------------------------------------------
 
-RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer(
-        RenderEngine& engine, ANativeWindowBuffer* buffer)
-      : mEngine(engine) {
-    mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                               buffer, nullptr);
-    if (mImage == EGL_NO_IMAGE_KHR) {
-        mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                                 RE::BindNativeBufferAsFramebuffer* bindHelper) {
+    bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                                           buffer, nullptr);
+    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
+        bindHelper->mStatus = NO_MEMORY;
         return;
     }
 
-    mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus);
+    uint32_t glStatus;
+    bindImageAsFramebuffer(bindHelper->mImage, &bindHelper->mTexName, &bindHelper->mFbName,
+                           &glStatus);
 
-    ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
-             mStatus);
+    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
+             glStatus);
+
+    bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
 }
 
-RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() {
-    if (mImage == EGL_NO_IMAGE_KHR) {
+void RenderEngine::unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) {
+    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
         return;
     }
 
     // back to main framebuffer
-    mEngine.unbindFramebuffer(mTexName, mFbName);
-    eglDestroyImageKHR(mEngine.mEGLDisplay, mImage);
-}
-
-status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const {
-    return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
+    unbindFramebuffer(bindHelper->mTexName, bindHelper->mFbName);
+    eglDestroyImageKHR(mEGLDisplay, bindHelper->mImage);
 }
 
 // ---------------------------------------------------------------------------
@@ -564,5 +588,7 @@
 }
 
 // ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 67c0d1c..eacef38 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -44,91 +44,63 @@
 class Texture;
 
 namespace RE {
+
 class Image;
 class Surface;
-} // namespace RE
+class BindNativeBufferAsFramebuffer;
+
+namespace impl {
+class RenderEngine;
+}
 
 class RenderEngine {
-    enum GlesVersion {
-        GLES_VERSION_1_0 = 0x10000,
-        GLES_VERSION_1_1 = 0x10001,
-        GLES_VERSION_2_0 = 0x20000,
-        GLES_VERSION_3_0 = 0x30000,
-    };
-    static GlesVersion parseGlesVersion(const char* str);
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-    EGLContext mEGLContext;
-    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
-
-    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
-                                        uint32_t* status) = 0;
-    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
-
-    static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
-
-protected:
-    RenderEngine();
-
 public:
-    virtual ~RenderEngine() = 0;
-
     enum FeatureFlag {
         WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
     };
-    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
 
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+    virtual ~RenderEngine() = 0;
 
-    void primeCache() const;
+    virtual std::unique_ptr<RE::Surface> createSurface() = 0;
+    virtual std::unique_ptr<RE::Image> createImage() = 0;
+
+    virtual void primeCache() const = 0;
 
     // dump the extension strings. always call the base class.
-    virtual void dump(String8& result);
+    virtual void dump(String8& result) = 0;
 
-    bool supportsImageCrop() const;
+    virtual bool supportsImageCrop() const = 0;
 
-    bool isCurrent() const;
-    bool setCurrentSurface(const RE::Surface& surface);
-    void resetCurrentSurface();
+    virtual bool isCurrent() const = 0;
+    virtual bool setCurrentSurface(const RE::Surface& surface) = 0;
+    virtual void resetCurrentSurface() = 0;
 
-    // synchronization
-
+    // helpers
     // flush submits RenderEngine command stream for execution and returns a
     // native fence fd that is signaled when the execution has completed.  It
     // returns -1 on errors.
-    base::unique_fd flush();
+    virtual base::unique_fd flush() = 0;
     // finish waits until RenderEngine command stream has been executed.  It
     // returns false on errors.
-    bool finish();
+    virtual bool finish() = 0;
     // waitFence inserts a wait on an external fence fd to RenderEngine
     // command stream.  It returns false on errors.
-    bool waitFence(base::unique_fd fenceFd);
+    virtual bool waitFence(base::unique_fd fenceFd) = 0;
 
-    // helpers
-    void clearWithColor(float red, float green, float blue, float alpha);
-    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
-                             float blue, float alpha);
+    virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
+    virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                                     float blue, float alpha) = 0;
 
     // common to all GL versions
-    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top);
-    void disableScissor();
-    void genTextures(size_t count, uint32_t* names);
-    void deleteTextures(size_t count, uint32_t const* names);
-    void bindExternalTextureImage(uint32_t texName, const RE::Image& image);
-    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels);
-
-    class BindNativeBufferAsFramebuffer {
-        RenderEngine& mEngine;
-        EGLImageKHR mImage;
-        uint32_t mTexName, mFbName;
-        uint32_t mStatus;
-
-    public:
-        BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer);
-        ~BindNativeBufferAsFramebuffer();
-        int getStatus() const;
-    };
+    virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0;
+    virtual void disableScissor() = 0;
+    virtual void genTextures(size_t count, uint32_t* names) = 0;
+    virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
+    virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0;
+    virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0;
+    virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                               RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
+    virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
 
     // set-up
     virtual void checkErrors() const;
@@ -145,7 +117,7 @@
     virtual void setupLayerBlackedOut() = 0;
     virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
 
-    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) { return mat4(); }
+    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) = 0;
 
     virtual void disableTexturing() = 0;
     virtual void disableBlending() = 0;
@@ -156,14 +128,123 @@
     // queries
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
+};
+
+class BindNativeBufferAsFramebuffer {
+public:
+    BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer)
+          : mEngine(engine) {
+        mEngine.bindNativeBufferAsFrameBuffer(buffer, this);
+    }
+    ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); }
+    status_t getStatus() const { return mStatus; }
+
+protected:
+    friend impl::RenderEngine;
+
+    RenderEngine& mEngine;
+    EGLImageKHR mImage;
+    uint32_t mTexName, mFbName;
+    status_t mStatus;
+};
+
+namespace impl {
+
+class Image;
+class Surface;
+
+class RenderEngine : public RE::RenderEngine {
+    enum GlesVersion {
+        GLES_VERSION_1_0 = 0x10000,
+        GLES_VERSION_1_1 = 0x10001,
+        GLES_VERSION_2_0 = 0x20000,
+        GLES_VERSION_3_0 = 0x30000,
+    };
+    static GlesVersion parseGlesVersion(const char* str);
+
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+    EGLContext mEGLContext;
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
+
+    static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
+
+protected:
+    RenderEngine();
+
+public:
+    virtual ~RenderEngine() = 0;
+
+    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+
+    // RenderEngine interface implementation
+
+    std::unique_ptr<RE::Surface> createSurface() override;
+    std::unique_ptr<RE::Image> createImage() override;
+
+    void primeCache() const override;
+
+    // dump the extension strings. always call the base class.
+    void dump(String8& result) override;
+
+    bool supportsImageCrop() const override;
+
+    bool isCurrent() const;
+    bool setCurrentSurface(const RE::Surface& surface) override;
+    void resetCurrentSurface() override;
+
+    // synchronization
+
+    // flush submits RenderEngine command stream for execution and returns a
+    // native fence fd that is signaled when the execution has completed.  It
+    // returns -1 on errors.
+    base::unique_fd flush() override;
+    // finish waits until RenderEngine command stream has been executed.  It
+    // returns false on errors.
+    bool finish() override;
+    // waitFence inserts a wait on an external fence fd to RenderEngine
+    // command stream.  It returns false on errors.
+    bool waitFence(base::unique_fd fenceFd) override;
+
+    // helpers
+    void clearWithColor(float red, float green, float blue, float alpha) override;
+    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                             float blue, float alpha) override;
+
+    // common to all GL versions
+    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
+    void disableScissor() override;
+    void genTextures(size_t count, uint32_t* names) override;
+    void deleteTextures(size_t count, uint32_t const* names) override;
+    void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override;
+    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
+
+    void checkErrors() const override;
+
+    mat4 setupColorTransform(const mat4& /* colorTransform */) override { return mat4(); }
 
     // internal to RenderEngine
     EGLDisplay getEGLDisplay() const;
     EGLConfig getEGLConfig() const;
+
+    // Common implementation
+    bool setCurrentSurface(const RE::impl::Surface& surface);
+    void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image);
+
+    void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                       RE::BindNativeBufferAsFramebuffer* bindHelper) override;
+    void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override;
+
+    // Overriden by each specialization
+    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+                                        uint32_t* status) = 0;
+    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+} // namespace impl
+} // namespace RE
+} // namespace android
 
 #endif /* SF_RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index a23d9fb..3c29e4b 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -23,6 +23,10 @@
 namespace android {
 namespace RE {
 
+Surface::~Surface() = default;
+
+namespace impl {
+
 Surface::Surface(const RenderEngine& engine)
       : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
     // RE does not assume any config when EGL_KHR_no_config_context is supported
@@ -102,5 +106,6 @@
     return querySurface(EGL_HEIGHT);
 }
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h
index 8b10be9..d4d3d8c 100644
--- a/services/surfaceflinger/RenderEngine/Surface.h
+++ b/services/surfaceflinger/RenderEngine/Surface.h
@@ -23,39 +23,60 @@
 struct ANativeWindow;
 
 namespace android {
-
-class RenderEngine;
-
 namespace RE {
 
 class Surface {
 public:
+    virtual ~Surface() = 0;
+
+    virtual void setCritical(bool enable) = 0;
+    virtual void setAsync(bool enable) = 0;
+
+    virtual void setNativeWindow(ANativeWindow* window) = 0;
+    virtual void swapBuffers() const = 0;
+
+    virtual int32_t queryRedSize() const = 0;
+    virtual int32_t queryGreenSize() const = 0;
+    virtual int32_t queryBlueSize() const = 0;
+    virtual int32_t queryAlphaSize() const = 0;
+
+    virtual int32_t queryWidth() const = 0;
+    virtual int32_t queryHeight() const = 0;
+};
+
+namespace impl {
+
+class RenderEngine;
+
+class Surface final : public RE::Surface {
+public:
     Surface(const RenderEngine& engine);
     ~Surface();
 
     Surface(const Surface&) = delete;
     Surface& operator=(const Surface&) = delete;
 
-    void setCritical(bool enable) { mCritical = enable; }
-    void setAsync(bool enable) { mAsync = enable; }
+    // RE::Surface implementation
+    void setCritical(bool enable) override { mCritical = enable; }
+    void setAsync(bool enable) override { mAsync = enable; }
 
-    void setNativeWindow(ANativeWindow* window);
-    void swapBuffers() const;
+    void setNativeWindow(ANativeWindow* window) override;
+    void swapBuffers() const override;
 
-    int32_t queryRedSize() const;
-    int32_t queryGreenSize() const;
-    int32_t queryBlueSize() const;
-    int32_t queryAlphaSize() const;
+    int32_t queryRedSize() const override;
+    int32_t queryGreenSize() const override;
+    int32_t queryBlueSize() const override;
+    int32_t queryAlphaSize() const override;
 
-    int32_t queryWidth() const;
-    int32_t queryHeight() const;
+    int32_t queryWidth() const override;
+    int32_t queryHeight() const override;
 
 private:
     EGLint queryConfig(EGLint attrib) const;
     EGLint querySurface(EGLint attrib) const;
 
     // methods internal to RenderEngine
-    friend class android::RenderEngine;
+    friend class RenderEngine;
     bool getAsync() const { return mAsync; }
     EGLSurface getEGLSurface() const { return mEGLSurface; }
 
@@ -69,5 +90,6 @@
     EGLSurface mEGLSurface = EGL_NO_SURFACE;
 };
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1380b01..7ad13e3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -410,12 +410,11 @@
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
     class MessageDestroyGLTexture : public MessageBase {
-        RenderEngine& engine;
+        RE::RenderEngine& engine;
         uint32_t texture;
     public:
-        MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture)
-            : engine(engine), texture(texture) {
-        }
+        MessageDestroyGLTexture(RE::RenderEngine& engine, uint32_t texture)
+              : engine(engine), texture(texture) {}
         virtual bool handler() {
             engine.deleteTextures(1, &texture);
             return true;
@@ -587,8 +586,11 @@
     mEventQueue.setEventThread(mSFEventThread.get());
 
     // Get a RenderEngine for the given display / config (can't fail)
-    getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
-            hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
+    getBE().mRenderEngine =
+            RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
+                                           hasWideColorDisplay
+                                                   ? RE::RenderEngine::WIDE_COLOR_SUPPORT
+                                                   : 0);
     LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -1473,7 +1475,7 @@
 
                 // and draw the dirty region
                 const int32_t height = hw->getHeight();
-                RenderEngine& engine(getRenderEngine());
+                auto& engine(getRenderEngine());
                 engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
 
                 hw->swapBuffers(getHwComposer());
@@ -2856,7 +2858,7 @@
 
 void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const {
     const int32_t height = displayDevice->getHeight();
-    RenderEngine& engine(getRenderEngine());
+    auto& engine(getRenderEngine());
     engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
 }
 
@@ -4518,7 +4520,7 @@
                                             bool useIdentityTransform) {
     ATRACE_CALL();
 
-    RenderEngine& engine(getRenderEngine());
+    auto& engine(getRenderEngine());
 
     // get screen geometry
     const auto raWidth = renderArea.getWidth();
@@ -4597,7 +4599,7 @@
 
     // this binds the given EGLImage as a framebuffer for the
     // duration of this scope.
-    RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+    RE::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
     if (bufferBond.getStatus() != NO_ERROR) {
         ALOGE("got ANWB binding error while taking screenshot");
         return INVALID_OPERATION;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 19dd059..a17eb70 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -83,16 +83,19 @@
 // ---------------------------------------------------------------------------
 
 class Client;
-class DisplayEventConnection;
-class EventThread;
-class Layer;
 class ColorLayer;
-class Surface;
-class RenderEngine;
+class DisplayEventConnection;
 class EventControlThread;
-class VSyncSource;
+class EventThread;
 class InjectVSyncSource;
+class Layer;
+class Surface;
 class SurfaceFlingerBE;
+class VSyncSource;
+
+namespace RE {
+class RenderEngine;
+}
 
 typedef std::function<void(const LayerVector::Visitor&)> TraverseLayersFunction;
 
@@ -139,7 +142,7 @@
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 
     // constant members (no synchronization needed for access)
-    std::unique_ptr<RenderEngine> mRenderEngine;
+    std::unique_ptr<RE::RenderEngine> mRenderEngine;
     EGLContext mEGLContext;
     EGLDisplay mEGLDisplay;
 
@@ -301,9 +304,7 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
-    RenderEngine& getRenderEngine() const {
-        return *getBE().mRenderEngine;
-    }
+    RE::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
 
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;