/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef SCOPEDGLHELPERS_H_ #define SCOPEDGLHELPERS_H_ #include "GLDefs.h" #include "mozilla/UniquePtr.h" namespace mozilla { namespace gl { class GLContext; #ifdef DEBUG bool IsContextCurrent(GLContext* gl); #endif //RAII via CRTP! template struct ScopedGLWrapper { private: bool mIsUnwrapped; protected: GLContext* const mGL; explicit ScopedGLWrapper(GLContext* gl) : mIsUnwrapped(false) , mGL(gl) { MOZ_ASSERT(&ScopedGLWrapper::Unwrap == &Derived::Unwrap); MOZ_ASSERT(&Derived::UnwrapImpl); MOZ_ASSERT(IsContextCurrent(mGL)); } virtual ~ScopedGLWrapper() { if (!mIsUnwrapped) Unwrap(); } public: void Unwrap() { MOZ_ASSERT(!mIsUnwrapped); Derived* derived = static_cast(this); derived->UnwrapImpl(); mIsUnwrapped = true; } }; // Wraps glEnable/Disable. struct ScopedGLState : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: const GLenum mCapability; bool mOldState; public: // Use |newState = true| to enable, |false| to disable. ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState); // variant that doesn't change state; simply records existing state to be // restored by the destructor ScopedGLState(GLContext* aGL, GLenum aCapability); protected: void UnwrapImpl(); }; // Saves and restores with GetUserBoundFB and BindUserFB. struct ScopedBindFramebuffer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mOldReadFB; GLuint mOldDrawFB; private: void Init(); public: explicit ScopedBindFramebuffer(GLContext* aGL); ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB); protected: void UnwrapImpl(); }; struct ScopedBindTextureUnit : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLenum mOldTexUnit; public: ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit); protected: void UnwrapImpl(); }; struct ScopedTexture : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mTexture; public: explicit ScopedTexture(GLContext* aGL); GLuint Texture() { return mTexture; } protected: void UnwrapImpl(); }; struct ScopedFramebuffer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mFB; public: explicit ScopedFramebuffer(GLContext* aGL); GLuint FB() { return mFB; } protected: void UnwrapImpl(); }; struct ScopedRenderbuffer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mRB; public: explicit ScopedRenderbuffer(GLContext* aGL); GLuint RB() { return mRB; } protected: void UnwrapImpl(); }; struct ScopedBindTexture : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mOldTex; GLenum mTarget; private: void Init(GLenum aTarget); public: ScopedBindTexture(GLContext* aGL, GLuint aNewTex, GLenum aTarget = LOCAL_GL_TEXTURE_2D); protected: void UnwrapImpl(); }; struct ScopedBindRenderbuffer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mOldRB; private: void Init(); public: explicit ScopedBindRenderbuffer(GLContext* aGL); ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB); protected: void UnwrapImpl(); }; struct ScopedFramebufferForTexture : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: bool mComplete; // True if the framebuffer we create is complete. GLuint mFB; public: ScopedFramebufferForTexture(GLContext* aGL, GLuint aTexture, GLenum aTarget = LOCAL_GL_TEXTURE_2D); bool IsComplete() const { return mComplete; } GLuint FB() const { MOZ_ASSERT(IsComplete()); return mFB; } protected: void UnwrapImpl(); }; struct ScopedFramebufferForRenderbuffer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: bool mComplete; // True if the framebuffer we create is complete. GLuint mFB; public: ScopedFramebufferForRenderbuffer(GLContext* aGL, GLuint aRB); bool IsComplete() const { return mComplete; } GLuint FB() const { return mFB; } protected: void UnwrapImpl(); }; struct ScopedViewportRect : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLint mSavedViewportRect[4]; public: ScopedViewportRect(GLContext* aGL, GLint x, GLint y, GLsizei width, GLsizei height); protected: void UnwrapImpl(); }; struct ScopedScissorRect : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLint mSavedScissorRect[4]; public: ScopedScissorRect(GLContext* aGL, GLint x, GLint y, GLsizei width, GLsizei height); explicit ScopedScissorRect(GLContext* aGL); protected: void UnwrapImpl(); }; struct ScopedVertexAttribPointer : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLuint mAttribIndex; GLint mAttribEnabled; GLint mAttribSize; GLint mAttribStride; GLint mAttribType; GLint mAttribNormalized; GLint mAttribBufferBinding; void* mAttribPointer; GLuint mBoundBuffer; public: ScopedVertexAttribPointer(GLContext* aGL, GLuint index, GLint size, GLenum type, realGLboolean normalized, GLsizei stride, GLuint buffer, const GLvoid* pointer); explicit ScopedVertexAttribPointer(GLContext* aGL, GLuint index); protected: void WrapImpl(GLuint index); void UnwrapImpl(); }; struct ScopedGLDrawState { explicit ScopedGLDrawState(GLContext* gl); ~ScopedGLDrawState(); GLuint boundProgram; GLuint boundBuffer; ScopedGLState blend; ScopedGLState cullFace; ScopedGLState depthTest; ScopedGLState dither; ScopedGLState polyOffsFill; ScopedGLState sampleAToC; ScopedGLState sampleCover; ScopedGLState scissor; ScopedGLState stencil; GLuint maxAttrib; UniquePtr attrib_enabled; GLint attrib0_size; GLint attrib0_stride; GLint attrib0_type; GLint attrib0_normalized; GLint attrib0_bufferBinding; void* attrib0_pointer; realGLboolean colorMask[4]; GLint viewport[4]; GLint scissorBox[4]; GLContext* const mGL; GLuint packAlign; }; struct ScopedPackAlignment : public ScopedGLWrapper { friend struct ScopedGLWrapper; protected: GLint mOldVal; public: ScopedPackAlignment(GLContext* aGL, GLint scopedVal); protected: void UnwrapImpl(); }; } /* namespace gl */ } /* namespace mozilla */ #endif /* SCOPEDGLHELPERS_H_ */