diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/renderengine/Android.bp | 1 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLES20RenderEngine.cpp | 69 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLES20RenderEngine.h | 12 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLSurface.cpp | 105 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLSurface.h | 76 | ||||
| -rw-r--r-- | libs/renderengine/include/renderengine/RenderEngine.h | 4 | ||||
| -rw-r--r-- | libs/renderengine/include/renderengine/Surface.h | 46 |
7 files changed, 297 insertions, 16 deletions
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index beaf9ee70d..7efc8bd64d 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -50,6 +50,7 @@ filegroup { "gl/GLExtensions.cpp", "gl/GLFramebuffer.cpp", "gl/GLImage.cpp", + "gl/GLSurface.cpp", "gl/Program.cpp", "gl/ProgramCache.cpp", ], diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp index d35762d447..70a4322c5f 100644 --- a/libs/renderengine/gl/GLES20RenderEngine.cpp +++ b/libs/renderengine/gl/GLES20RenderEngine.cpp @@ -41,6 +41,7 @@ #include "GLExtensions.h" #include "GLFramebuffer.h" #include "GLImage.h" +#include "GLSurface.h" #include "Program.h" #include "ProgramCache.h" @@ -274,8 +275,6 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, // now figure out what version of GL did we actually get // NOTE: a dummy surface is not needed if KHR_create_context is supported - // TODO(alecmouri): don't create this surface if EGL_KHR_surfaceless_context - // is supported. EGLConfig dummyConfig = config; if (dummyConfig == EGL_NO_CONFIG) { @@ -302,10 +301,10 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, break; case GLES_VERSION_2_0: case GLES_VERSION_3_0: - engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt, - dummy); + engine = std::make_unique<GLES20RenderEngine>(featureFlags); break; } + engine->setEGLHandles(display, config, ctxt); ALOGI("OpenGL ES informations:"); ALOGI("vendor : %s", extensions.getVendor()); @@ -315,6 +314,9 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat, ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize()); ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims()); + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(display, dummy); + return engine; } @@ -357,13 +359,11 @@ EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bo return config; } -GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config, - EGLContext ctxt, EGLSurface dummy) +GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags) : renderengine::impl::RenderEngine(featureFlags), - mEGLDisplay(display), - mEGLConfig(config), - mEGLContext(ctxt), - mDummySurface(dummy), + mEGLDisplay(EGL_NO_DISPLAY), + mEGLConfig(nullptr), + mEGLContext(EGL_NO_CONTEXT), mVpWidth(0), mVpHeight(0), mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) { @@ -422,6 +422,10 @@ std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() { return std::make_unique<GLFramebuffer>(*this); } +std::unique_ptr<Surface> GLES20RenderEngine::createSurface() { + return std::make_unique<GLSurface>(*this); +} + std::unique_ptr<Image> GLES20RenderEngine::createImage() { return std::make_unique<GLImage>(*this); } @@ -434,6 +438,31 @@ bool GLES20RenderEngine::isCurrent() const { return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext(); } +bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) { + // Surface is an abstract interface. GLES20RenderEngine only ever + // creates GLSurface's, so it is safe to just cast to the actual + // type. + bool success = true; + const GLSurface& glSurface = static_cast<const GLSurface&>(surface); + EGLSurface eglSurface = glSurface.getEGLSurface(); + if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) { + success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE; + if (success && glSurface.getAsync()) { + eglSwapInterval(mEGLDisplay, 0); + } + if (success) { + mSurfaceHeight = glSurface.getHeight(); + } + } + + return success; +} + +void GLES20RenderEngine::resetCurrentSurface() { + eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + mSurfaceHeight = 0; +} + base::unique_fd GLES20RenderEngine::flush() { if (!GLExtensions::getInstance().hasNativeFenceSync()) { return base::unique_fd(); @@ -547,7 +576,7 @@ void GLES20RenderEngine::fillRegionWithColor(const Region& region, float red, fl void GLES20RenderEngine::setScissor(const Rect& region) { // Invert y-coordinate to map to GL-space. - int32_t canvasHeight = mFboHeight; + int32_t canvasHeight = mRenderToFbo ? mFboHeight : mSurfaceHeight; int32_t glBottom = canvasHeight - region.bottom; glScissor(region.left, glBottom, region.getWidth(), region.getHeight()); @@ -590,6 +619,7 @@ status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { glBindFramebuffer(GL_FRAMEBUFFER, framebufferName); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0); + mRenderToFbo = true; mFboHeight = glFramebuffer->getBufferHeight(); uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -601,10 +631,17 @@ status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { } void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) { + mRenderToFbo = false; mFboHeight = 0; // back to main framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Workaround for b/77935566 to force the EGL driver to release the + // screenshot buffer + setScissor(Rect::EMPTY_RECT); + clearWithColor(0.0, 0.0, 0.0, 0.0); + disableScissor(); } void GLES20RenderEngine::checkErrors() const { @@ -629,7 +666,9 @@ void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect s int32_t r = sourceCrop.right; int32_t b = sourceCrop.bottom; int32_t t = sourceCrop.top; - std::swap(t, b); + if (mRenderToFbo) { + std::swap(t, b); + } mat4 m = mat4::ortho(l, r, b, t, 0, 1); // Apply custom rotation to the projection. @@ -935,6 +974,12 @@ bool GLES20RenderEngine::needsXYZTransformMatrix() const { return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer; } +void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) { + mEGLDisplay = display; + mEGLConfig = config; + mEGLContext = ctxt; +} + } // namespace gl } // namespace renderengine } // namespace android diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLES20RenderEngine.h index 6c50938863..148df2fbb4 100644 --- a/libs/renderengine/gl/GLES20RenderEngine.h +++ b/libs/renderengine/gl/GLES20RenderEngine.h @@ -40,21 +40,24 @@ class Texture; namespace gl { class GLImage; +class GLSurface; class GLES20RenderEngine : public impl::RenderEngine { public: static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags); static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); - GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag - EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy); + GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag ~GLES20RenderEngine() override; std::unique_ptr<Framebuffer> createFramebuffer() override; + std::unique_ptr<Surface> createSurface() override; std::unique_ptr<Image> createImage() override; void primeCache() const override; bool isCurrent() const override; + bool setCurrentSurface(const Surface& surface) override; + void resetCurrentSurface() override; base::unique_fd flush() override; bool finish() override; bool waitFence(base::unique_fd fenceFd) override; @@ -117,12 +120,11 @@ private: // with PQ or HLG transfer function. bool isHdrDataSpace(const ui::Dataspace dataSpace) const; bool needsXYZTransformMatrix() const; - void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy); + void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; EGLContext mEGLContext; - EGLSurface mDummySurface; GLuint mProtectedTexName; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; @@ -143,6 +145,8 @@ private: mat4 mBt2020ToSrgb; mat4 mBt2020ToDisplayP3; + bool mRenderToFbo = false; + int32_t mSurfaceHeight = 0; int32_t mFboHeight = 0; // Current dataspace of layer being rendered diff --git a/libs/renderengine/gl/GLSurface.cpp b/libs/renderengine/gl/GLSurface.cpp new file mode 100644 index 0000000000..2d694e9124 --- /dev/null +++ b/libs/renderengine/gl/GLSurface.cpp @@ -0,0 +1,105 @@ +/* + * 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 "GLSurface.h" + +#include <android/native_window.h> +#include <log/log.h> +#include <ui/PixelFormat.h> +#include "GLES20RenderEngine.h" + +namespace android { +namespace renderengine { +namespace gl { + +GLSurface::GLSurface(const GLES20RenderEngine& engine) + : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) { + // RE does not assume any config when EGL_KHR_no_config_context is supported + if (mEGLConfig == EGL_NO_CONFIG_KHR) { + mEGLConfig = + GLES20RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false); + } +} + +GLSurface::~GLSurface() { + setNativeWindow(nullptr); +} + +void GLSurface::setNativeWindow(ANativeWindow* window) { + if (mEGLSurface != EGL_NO_SURFACE) { + eglDestroySurface(mEGLDisplay, mEGLSurface); + mEGLSurface = EGL_NO_SURFACE; + mSurfaceWidth = 0; + mSurfaceHeight = 0; + } + + mWindow = window; + if (mWindow) { + mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr); + mSurfaceWidth = ANativeWindow_getWidth(window); + mSurfaceHeight = ANativeWindow_getHeight(window); + } +} + +void GLSurface::swapBuffers() const { + if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) { + EGLint error = eglGetError(); + + const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x"; + if (mCritical || error == EGL_CONTEXT_LOST) { + LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error); + } else { + ALOGE(format, mEGLDisplay, mEGLSurface, error); + } + } +} + +EGLint GLSurface::queryConfig(EGLint attrib) const { + EGLint value; + if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) { + value = 0; + } + + return value; +} + +int32_t GLSurface::queryRedSize() const { + return queryConfig(EGL_RED_SIZE); +} + +int32_t GLSurface::queryGreenSize() const { + return queryConfig(EGL_GREEN_SIZE); +} + +int32_t GLSurface::queryBlueSize() const { + return queryConfig(EGL_BLUE_SIZE); +} + +int32_t GLSurface::queryAlphaSize() const { + return queryConfig(EGL_ALPHA_SIZE); +} + +int32_t GLSurface::getWidth() const { + return mSurfaceWidth; +} + +int32_t GLSurface::getHeight() const { + return mSurfaceHeight; +} + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/gl/GLSurface.h b/libs/renderengine/gl/GLSurface.h new file mode 100644 index 0000000000..092d371ee9 --- /dev/null +++ b/libs/renderengine/gl/GLSurface.h @@ -0,0 +1,76 @@ +/* + * 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 <android-base/macros.h> +#include <renderengine/Surface.h> + +struct ANativeWindow; + +namespace android { +namespace renderengine { +namespace gl { + +class GLES20RenderEngine; + +class GLSurface final : public renderengine::Surface { +public: + GLSurface(const GLES20RenderEngine& engine); + ~GLSurface() override; + + // renderengine::Surface implementation + void setCritical(bool enable) override { mCritical = enable; } + void setAsync(bool enable) override { mAsync = enable; } + + void setNativeWindow(ANativeWindow* window) override; + void swapBuffers() const override; + + int32_t queryRedSize() const override; + int32_t queryGreenSize() const override; + int32_t queryBlueSize() const override; + int32_t queryAlphaSize() const override; + + bool getAsync() const { return mAsync; } + EGLSurface getEGLSurface() const { return mEGLSurface; } + + int32_t getWidth() const override; + int32_t getHeight() const override; + +private: + EGLint queryConfig(EGLint attrib) const; + + EGLDisplay mEGLDisplay; + EGLConfig mEGLConfig; + + bool mCritical = false; + bool mAsync = false; + + int32_t mSurfaceWidth = 0; + int32_t mSurfaceHeight = 0; + + ANativeWindow* mWindow = nullptr; + EGLSurface mEGLSurface = EGL_NO_SURFACE; + + DISALLOW_COPY_AND_ASSIGN(GLSurface); +}; + +} // namespace gl +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 22891c42c4..becb3c3a10 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -48,6 +48,7 @@ namespace renderengine { class BindNativeBufferAsFramebuffer; class Image; class Mesh; +class Surface; class Texture; namespace impl { @@ -71,6 +72,7 @@ public: // used to support legacy behavior. virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0; + virtual std::unique_ptr<Surface> createSurface() = 0; virtual std::unique_ptr<Image> createImage() = 0; virtual void primeCache() const = 0; @@ -82,6 +84,8 @@ public: virtual bool useWaitSync() const = 0; virtual bool isCurrent() const = 0; + virtual bool setCurrentSurface(const Surface& surface) = 0; + virtual void resetCurrentSurface() = 0; // helpers // flush submits RenderEngine command stream for execution and returns a diff --git a/libs/renderengine/include/renderengine/Surface.h b/libs/renderengine/include/renderengine/Surface.h new file mode 100644 index 0000000000..ba7331daab --- /dev/null +++ b/libs/renderengine/include/renderengine/Surface.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <cstdint> + +struct ANativeWindow; + +namespace android { +namespace renderengine { + +class Surface { +public: + virtual ~Surface() = default; + + 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 getWidth() const = 0; + virtual int32_t getHeight() const = 0; +}; + +} // namespace renderengine +} // namespace android |