[RenderEngine] Make BindNativeBufferAsFramebuffer more generic.
BindNativeBufferAsFramebuffer is a helper class that manages resource of an EGL
image for screenshot capturing. However, as a public API it ties to GLES. This
patch abstracts framebuffer out as Framebuffer and uses it instead of EGL
image. As a result, we can move the most of the implementation of
bindNativeBufferAsFrameBuffer and unbindNativeBufferAsFrameBuffer to
GLFramebuffer so that it manages its own resources, and move the rest of the
implementation to GLES20RenderEngine and get rid off two virtual functions.
Minor: Clean up some coding style.
BUG: 112585051
Test: Build, flash, boot and run some display validation
Change-Id: I787625089f8959cc273d4756baa7135cb004ed2d
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index def3abb..bfabf4d 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -37,6 +37,7 @@
#include <utils/String8.h>
#include <utils/Trace.h>
#include "GLExtensions.h"
+#include "GLFramebuffer.h"
#include "GLImage.h"
#include "GLSurface.h"
#include "Program.h"
@@ -154,6 +155,10 @@
GLES20RenderEngine::~GLES20RenderEngine() {}
+std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
+ return std::make_unique<GLFramebuffer>(*this);
+}
+
std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
return std::make_unique<GLSurface>(*this);
}
@@ -197,10 +202,49 @@
glBindTexture(target, texName);
if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
- glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
+ glEGLImageTargetTexture2DOES(target,
+ static_cast<GLeglImageOES>(glImage.getEGLImage()));
}
}
+status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
+ GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
+ EGLImageKHR eglImage = glFramebuffer->getEGLImage();
+ uint32_t textureName = glFramebuffer->getTextureName();
+ uint32_t framebufferName = glFramebuffer->getFramebufferName();
+
+ // Bind the texture and turn our EGLImage into a texture
+ glBindTexture(GL_TEXTURE_2D, textureName);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
+
+ // Bind the Framebuffer to render into
+ glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, textureName, 0);
+
+ mRenderToFbo = true;
+
+ uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES,
+ "glCheckFramebufferStatusOES error %d", glStatus);
+
+ return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
+}
+
+void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+ mRenderToFbo = false;
+
+ // back to main framebuffer
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // Workaround for b/77935566 to force the EGL driver to release the
+ // screenshot buffer
+ setScissor(0, 0, 0, 0);
+ clearWithColor(0.0, 0.0, 0.0, 0.0);
+ disableScissor();
+}
+
void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) {
int32_t l = sourceCrop.left;
@@ -304,34 +348,6 @@
glDisable(GL_BLEND);
}
-void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
- uint32_t* fbName, uint32_t* status) {
- GLuint tname, name;
- // turn our EGLImage into a texture
- glGenTextures(1, &tname);
- glBindTexture(GL_TEXTURE_2D, tname);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
-
- // create a Framebuffer Object to render into
- glGenFramebuffers(1, &name);
- glBindFramebuffer(GL_FRAMEBUFFER, name);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
-
- *status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- *texName = tname;
- *fbName = name;
-
- mRenderToFbo = true;
-}
-
-void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
- mRenderToFbo = false;
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
- glDeleteFramebuffers(1, &fbName);
- glDeleteTextures(1, &texName);
-}
-
void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
mState.setPremultipliedAlpha(true);
mState.setOpaque(false);
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index a6fc03d..3113e53 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -39,32 +39,13 @@
class GLSurface;
class GLES20RenderEngine : public impl::RenderEngine {
- GLuint mProtectedTexName;
- GLint mMaxViewportDims[2];
- GLint mMaxTextureSize;
- GLuint mVpWidth;
- GLuint mVpHeight;
-
- struct Group {
- GLuint texture;
- GLuint fbo;
- GLuint width;
- GLuint height;
- mat4 colorTransform;
- };
-
- Description mState;
-
- virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
- uint32_t* status);
- virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
-
public:
GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
- virtual ~GLES20RenderEngine();
+ ~GLES20RenderEngine() override;
- std::unique_ptr<renderengine::Surface> createSurface() override;
- std::unique_ptr<renderengine::Image> createImage() override;
+ std::unique_ptr<Framebuffer> createFramebuffer() override;
+ std::unique_ptr<Surface> createSurface() override;
+ std::unique_ptr<Image> createImage() override;
void primeCache() const override;
@@ -72,15 +53,16 @@
bool setCurrentSurface(const Surface& surface) override;
void resetCurrentSurface() override;
- void bindExternalTextureImage(uint32_t texName, const renderengine::Image& image) override;
-
+ void bindExternalTextureImage(uint32_t texName, const Image& image) override;
+ status_t bindFrameBuffer(Framebuffer* framebuffer) override;
+ void unbindFrameBuffer(Framebuffer* framebuffer) override;
protected:
- virtual void dump(String8& result);
- virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
- ui::Transform::orientation_flags rotation);
- virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
- const half4& color) override;
+ void dump(String8& result) override;
+ void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+ ui::Transform::orientation_flags rotation) override;
+ void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+ const half4& color) override;
// Color management related functions and state
void setSourceY410BT2020(bool enable) override;
@@ -88,17 +70,41 @@
void setOutputDataSpace(ui::Dataspace dataspace) override;
void setDisplayMaxLuminance(const float maxLuminance) override;
- virtual void setupLayerTexturing(const Texture& texture);
- virtual void setupLayerBlackedOut();
- virtual void setupFillWithColor(float r, float g, float b, float a);
- virtual void setupColorTransform(const mat4& colorTransform);
- virtual void disableTexturing();
- virtual void disableBlending();
+ void setupLayerTexturing(const Texture& texture) override;
+ void setupLayerBlackedOut() override;
+ void setupFillWithColor(float r, float g, float b, float a) override;
+ void setupColorTransform(const mat4& colorTransform) override;
+ void disableTexturing() override;
+ void disableBlending() override;
- virtual void drawMesh(const Mesh& mesh);
+ void drawMesh(const Mesh& mesh) override;
- virtual size_t getMaxTextureSize() const;
- virtual size_t getMaxViewportDims() const;
+ size_t getMaxTextureSize() const override;
+ size_t getMaxViewportDims() const override;
+
+private:
+ // A data space is considered HDR data space if it has BT2020 color space
+ // with PQ or HLG transfer function.
+ bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
+ bool needsXYZTransformMatrix() const;
+
+ GLuint mProtectedTexName;
+ GLint mMaxViewportDims[2];
+ GLint mMaxTextureSize;
+ GLuint mVpWidth;
+ GLuint mVpHeight;
+ Description mState;
+
+ mat4 mSrgbToDisplayP3;
+ mat4 mDisplayP3ToSrgb;
+ mat3 mSrgbToXyz;
+ mat3 mBt2020ToXyz;
+ mat3 mDisplayP3ToXyz;
+ mat4 mXyzToSrgb;
+ mat4 mXyzToDisplayP3;
+ mat4 mXyzToBt2020;
+
+ bool mRenderToFbo = false;
// Current dataspace of layer being rendered
ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
@@ -109,22 +115,6 @@
// Whether device supports color management, currently color management
// supports sRGB, DisplayP3 color spaces.
const bool mUseColorManagement = false;
- mat4 mSrgbToDisplayP3;
- mat4 mDisplayP3ToSrgb;
- mat3 mSrgbToXyz;
- mat3 mBt2020ToXyz;
- mat3 mDisplayP3ToXyz;
- mat4 mXyzToSrgb;
- mat4 mXyzToDisplayP3;
- mat4 mXyzToBt2020;
-
-private:
- // A data space is considered HDR data space if it has BT2020 color space
- // with PQ or HLG transfer function.
- bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
- bool needsXYZTransformMatrix() const;
-
- bool mRenderToFbo = false;
};
} // namespace gl
diff --git a/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp
new file mode 100644
index 0000000..6aca1c8
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GLFramebuffer.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include "GLES20RenderEngine.h"
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+GLFramebuffer::GLFramebuffer(const GLES20RenderEngine& engine)
+ : mEGLDisplay(engine.getEGLDisplay()),
+ mEGLImage(EGL_NO_IMAGE_KHR) {
+ glGenTextures(1, &mTextureName);
+ glGenFramebuffers(1, &mFramebufferName);
+}
+
+GLFramebuffer::~GLFramebuffer() {
+ glDeleteFramebuffers(1, &mFramebufferName);
+ glDeleteTextures(1, &mTextureName);
+ eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+}
+
+bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) {
+ if (mEGLImage != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+ mEGLImage = EGL_NO_IMAGE_KHR;
+ }
+
+ if (nativeBuffer) {
+ mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID,
+ nativeBuffer, nullptr);
+ if (mEGLImage == EGL_NO_IMAGE_KHR) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h
new file mode 100644
index 0000000..90b2248
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <renderengine/Framebuffer.h>
+
+struct ANativeWindowBuffer;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLFramebuffer : public renderengine::Framebuffer {
+public:
+ explicit GLFramebuffer(const GLES20RenderEngine& engine);
+ ~GLFramebuffer() override;
+
+ bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) override;
+ EGLImageKHR getEGLImage() const { return mEGLImage; }
+ uint32_t getTextureName() const { return mTextureName; }
+ uint32_t getFramebufferName() const { return mFramebufferName; }
+
+private:
+ EGLDisplay mEGLDisplay;
+ EGLImageKHR mEGLImage;
+ uint32_t mTextureName, mFramebufferName;
+};
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLImage.h b/services/surfaceflinger/RenderEngine/gl/GLImage.h
index a0f2358..f670783 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLImage.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLImage.h
@@ -38,7 +38,7 @@
bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
- EGLSurface getEGLImage() const { return mEGLImage; }
+ EGLImageKHR getEGLImage() const { return mEGLImage; }
private:
EGLDisplay mEGLDisplay;
@@ -47,6 +47,6 @@
DISALLOW_COPY_AND_ASSIGN(GLImage);
};
-} // namespace gl
-} // namespace renderengine
-} // namespace android
+} // namespace gl
+} // namespace renderengine
+} // namespace android