/* * Copyright (C) 2014 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 EGLMANAGER_H #define EGLMANAGER_H #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkRect.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> namespace android { namespace uirenderer { namespace renderthread { class RenderThread; class EglManager; class Frame { public: EGLint width() const { return mWidth; } EGLint height() const { return mHeight; } // See: https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_buffer_age.txt // for what this means EGLint bufferAge() const { return mBufferAge; } private: friend class EglManager; EGLSurface mSurface; EGLint mWidth; EGLint mHeight; EGLint mBufferAge; // Maps from 0,0 in top-left to 0,0 in bottom-left // If out is not an EGLint[4] you're going to have a bad time void map(const SkRect& in, EGLint* out) const; }; // This class contains the shared global EGL objects, such as EGLDisplay // and EGLConfig, which are re-used by CanvasContext class EglManager { public: // Returns true on success, false on failure void initialize(); bool hasEglContext(); EGLSurface createSurface(EGLNativeWindowType window); void destroySurface(EGLSurface surface); void destroy(); bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; } // Returns true if the current surface changed, false if it was already current bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr); Frame beginFrame(EGLSurface surface); void damageFrame(const Frame& frame, const SkRect& dirty); // If this returns true it is mandatory that swapBuffers is called // if damageFrame is called without subsequent calls to damageFrame(). // See EGL_KHR_partial_update for more information bool damageRequiresSwap(); bool swapBuffers(const Frame& frame, const SkRect& screenDirty); // Returns true iff the surface is now preserving buffers. bool setPreserveBuffer(EGLSurface surface, bool preserve); void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); void fence(); private: friend class RenderThread; EglManager(RenderThread& thread); // EglContext is never destroyed, method is purposely not implemented ~EglManager(); void initExtensions(); void createPBufferSurface(); void loadConfig(); void createContext(); void initAtlas(); EGLint queryBufferAge(EGLSurface surface); RenderThread& mRenderThread; EGLDisplay mEglDisplay; EGLConfig mEglConfig; EGLContext mEglContext; EGLSurface mPBufferSurface; EGLSurface mCurrentSurface; sp<GraphicBuffer> mAtlasBuffer; int64_t* mAtlasMap; size_t mAtlasMapSize; enum class SwapBehavior { Discard, Preserved, BufferAge, }; SwapBehavior mSwapBehavior = SwapBehavior::Discard; }; } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ #endif /* EGLMANAGER_H */