| /* |
| * Copyright 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef SF_GLESRENDERENGINE_H_ |
| #define SF_GLESRENDERENGINE_H_ |
| |
| #include <condition_variable> |
| #include <deque> |
| #include <mutex> |
| #include <queue> |
| #include <thread> |
| #include <unordered_map> |
| |
| #include <EGL/egl.h> |
| #include <EGL/eglext.h> |
| #include <GLES2/gl2.h> |
| #include <android-base/thread_annotations.h> |
| #include <renderengine/RenderEngine.h> |
| #include <renderengine/private/Description.h> |
| #include <sys/types.h> |
| #include "GLShadowTexture.h" |
| #include "ImageManager.h" |
| |
| #define EGL_NO_CONFIG ((EGLConfig)0) |
| |
| namespace android { |
| |
| namespace renderengine { |
| |
| class Mesh; |
| class Texture; |
| |
| namespace gl { |
| |
| class GLImage; |
| class BlurFilter; |
| |
| class GLESRenderEngine : public RenderEngine { |
| public: |
| static std::unique_ptr<GLESRenderEngine> create(const RenderEngineCreationArgs& args); |
| |
| GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, |
| EGLContext ctxt, EGLSurface stub, EGLContext protectedContext, |
| EGLSurface protectedStub); |
| ~GLESRenderEngine() override EXCLUDES(mRenderingMutex); |
| |
| std::future<void> primeCache() override; |
| void genTextures(size_t count, uint32_t* names) override; |
| void deleteTextures(size_t count, uint32_t const* names) override; |
| bool isProtected() const override { return mInProtectedContext; } |
| bool supportsProtectedContent() const override; |
| void useProtectedContext(bool useProtectedContext) override; |
| status_t drawLayers(const DisplaySettings& display, |
| const std::vector<const LayerSettings*>& layers, |
| const std::shared_ptr<ExternalTexture>& buffer, |
| const bool useFramebufferCache, base::unique_fd&& bufferFence, |
| base::unique_fd* drawFence) override; |
| void cleanupPostRender() override; |
| int getContextPriority() override; |
| bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } |
| void onPrimaryDisplaySizeChanged(ui::Size size) override {} |
| |
| EGLDisplay getEGLDisplay() const { return mEGLDisplay; } |
| // Creates an output image for rendering to |
| EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected, |
| bool useFramebufferCache) |
| EXCLUDES(mFramebufferImageCacheMutex); |
| |
| // Test-only methods |
| // Returns true iff mImageCache contains an image keyed by bufferId |
| bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex); |
| // Returns true iff texName was previously generated by RenderEngine and was |
| // not destroyed. |
| bool isTextureNameKnownForTesting(uint32_t texName); |
| // Returns the buffer ID of the content bound to texName, or nullopt if no |
| // such mapping exists. |
| std::optional<uint64_t> getBufferIdForTextureNameForTesting(uint32_t texName); |
| // Returns true iff mFramebufferImageCache contains an image keyed by bufferId |
| bool isFramebufferImageCachedForTesting(uint64_t bufferId) |
| EXCLUDES(mFramebufferImageCacheMutex); |
| // These are wrappers around public methods above, but exposing Barrier |
| // objects so that tests can block. |
| std::shared_ptr<ImageManager::Barrier> cacheExternalTextureBufferForTesting( |
| const sp<GraphicBuffer>& buffer); |
| std::shared_ptr<ImageManager::Barrier> unbindExternalTextureBufferForTesting(uint64_t bufferId); |
| |
| protected: |
| Framebuffer* getFramebufferForDrawing(); |
| void dump(std::string& result) override EXCLUDES(mRenderingMutex) |
| EXCLUDES(mFramebufferImageCacheMutex); |
| size_t getMaxTextureSize() const override; |
| size_t getMaxViewportDims() const override; |
| void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) |
| EXCLUDES(mRenderingMutex); |
| void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex); |
| bool canSkipPostRenderCleanup() const override; |
| |
| private: |
| friend class BindNativeBufferAsFramebuffer; |
| |
| enum GlesVersion { |
| GLES_VERSION_1_0 = 0x10000, |
| GLES_VERSION_1_1 = 0x10001, |
| GLES_VERSION_2_0 = 0x20000, |
| GLES_VERSION_3_0 = 0x30000, |
| }; |
| |
| static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); |
| static GlesVersion parseGlesVersion(const char* str); |
| static EGLContext createEglContext(EGLDisplay display, EGLConfig config, |
| EGLContext shareContext, |
| std::optional<ContextPriority> contextPriority, |
| Protection protection); |
| static std::optional<RenderEngine::ContextPriority> createContextPriority( |
| const RenderEngineCreationArgs& args); |
| static EGLSurface createStubEglPbufferSurface(EGLDisplay display, EGLConfig config, |
| int hwcFormat, Protection protection); |
| std::unique_ptr<Framebuffer> createFramebuffer(); |
| std::unique_ptr<Image> createImage(); |
| void checkErrors() const; |
| void checkErrors(const char* tag) const; |
| void setScissor(const Rect& region); |
| void disableScissor(); |
| bool waitSync(EGLSyncKHR sync, EGLint flags); |
| status_t cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer) |
| EXCLUDES(mRenderingMutex); |
| void unbindExternalTextureBufferInternal(uint64_t bufferId) EXCLUDES(mRenderingMutex); |
| status_t bindFrameBuffer(Framebuffer* framebuffer); |
| void unbindFrameBuffer(Framebuffer* framebuffer); |
| void bindExternalTextureImage(uint32_t texName, const Image& image); |
| void bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer, |
| const sp<Fence>& fence) EXCLUDES(mRenderingMutex); |
| void cleanFramebufferCache() EXCLUDES(mFramebufferImageCacheMutex) override; |
| |
| // A data space is considered HDR data space if it has BT2020 color space |
| // with PQ or HLG transfer function. |
| bool isHdrDataSpace(const ui::Dataspace dataSpace) const; |
| bool needsXYZTransformMatrix() const; |
| // Defines the viewport, and sets the projection matrix to the projection |
| // defined by the clip. |
| void setViewportAndProjection(Rect viewport, Rect clip); |
| // Evicts stale images from the buffer cache. |
| void evictImages(const std::vector<LayerSettings>& layers); |
| // Computes the cropping window for the layer and sets up cropping |
| // coordinates for the mesh. |
| FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh); |
| |
| // We do a special handling for rounded corners when it's possible to turn off blending |
| // for the majority of the layer. The rounded corners needs to turn on blending such that |
| // we can set the alpha value correctly, however, only the corners need this, and since |
| // blending is an expensive operation, we want to turn off blending when it's not necessary. |
| void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer, |
| const Mesh& mesh); |
| base::unique_fd flush(); |
| bool finish(); |
| bool waitFence(base::unique_fd fenceFd); |
| void clearWithColor(float red, float green, float blue, float alpha); |
| void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha); |
| void handleShadow(const FloatRect& casterRect, float casterCornerRadius, |
| const ShadowSettings& shadowSettings); |
| void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, |
| const half4& color, float cornerRadius); |
| void setupLayerTexturing(const Texture& texture); |
| void setupFillWithColor(float r, float g, float b, float a); |
| void setColorTransform(const mat4& colorTransform); |
| void setDisplayColorTransform(const mat4& colorTransform); |
| void disableTexturing(); |
| void disableBlending(); |
| void setupCornerRadiusCropSize(float width, float height); |
| |
| // HDR and color management related functions and state |
| void setSourceY410BT2020(bool enable); |
| void setSourceDataSpace(ui::Dataspace source); |
| void setOutputDataSpace(ui::Dataspace dataspace); |
| void setDisplayMaxLuminance(const float maxLuminance); |
| |
| // drawing |
| void drawMesh(const Mesh& mesh); |
| |
| EGLDisplay mEGLDisplay; |
| EGLConfig mEGLConfig; |
| EGLContext mEGLContext; |
| EGLSurface mStubSurface; |
| EGLContext mProtectedEGLContext; |
| EGLSurface mProtectedStubSurface; |
| GLint mMaxViewportDims[2]; |
| GLint mMaxTextureSize; |
| GLuint mVpWidth; |
| GLuint mVpHeight; |
| Description mState; |
| std::unique_ptr<GLShadowTexture> mShadowTexture = nullptr; |
| |
| mat4 mSrgbToXyz; |
| mat4 mDisplayP3ToXyz; |
| mat4 mBt2020ToXyz; |
| mat4 mXyzToSrgb; |
| mat4 mXyzToDisplayP3; |
| mat4 mXyzToBt2020; |
| mat4 mSrgbToDisplayP3; |
| mat4 mSrgbToBt2020; |
| mat4 mDisplayP3ToSrgb; |
| mat4 mDisplayP3ToBt2020; |
| mat4 mBt2020ToSrgb; |
| mat4 mBt2020ToDisplayP3; |
| |
| bool mInProtectedContext = false; |
| // If set to true, then enables tracing flush() and finish() to systrace. |
| bool mTraceGpuCompletion = false; |
| // Maximum size of mFramebufferImageCache. If more images would be cached, then (approximately) |
| // the last recently used buffer should be kicked out. |
| uint32_t mFramebufferImageCacheSize = 0; |
| |
| // Cache of output images, keyed by corresponding GraphicBuffer ID. |
| std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache |
| GUARDED_BY(mFramebufferImageCacheMutex); |
| // The only reason why we have this mutex is so that we don't segfault when |
| // dumping info. |
| std::mutex mFramebufferImageCacheMutex; |
| |
| // Current dataspace of layer being rendered |
| ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN; |
| |
| // Current output dataspace of the render engine |
| ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN; |
| |
| // Whether device supports color management, currently color management |
| // supports sRGB, DisplayP3 color spaces. |
| const bool mUseColorManagement = false; |
| |
| // Whether only shaders performing tone mapping from HDR to SDR will be generated on |
| // primeCache(). |
| const bool mPrecacheToneMapperShaderOnly = false; |
| |
| // Cache of GL images that we'll store per GraphicBuffer ID |
| std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex); |
| std::unordered_map<uint32_t, std::optional<uint64_t>> mTextureView; |
| |
| // Mutex guarding rendering operations, so that: |
| // 1. GL operations aren't interleaved, and |
| // 2. Internal state related to rendering that is potentially modified by |
| // multiple threads is guaranteed thread-safe. |
| std::mutex mRenderingMutex; |
| |
| std::unique_ptr<Framebuffer> mDrawingBuffer; |
| // this is a 1x1 RGB buffer, but over-allocate in case a driver wants more |
| // memory or if it needs to satisfy alignment requirements. In this case: |
| // assume that each channel requires 4 bytes, and add 3 additional bytes to |
| // ensure that we align on a word. Allocating 16 bytes will provide a |
| // guarantee that we don't clobber memory. |
| uint32_t mPlaceholderDrawBuffer[4]; |
| // Placeholder buffer and image, similar to mPlaceholderDrawBuffer, but |
| // instead these are intended for cleaning up texture memory with the |
| // GL_TEXTURE_EXTERNAL_OES target. |
| ANativeWindowBuffer* mPlaceholderBuffer = nullptr; |
| EGLImage mPlaceholderImage = EGL_NO_IMAGE_KHR; |
| sp<Fence> mLastDrawFence; |
| // Store a separate boolean checking if prior resources were cleaned up, as |
| // devices that don't support native sync fences can't rely on a last draw |
| // fence that doesn't exist. |
| bool mPriorResourcesCleaned = true; |
| |
| // Blur effect processor, only instantiated when a layer requests it. |
| BlurFilter* mBlurFilter = nullptr; |
| |
| class FlushTracer { |
| public: |
| FlushTracer(GLESRenderEngine* engine); |
| ~FlushTracer(); |
| void queueSync(EGLSyncKHR sync) EXCLUDES(mMutex); |
| |
| struct QueueEntry { |
| EGLSyncKHR mSync = nullptr; |
| uint64_t mFrameNum = 0; |
| }; |
| |
| private: |
| void loop(); |
| GLESRenderEngine* const mEngine; |
| std::thread mThread; |
| std::condition_variable_any mCondition; |
| std::mutex mMutex; |
| std::queue<QueueEntry> mQueue GUARDED_BY(mMutex); |
| uint64_t mFramesQueued GUARDED_BY(mMutex) = 0; |
| bool mRunning = true; |
| }; |
| friend class FlushTracer; |
| friend class ImageManager; |
| friend class GLFramebuffer; |
| friend class BlurFilter; |
| friend class GenericProgram; |
| std::unique_ptr<FlushTracer> mFlushTracer; |
| std::unique_ptr<ImageManager> mImageManager; |
| }; |
| |
| } // namespace gl |
| } // namespace renderengine |
| } // namespace android |
| |
| #endif /* SF_GLESRENDERENGINE_H_ */ |