/* * 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 <android-base/thread_annotations.h> #include <stdint.h> #include <sys/types.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 <renderengine/RenderEngine.h> #include <renderengine/private/Description.h> #define EGL_NO_CONFIG ((EGLConfig)0) namespace android { namespace renderengine { class Mesh; class Texture; namespace gl { class GLImage; class GLESRenderEngine : public impl::RenderEngine { public: static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags, uint32_t imageCacheSize); static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext, EGLSurface protectedDummy, uint32_t imageCacheSize); ~GLESRenderEngine() override EXCLUDES(mRenderingMutex); std::unique_ptr<Framebuffer> createFramebuffer() override; std::unique_ptr<Image> createImage() override; void primeCache() const override; bool isCurrent() const override; base::unique_fd flush() override; bool finish() override; bool waitFence(base::unique_fd fenceFd) override; void clearWithColor(float red, float green, float blue, float alpha) override; void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha) 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 Image& image) override; status_t bindExternalTextureBuffer(uint32_t texName, const sp<GraphicBuffer>& buffer, const sp<Fence>& fence) EXCLUDES(mRenderingMutex); status_t cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex); void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); status_t bindFrameBuffer(Framebuffer* framebuffer) override; void unbindFrameBuffer(Framebuffer* framebuffer) override; void checkErrors() const override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector<LayerSettings>& layers, ANativeWindowBuffer* buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) EXCLUDES(mRenderingMutex) override; // internal to RenderEngine EGLDisplay getEGLDisplay() const { return mEGLDisplay; } EGLConfig getEGLConfig() const { return mEGLConfig; } // Creates an output image for rendering to EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected, bool useFramebufferCache); // Test-only methods // Returns true iff mImageCache contains an image keyed by bufferId bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex); // Returns true iff mFramebufferImageCache contains an image keyed by bufferId bool isFramebufferImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex); protected: Framebuffer* getFramebufferForDrawing() override; void dump(std::string& 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, float cornerRadius) override; void setupLayerTexturing(const Texture& texture) override; void setupLayerBlackedOut() override; void setupFillWithColor(float r, float g, float b, float a) override; void setColorTransform(const mat4& colorTransform) override; void disableTexturing() override; void disableBlending() override; void setupCornerRadiusCropSize(float width, float height) override; // HDR and color management related functions and state void setSourceY410BT2020(bool enable) override; void setSourceDataSpace(ui::Dataspace source) override; void setOutputDataSpace(ui::Dataspace dataspace) override; void setDisplayMaxLuminance(const float maxLuminance) override; // drawing void drawMesh(const Mesh& mesh) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; private: 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); static EGLContext createEglContext(EGLDisplay display, EGLConfig config, EGLContext shareContext, bool useContextPriority, Protection protection); static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config, int hwcFormat, Protection protection); void setScissor(const Rect& region); void disableScissor(); bool waitSync(EGLSyncKHR sync, EGLint flags); // 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); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; EGLContext mEGLContext; EGLSurface mDummySurface; EGLContext mProtectedEGLContext; EGLSurface mProtectedDummySurface; GLuint mProtectedTexName; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; GLuint mVpWidth; GLuint mVpHeight; Description mState; 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; // 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; // Cache of GL images that we'll store per GraphicBuffer ID std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex); // 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; // See bindExternalTextureBuffer above, but requiring that mRenderingMutex // is held. status_t bindExternalTextureBufferLocked(uint32_t texName, const sp<GraphicBuffer>& buffer, const sp<Fence>& fence) REQUIRES(mRenderingMutex); // See cacheExternalTextureBuffer above, but requiring that mRenderingMutex // is held. status_t cacheExternalTextureBufferLocked(const sp<GraphicBuffer>& buffer) REQUIRES(mRenderingMutex); std::unique_ptr<Framebuffer> mDrawingBuffer; 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; std::unique_ptr<FlushTracer> mFlushTracer; }; } // namespace gl } // namespace renderengine } // namespace android #endif /* SF_GLESRENDERENGINE_H_ */