| // |
| // Copyright 2022 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // PixelLocalStorage.h: Defines the renderer-agnostic container classes |
| // gl::PixelLocalStorage and gl::PixelLocalStoragePlane for |
| // ANGLE_shader_pixel_local_storage. |
| |
| #ifndef LIBANGLE_PIXEL_LOCAL_STORAGE_H_ |
| #define LIBANGLE_PIXEL_LOCAL_STORAGE_H_ |
| |
| #include "GLSLANG/ShaderLang.h" |
| #include "libANGLE/Caps.h" |
| #include "libANGLE/ImageIndex.h" |
| #include "libANGLE/angletypes.h" |
| |
| namespace gl |
| { |
| |
| class Context; |
| class Texture; |
| |
| // Holds the configuration of an ANGLE_shader_pixel_local_storage plane. |
| // |
| // Unlike normal framebuffer attachments, pixel local storage planes don't take effect until the |
| // application calls glBeginPixelLocalStorageANGLE, and the manner in which they take effect is |
| // highly dependent on the backend implementation. A PixelLocalStoragePlane is just a plain data |
| // description what to set up later once PLS is enabled. |
| class PixelLocalStoragePlane : angle::NonCopyable, public angle::ObserverInterface |
| { |
| public: |
| PixelLocalStoragePlane(); |
| ~PixelLocalStoragePlane() override; |
| |
| // Called when the context is lost or destroyed. Causes this class to clear its GL object |
| // handles. |
| void onContextObjectsLost(); |
| |
| void deinitialize(Context *); |
| void setMemoryless(Context *, GLenum internalformat); |
| void setTextureBacked(Context *, Texture *, int level, int layer); |
| void onSubjectStateChange(angle::SubjectIndex, angle::SubjectMessage) override; |
| |
| // Returns true if the plane is deinitialized, either explicitly or implicitly via deleting the |
| // texture that was attached to it. |
| bool isDeinitialized() const; |
| |
| GLenum getInternalformat() const { return mInternalformat; } |
| bool isMemoryless() const { return mMemoryless; } |
| TextureID getTextureID() const { return mTextureID; } |
| |
| // Implements glGetIntegeri_v() for GL_PIXEL_LOCAL_FORMAT_ANGLE, |
| // GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, and |
| // GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE |
| GLint getIntegeri(GLenum target) const; |
| |
| // If this plane is texture backed, stores the bound texture image's {width, height, 0} to |
| // Extents and returns true. Otherwise returns false, meaning the plane is either deinitialized |
| // or memoryless. |
| bool getTextureImageExtents(const Context *, Extents *extents) const; |
| |
| // Ensures we have an internal backing texture for memoryless planes. In some implementations we |
| // need a backing texture even if the plane is memoryless. |
| void ensureBackingTextureIfMemoryless(Context *, Extents plsSize); |
| |
| // Attaches this plane to the specified color attachment point on the current draw framebuffer. |
| void attachToDrawFramebuffer(Context *, GLenum colorAttachment) const; |
| |
| // Interface for clearing typed pixel local storage planes. |
| class ClearCommands |
| { |
| public: |
| virtual ~ClearCommands() {} |
| virtual void clearfv(int target, const GLfloat[]) const = 0; |
| virtual void cleariv(int target, const GLint[]) const = 0; |
| virtual void clearuiv(int target, const GLuint[]) const = 0; |
| }; |
| |
| // Issues the approprite command from ClearCommands for this plane's internalformat. Uses the |
| // clear state value that corresponds to mInternalFormat, and potentially clamps it to ensure it |
| // is representable. |
| void issueClearCommand(ClearCommands *, int target, GLenum loadop) const; |
| |
| // Binds this PLS plane to a texture image unit for image load/store shader operations. |
| void bindToImage(Context *, GLuint unit, bool needsR32Packing) const; |
| |
| // Low-level access to the backing texture. The plane must not be memoryless or deinitialized. |
| const ImageIndex &getTextureImageIndex() const { return mTextureImageIndex; } |
| const Texture *getBackingTexture(const Context *context) const; |
| |
| void setClearValuef(const GLfloat value[4]) { memcpy(mClearValuef.data(), value, 4 * 4); } |
| void setClearValuei(const GLint value[4]) { memcpy(mClearValuei.data(), value, 4 * 4); } |
| void setClearValueui(const GLuint value[4]) { memcpy(mClearValueui.data(), value, 4 * 4); } |
| |
| void getClearValuef(GLfloat value[4]) const { memcpy(value, mClearValuef.data(), 4 * 4); } |
| void getClearValuei(GLint value[4]) const { memcpy(value, mClearValuei.data(), 4 * 4); } |
| void getClearValueui(GLuint value[4]) const { memcpy(value, mClearValueui.data(), 4 * 4); } |
| |
| // True if PLS is currently active and this plane is enabled. |
| bool isActive() const { return mActive; } |
| void markActive(bool active) { mActive = active; } |
| |
| private: |
| GLenum mInternalformat = GL_NONE; // GL_NONE if this plane is in a deinitialized state. |
| bool mMemoryless = false; |
| TextureID mTextureID = TextureID(); |
| ImageIndex mTextureImageIndex; |
| |
| // Clear value state. |
| std::array<GLfloat, 4> mClearValuef{}; |
| std::array<GLint, 4> mClearValuei{}; |
| std::array<GLuint, 4> mClearValueui{}; |
| |
| // True if PLS is currently active and this plane is enabled. |
| bool mActive = false; |
| |
| angle::ObserverBinding mTextureObserver; |
| }; |
| |
| // Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state. |
| // |
| // The main magic of ANGLE_shader_pixel_local_storage happens inside shaders, so we just emulate the |
| // client API on top of ANGLE's OpenGL ES API for simplicity. |
| class PixelLocalStorage |
| { |
| public: |
| static std::unique_ptr<PixelLocalStorage> Make(const Context *); |
| |
| virtual ~PixelLocalStorage(); |
| |
| // Called when the owning framebuffer is being destroyed. |
| void onFramebufferDestroyed(const Context *); |
| |
| // Deletes any GL objects that have been allocated for pixel local storage. These can't be |
| // cleaned up in the destructor because they require a non-const Context object. |
| void deleteContextObjects(Context *); |
| |
| const PixelLocalStoragePlane &getPlane(GLint plane) const |
| { |
| ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES); |
| return mPlanes[plane]; |
| } |
| |
| const PixelLocalStoragePlane *getPlanes() { return mPlanes.data(); } |
| |
| size_t interruptCount() const { return mInterruptCount; } |
| |
| // ANGLE_shader_pixel_local_storage API. |
| void deinitialize(Context *context, GLint plane) { mPlanes[plane].deinitialize(context); } |
| void setMemoryless(Context *context, GLint plane, GLenum internalformat) |
| { |
| mPlanes[plane].setMemoryless(context, internalformat); |
| } |
| void setTextureBacked(Context *context, GLint plane, Texture *tex, int level, int layer) |
| { |
| mPlanes[plane].setTextureBacked(context, tex, level, layer); |
| } |
| void setClearValuef(GLint plane, const GLfloat val[4]) { mPlanes[plane].setClearValuef(val); } |
| void setClearValuei(GLint plane, const GLint val[4]) { mPlanes[plane].setClearValuei(val); } |
| void setClearValueui(GLint plane, const GLuint val[4]) { mPlanes[plane].setClearValueui(val); } |
| void begin(Context *, GLsizei n, const GLenum loadops[]); |
| void end(Context *, GLsizei n, const GLenum storeops[]); |
| void barrier(Context *); |
| void interrupt(Context *); |
| void restore(Context *); |
| |
| protected: |
| PixelLocalStorage(const ShPixelLocalStorageOptions &, const Caps &); |
| |
| // Called when the context is lost or destroyed. Causes the subclass to clear its GL object |
| // handles. |
| virtual void onContextObjectsLost() = 0; |
| |
| // Called when the framebuffer is being destroyed. Causes the subclass to delete its frontend GL |
| // object handles. |
| virtual void onDeleteContextObjects(Context *) = 0; |
| |
| // ANGLE_shader_pixel_local_storage API. |
| virtual void onBegin(Context *, GLsizei n, const GLenum loadops[], Extents plsSize) = 0; |
| virtual void onEnd(Context *, GLsizei n, const GLenum storeops[]) = 0; |
| virtual void onBarrier(Context *) = 0; |
| |
| const ShPixelLocalStorageOptions mPLSOptions; |
| |
| private: |
| angle::FixedVector<PixelLocalStoragePlane, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES> |
| mPlanes; |
| size_t mInterruptCount = 0; |
| GLsizei mActivePlanesAtInterrupt = 0; |
| }; |
| |
| } // namespace gl |
| |
| #endif // LIBANGLE_PIXEL_LOCAL_STORAGE_H_ |