diff options
Diffstat (limited to 'dom/canvas/WebGLFramebuffer.h')
-rw-r--r-- | dom/canvas/WebGLFramebuffer.h | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/dom/canvas/WebGLFramebuffer.h b/dom/canvas/WebGLFramebuffer.h new file mode 100644 index 000000000..ac457c098 --- /dev/null +++ b/dom/canvas/WebGLFramebuffer.h @@ -0,0 +1,295 @@ +/* -*- Mode: C++; tab-width: 4; 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 WEBGL_FRAMEBUFFER_H_ +#define WEBGL_FRAMEBUFFER_H_ + +#include <vector> + +#include "mozilla/LinkedList.h" +#include "mozilla/WeakPtr.h" +#include "nsWrapperCache.h" + +#include "WebGLObjectModel.h" +#include "WebGLRenderbuffer.h" +#include "WebGLStrongTypes.h" +#include "WebGLTexture.h" +#include "WebGLTypes.h" + +namespace mozilla { + +class WebGLFramebuffer; +class WebGLRenderbuffer; +class WebGLTexture; + +template<typename T> +class PlacementArray; + +namespace gl { + class GLContext; +} // namespace gl + +class WebGLFBAttachPoint final +{ + friend class WebGLFramebuffer; +public: + WebGLFramebuffer* const mFB; + const GLenum mAttachmentPoint; + +protected: + WebGLRefPtr<WebGLTexture> mTexturePtr; + WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr; + TexImageTarget mTexImageTarget; + GLint mTexImageLayer; + uint32_t mTexImageLevel; + + //// + + WebGLFBAttachPoint(); + WebGLFBAttachPoint(WebGLFramebuffer* fb, GLenum attachmentPoint); + +public: + ~WebGLFBAttachPoint(); + + //// + + void Unlink(); + + bool IsDefined() const; + bool IsDeleteRequested() const; + + const webgl::FormatUsageInfo* Format() const; + uint32_t Samples() const; + + bool HasAlpha() const; + bool IsReadableFloat() const; + + void Clear(); + + void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level, + GLint layer = 0); + void SetRenderbuffer(WebGLRenderbuffer* rb); + + WebGLTexture* Texture() const { return mTexturePtr; } + WebGLRenderbuffer* Renderbuffer() const { return mRenderbufferPtr; } + + TexImageTarget ImageTarget() const { + return mTexImageTarget; + } + GLint Layer() const { + return mTexImageLayer; + } + uint32_t MipLevel() const { + return mTexImageLevel; + } + void AttachmentName(nsCString* out) const; + + bool HasUninitializedImageData() const; + void SetImageDataStatus(WebGLImageDataStatus x) const; + + void Size(uint32_t* const out_width, uint32_t* const out_height) const; + + bool HasImage() const; + bool IsComplete(WebGLContext* webgl, nsCString* const out_info) const; + + void Resolve(gl::GLContext* gl) const; + + JS::Value GetParameter(const char* funcName, WebGLContext* webgl, JSContext* cx, + GLenum target, GLenum attachment, GLenum pname, + ErrorResult* const out_error) const; + + void OnBackingStoreRespecified() const; + + bool IsEquivalentForFeedback(const WebGLFBAttachPoint& other) const { + if (!IsDefined() || !other.IsDefined()) + return false; + +#define _(X) X == other.X + return ( _(mRenderbufferPtr) && + _(mTexturePtr) && + _(mTexImageTarget.get()) && + _(mTexImageLevel) && + _(mTexImageLayer) ); +#undef _ + } + + //// + + struct Ordered { + const WebGLFBAttachPoint& mRef; + + explicit Ordered(const WebGLFBAttachPoint& ref) + : mRef(ref) + { } + + bool operator<(const Ordered& other) const { + MOZ_ASSERT(mRef.IsDefined() && other.mRef.IsDefined()); + +#define ORDER_BY(X) if (X != other.X) return X < other.X; + + ORDER_BY(mRef.mRenderbufferPtr) + ORDER_BY(mRef.mTexturePtr) + ORDER_BY(mRef.mTexImageTarget.get()) + ORDER_BY(mRef.mTexImageLevel) + ORDER_BY(mRef.mTexImageLayer) + +#undef ORDER_BY + return false; + } + }; +}; + +class WebGLFramebuffer final + : public nsWrapperCache + , public WebGLRefCountedObject<WebGLFramebuffer> + , public LinkedListElement<WebGLFramebuffer> + , public SupportsWeakPtr<WebGLFramebuffer> +{ + friend class WebGLContext; + +public: + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(WebGLFramebuffer) + + const GLuint mGLName; + +protected: +#ifdef ANDROID + // Bug 1140459: Some drivers (including our test slaves!) don't + // give reasonable answers for IsRenderbuffer, maybe others. + // This shows up on Android 2.3 emulator. + // + // So we track the `is a Framebuffer` state ourselves. + bool mIsFB; +#endif + + //// + + WebGLFBAttachPoint mDepthAttachment; + WebGLFBAttachPoint mStencilAttachment; + WebGLFBAttachPoint mDepthStencilAttachment; + + // In theory, this number can be unbounded based on the driver. However, no driver + // appears to expose more than 8. We might as well stop there too, for now. + // (http://opengl.gpuinfo.org/gl_stats_caps_single.php?listreportsbycap=GL_MAX_COLOR_ATTACHMENTS) + static const size_t kMaxColorAttachments = 8; // jgilbert's MacBook Pro exposes 8. + WebGLFBAttachPoint mColorAttachments[kMaxColorAttachments]; + + //// + + std::vector<const WebGLFBAttachPoint*> mColorDrawBuffers; // Non-null + const WebGLFBAttachPoint* mColorReadBuffer; // Null if NONE + + //// + + struct ResolvedData { + // IsFeedback + std::vector<const WebGLFBAttachPoint*> texDrawBuffers; // Non-null + std::set<WebGLFBAttachPoint::Ordered> drawSet; + std::set<WebGLFBAttachPoint::Ordered> readSet; + + explicit ResolvedData(const WebGLFramebuffer& parent); + }; + + UniquePtr<const ResolvedData> mResolvedCompleteData; + + //// + +public: + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer) + + WebGLFramebuffer(WebGLContext* webgl, GLuint fbo); + + WebGLContext* GetParentObject() const { return mContext; } + virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override; + +private: + ~WebGLFramebuffer() { + DeleteOnce(); + } + +public: + void Delete(); + + //// + + bool HasDefinedAttachments() const; + bool HasIncompleteAttachments(nsCString* const out_info) const; + bool AllImageRectsMatch() const; + bool AllImageSamplesMatch() const; + FBStatus PrecheckFramebufferStatus(nsCString* const out_info) const; + +protected: + Maybe<WebGLFBAttachPoint*> GetAttachPoint(GLenum attachment); // Fallible + Maybe<WebGLFBAttachPoint*> GetColorAttachPoint(GLenum attachment); // Fallible + void ResolveAttachments() const; + void RefreshDrawBuffers() const; + void RefreshReadBuffer() const; + bool ResolveAttachmentData(const char* funcName) const; + +public: + void DetachTexture(const WebGLTexture* tex); + void DetachRenderbuffer(const WebGLRenderbuffer* rb); + bool ValidateAndInitAttachments(const char* funcName); + bool ValidateClearBufferType(const char* funcName, GLenum buffer, uint32_t drawBuffer, + GLenum funcType) const; + + bool ValidateForRead(const char* info, + const webgl::FormatUsageInfo** const out_format, + uint32_t* const out_width, uint32_t* const out_height); + + //////////////// + // Getters + +#define GETTER(X) const decltype(m##X)& X() const { return m##X; } + + GETTER(DepthAttachment) + GETTER(StencilAttachment) + GETTER(DepthStencilAttachment) + GETTER(ColorDrawBuffers) + GETTER(ColorReadBuffer) + GETTER(ResolvedCompleteData) + +#undef GETTER + + //////////////// + // Invalidation + + bool IsResolvedComplete() const { return bool(mResolvedCompleteData); } + + void InvalidateFramebufferStatus() { + mResolvedCompleteData = nullptr; + } + + void RefreshResolvedData(); + + //////////////// + // WebGL funcs + + FBStatus CheckFramebufferStatus(const char* funcName); + void FramebufferRenderbuffer(const char* funcName, GLenum attachment, GLenum rbtarget, + WebGLRenderbuffer* rb); + void FramebufferTexture2D(const char* funcName, GLenum attachment, + GLenum texImageTarget, WebGLTexture* tex, GLint level); + void FramebufferTextureLayer(const char* funcName, GLenum attachment, + WebGLTexture* tex, GLint level, GLint layer); + void DrawBuffers(const char* funcName, const dom::Sequence<GLenum>& buffers); + void ReadBuffer(const char* funcName, GLenum attachPoint); + + JS::Value GetAttachmentParameter(const char* funcName, JSContext* cx, GLenum target, + GLenum attachment, GLenum pname, + ErrorResult* const out_error); + + static void BlitFramebuffer(WebGLContext* webgl, + const WebGLFramebuffer* src, GLint srcX0, GLint srcY0, + GLint srcX1, GLint srcY1, + const WebGLFramebuffer* dst, GLint dstX0, GLint dstY0, + GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); +}; + +} // namespace mozilla + +#endif // WEBGL_FRAMEBUFFER_H_ |