forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			1436 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1436 lines
		
	
	
	
		
			48 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* 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 WEBGLCONTEXT_H_
 | |
| #define WEBGLCONTEXT_H_
 | |
| 
 | |
| #include <bitset>
 | |
| #include <memory>
 | |
| #include <stdarg.h>
 | |
| 
 | |
| #include "GLContextTypes.h"
 | |
| #include "GLDefs.h"
 | |
| #include "GLScreenBuffer.h"
 | |
| #include "js/ScalarType.h"  // js::Scalar::Type
 | |
| #include "mozilla/Attributes.h"
 | |
| #include "mozilla/Atomics.h"
 | |
| #include "mozilla/CheckedInt.h"
 | |
| #include "mozilla/dom/ipc/IdType.h"
 | |
| #include "mozilla/dom/BindingDeclarations.h"
 | |
| #include "mozilla/dom/HTMLCanvasElement.h"
 | |
| #include "mozilla/dom/Nullable.h"
 | |
| #include "mozilla/dom/TypedArray.h"
 | |
| #include "mozilla/EnumeratedArray.h"
 | |
| #include "mozilla/gfx/2D.h"
 | |
| #include "mozilla/Mutex.h"
 | |
| #include "mozilla/StaticMutex.h"
 | |
| #include "mozilla/StaticPrefs_webgl.h"
 | |
| #include "mozilla/UniquePtr.h"
 | |
| #include "mozilla/WeakPtr.h"
 | |
| #include "nsICanvasRenderingContextInternal.h"
 | |
| #include "nsTArray.h"
 | |
| #include "SurfaceTypes.h"
 | |
| #include "ScopedGLHelpers.h"
 | |
| #include "TexUnpackBlob.h"
 | |
| 
 | |
| // Local
 | |
| #include "CacheInvalidator.h"
 | |
| #include "WebGLContextLossHandler.h"
 | |
| #include "WebGLExtensions.h"
 | |
| #include "WebGLObjectModel.h"
 | |
| #include "WebGLStrongTypes.h"
 | |
| #include "WebGLTypes.h"
 | |
| 
 | |
| // Generated
 | |
| #include "mozilla/dom/WebGLRenderingContextBinding.h"
 | |
| #include "mozilla/dom/WebGL2RenderingContextBinding.h"
 | |
| 
 | |
| #include <list>
 | |
| 
 | |
| class nsIDocShell;
 | |
| 
 | |
| // WebGL-only GLenums
 | |
| // clang-format off
 | |
| #define LOCAL_GL_BROWSER_DEFAULT_WEBGL              0x9244
 | |
| #define LOCAL_GL_CONTEXT_LOST_WEBGL                 0x9242
 | |
| #define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL      0x9247
 | |
| #define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
 | |
| #define LOCAL_GL_UNPACK_FLIP_Y_WEBGL                0x9240
 | |
| #define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL     0x9241
 | |
| // clang-format on
 | |
| 
 | |
| namespace mozilla {
 | |
| class HostWebGLContext;
 | |
| class ScopedCopyTexImageSource;
 | |
| class ScopedDrawCallWrapper;
 | |
| class ScopedResolveTexturesForDraw;
 | |
| class WebGLBuffer;
 | |
| class WebGLExtensionBase;
 | |
| class WebGLFramebuffer;
 | |
| class WebGLProgram;
 | |
| class WebGLQuery;
 | |
| class WebGLRenderbuffer;
 | |
| class WebGLSampler;
 | |
| class WebGLShader;
 | |
| class WebGLSync;
 | |
| class WebGLTexture;
 | |
| class WebGLTransformFeedback;
 | |
| class WebGLVertexArray;
 | |
| 
 | |
| namespace dom {
 | |
| class Document;
 | |
| class Element;
 | |
| class ImageData;
 | |
| class OwningHTMLCanvasElementOrOffscreenCanvas;
 | |
| struct WebGLContextAttributes;
 | |
| }  // namespace dom
 | |
| 
 | |
| namespace gfx {
 | |
| class SourceSurface;
 | |
| class VRLayerChild;
 | |
| }  // namespace gfx
 | |
| 
 | |
| namespace gl {
 | |
| class GLScreenBuffer;
 | |
| class MozFramebuffer;
 | |
| class SharedSurface;
 | |
| class Texture;
 | |
| }  // namespace gl
 | |
| 
 | |
| namespace layers {
 | |
| class CompositableHost;
 | |
| class RemoteTextureOwnerClient;
 | |
| class SurfaceDescriptor;
 | |
| }  // namespace layers
 | |
| 
 | |
| namespace webgl {
 | |
| class AvailabilityRunnable;
 | |
| struct CachedDrawFetchLimits;
 | |
| struct FbAttachInfo;
 | |
| struct FormatInfo;
 | |
| class FormatUsageAuthority;
 | |
| struct FormatUsageInfo;
 | |
| struct ImageInfo;
 | |
| struct LinkedProgramInfo;
 | |
| struct SamplerUniformInfo;
 | |
| struct SamplingState;
 | |
| class ScopedPrepForResourceClear;
 | |
| class ShaderValidator;
 | |
| class TexUnpackBlob;
 | |
| struct UniformInfo;
 | |
| struct UniformBlockInfo;
 | |
| struct VertAttribPointerDesc;
 | |
| }  // namespace webgl
 | |
| 
 | |
| struct WebGLTexImageData {
 | |
|   TexImageTarget mTarget;
 | |
|   int32_t mRowLength;
 | |
|   uint32_t mWidth;
 | |
|   uint32_t mHeight;
 | |
|   uint32_t mDepth;
 | |
|   gfxAlphaType mSrcAlphaType;
 | |
| };
 | |
| 
 | |
| struct WebGLTexPboOffset {
 | |
|   TexImageTarget mTarget;
 | |
|   uint32_t mWidth;
 | |
|   uint32_t mHeight;
 | |
|   uint32_t mDepth;
 | |
|   WebGLsizeiptr mPboOffset;
 | |
|   bool mHasExpectedImageSize;
 | |
|   GLsizei mExpectedImageSize;
 | |
| };
 | |
| 
 | |
| WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
 | |
| 
 | |
| void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
 | |
| 
 | |
| // From WebGLContextUtils
 | |
| TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
 | |
| 
 | |
| struct WebGLIntOrFloat {
 | |
|   const enum { Int, Float, Uint } mType;
 | |
| 
 | |
|   union {
 | |
|     GLint i;
 | |
|     GLfloat f;
 | |
|     GLuint u;
 | |
|   } mValue;
 | |
| 
 | |
|   explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; }
 | |
|   explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; }
 | |
| 
 | |
|   GLint AsInt() const {
 | |
|     return (mType == Int) ? mValue.i : NS_lroundf(mValue.f);
 | |
|   }
 | |
|   GLfloat AsFloat() const {
 | |
|     return (mType == Float) ? mValue.f : GLfloat(mValue.i);
 | |
|   }
 | |
| };
 | |
| 
 | |
| ////////////////////////////////////
 | |
| 
 | |
| namespace webgl {
 | |
| 
 | |
| class AvailabilityRunnable final : public DiscardableRunnable {
 | |
|  public:
 | |
|   const WeakPtr<const ClientWebGLContext> mWebGL;
 | |
|   std::vector<WeakPtr<WebGLQueryJS>> mQueries;
 | |
|   std::vector<WeakPtr<WebGLSyncJS>> mSyncs;
 | |
| 
 | |
|   explicit AvailabilityRunnable(const ClientWebGLContext* webgl);
 | |
|   ~AvailabilityRunnable();
 | |
| 
 | |
|   NS_IMETHOD Run() override;
 | |
| };
 | |
| 
 | |
| }  // namespace webgl
 | |
| 
 | |
| ////////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| class WebGLContext : public VRefCounted, public SupportsWeakPtr {
 | |
|   friend class ScopedDrawCallWrapper;
 | |
|   friend class ScopedDrawWithTransformFeedback;
 | |
|   friend class ScopedFakeVertexAttrib0;
 | |
|   friend class ScopedFBRebinder;
 | |
|   friend class WebGL2Context;
 | |
|   friend class WebGLContextUserData;
 | |
|   friend class WebGLExtensionCompressedTextureASTC;
 | |
|   friend class WebGLExtensionCompressedTextureBPTC;
 | |
|   friend class WebGLExtensionCompressedTextureES3;
 | |
|   friend class WebGLExtensionCompressedTextureETC1;
 | |
|   friend class WebGLExtensionCompressedTexturePVRTC;
 | |
|   friend class WebGLExtensionCompressedTextureRGTC;
 | |
|   friend class WebGLExtensionCompressedTextureS3TC;
 | |
|   friend class WebGLExtensionCompressedTextureS3TC_SRGB;
 | |
|   friend class WebGLExtensionDepthTexture;
 | |
|   friend class WebGLExtensionDisjointTimerQuery;
 | |
|   friend class WebGLExtensionDrawBuffers;
 | |
|   friend class WebGLExtensionLoseContext;
 | |
|   friend class WebGLExtensionMOZDebug;
 | |
|   friend class WebGLExtensionVertexArray;
 | |
|   friend class WebGLMemoryTracker;
 | |
|   friend class webgl::AvailabilityRunnable;
 | |
|   friend struct webgl::LinkedProgramInfo;
 | |
|   friend struct webgl::SamplerUniformInfo;
 | |
|   friend class webgl::ScopedPrepForResourceClear;
 | |
|   friend struct webgl::UniformBlockInfo;
 | |
| 
 | |
|   friend const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext*, GLenum,
 | |
|                                                           uint32_t);
 | |
|   friend RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
 | |
|       WebGLProgram* prog, gl::GLContext* gl);
 | |
| 
 | |
|   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLContext, override)
 | |
| 
 | |
|   enum {
 | |
|     UNPACK_FLIP_Y_WEBGL = 0x9240,
 | |
|     UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
 | |
|     // We throw InvalidOperation in TexImage if we fail to use GPU fast-path
 | |
|     // for texture copy when it is set to true, only for debug purpose.
 | |
|     UNPACK_REQUIRE_FASTPATH = 0x10001,
 | |
|     CONTEXT_LOST_WEBGL = 0x9242,
 | |
|     UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
 | |
|     BROWSER_DEFAULT_WEBGL = 0x9244,
 | |
|     UNMASKED_VENDOR_WEBGL = 0x9245,
 | |
|     UNMASKED_RENDERER_WEBGL = 0x9246
 | |
|   };
 | |
| 
 | |
|  private:
 | |
|   class LruPosition final {
 | |
|     std::list<WebGLContext*>::iterator mItr;
 | |
| 
 | |
|     LruPosition(const LruPosition&) = delete;
 | |
|     LruPosition(LruPosition&&) = delete;
 | |
|     LruPosition& operator=(const LruPosition&) = delete;
 | |
|     LruPosition& operator=(LruPosition&&) = delete;
 | |
| 
 | |
|    public:
 | |
|     void AssignLocked(WebGLContext& aContext) MOZ_REQUIRES(sLruMutex);
 | |
|     void Reset();
 | |
|     void ResetLocked() MOZ_REQUIRES(sLruMutex);
 | |
|     bool IsInsertedLocked() const MOZ_REQUIRES(sLruMutex);
 | |
| 
 | |
|     LruPosition();
 | |
|     explicit LruPosition(WebGLContext&);
 | |
| 
 | |
|     ~LruPosition() { Reset(); }
 | |
|   };
 | |
| 
 | |
|   mutable LruPosition mLruPosition MOZ_GUARDED_BY(sLruMutex);
 | |
| 
 | |
|   void BumpLruLocked() MOZ_REQUIRES(sLruMutex);
 | |
| 
 | |
|  public:
 | |
|   void BumpLru();
 | |
|   void LoseLruContextIfLimitExceeded();
 | |
| 
 | |
|   // -
 | |
| 
 | |
|   // We've had issues in the past with nulling `gl` without actually releasing
 | |
|   // all of our resources. This construction ensures that we are aware that we
 | |
|   // should only null `gl` in DestroyResourcesAndContext.
 | |
|   RefPtr<gl::GLContext> mGL_OnlyClearInDestroyResourcesAndContext;
 | |
| 
 | |
|  public:
 | |
|   // Grab a const reference so we can see changes, but can't make changes.
 | |
|   const decltype(mGL_OnlyClearInDestroyResourcesAndContext)& gl;
 | |
| 
 | |
|  public:
 | |
|   void CheckForInactivity();
 | |
| 
 | |
|  protected:
 | |
|   const WeakPtr<HostWebGLContext> mHost;
 | |
|   const bool mResistFingerprinting;
 | |
|   WebGLContextOptions mOptions;
 | |
|   const uint32_t mPrincipalKey;
 | |
|   Maybe<webgl::Limits> mLimits;
 | |
|   const uint32_t mMaxVertIdsPerDraw =
 | |
|       StaticPrefs::webgl_max_vert_ids_per_draw();
 | |
| 
 | |
|   bool mIsContextLost = false;
 | |
|   Atomic<bool> mPendingContextLoss = Atomic<bool>{false};
 | |
|   webgl::ContextLossReason mPendingContextLossReason =
 | |
|       webgl::ContextLossReason::None;
 | |
|   const uint32_t mMaxPerfWarnings = StaticPrefs::webgl_perf_max_warnings();
 | |
|   mutable uint64_t mNumPerfWarnings = 0;
 | |
|   const uint32_t mMaxAcceptableFBStatusInvals =
 | |
|       StaticPrefs::webgl_perf_max_acceptable_fb_status_invals();
 | |
|   bool mWarnOnce_DepthTexCompareFilterable = true;
 | |
| 
 | |
|   uint64_t mNextFenceId = 1;
 | |
|   uint64_t mCompletedFenceId = 0;
 | |
| 
 | |
|   std::unique_ptr<gl::Texture> mIncompleteTexOverride;
 | |
| 
 | |
|  public:
 | |
|   class FuncScope;
 | |
| 
 | |
|  private:
 | |
|   mutable FuncScope* mFuncScope = nullptr;
 | |
| 
 | |
|  public:
 | |
|   static RefPtr<WebGLContext> Create(HostWebGLContext*,
 | |
|                                      const webgl::InitContextDesc&,
 | |
|                                      webgl::InitContextResult* out);
 | |
| 
 | |
|  private:
 | |
|   webgl::OptionalRenderableFormatBits mOptionalRenderableFormatBits =
 | |
|       webgl::OptionalRenderableFormatBits{0};
 | |
|   void FinishInit();
 | |
| 
 | |
|  protected:
 | |
|   WebGLContext(HostWebGLContext*, const webgl::InitContextDesc&);
 | |
|   virtual ~WebGLContext();
 | |
| 
 | |
|   RefPtr<layers::CompositableHost> mCompositableHost;
 | |
| 
 | |
|   layers::LayersBackend mBackend = layers::LayersBackend::LAYERS_NONE;
 | |
| 
 | |
|  public:
 | |
|   void Resize(uvec2 size);
 | |
| 
 | |
|   void SetCompositableHost(RefPtr<layers::CompositableHost>& aCompositableHost);
 | |
| 
 | |
|   /**
 | |
|    * An abstract base class to be implemented by callers wanting to be notified
 | |
|    * that a refresh has occurred. Callers must ensure an observer is removed
 | |
|    * before it is destroyed.
 | |
|    */
 | |
|   virtual void DidRefresh();
 | |
| 
 | |
|   void OnMemoryPressure();
 | |
| 
 | |
|   // -
 | |
| 
 | |
|   /*
 | |
| 
 | |
|   Here are the bind calls that are supposed to be fully-validated client side,
 | |
|   so that client's binding state doesn't diverge:
 | |
|   * AttachShader
 | |
|   * DetachShader
 | |
|   * BindFramebuffer
 | |
|   * FramebufferAttach
 | |
|   * BindBuffer
 | |
|   * BindBufferRange
 | |
|   * BindTexture
 | |
|   * UseProgram
 | |
|   * BindSampler
 | |
|   * BindTransformFeedback
 | |
|   * BindVertexArray
 | |
|   * BeginQuery
 | |
|   * EndQuery
 | |
|   * ActiveTexture
 | |
| 
 | |
|   */
 | |
| 
 | |
|   const auto& CurFuncScope() const { return *mFuncScope; }
 | |
|   const char* FuncName() const;
 | |
| 
 | |
|   class FuncScope final {
 | |
|    public:
 | |
|     const WebGLContext& mWebGL;
 | |
|     const char* const mFuncName;
 | |
|     bool mBindFailureGuard = false;
 | |
| 
 | |
|    public:
 | |
|     FuncScope(const WebGLContext& webgl, const char* funcName);
 | |
|     ~FuncScope();
 | |
|   };
 | |
| 
 | |
|   void GenerateErrorImpl(const GLenum err, const nsACString& text) const {
 | |
|     GenerateErrorImpl(err, std::string(text.BeginReading()));
 | |
|   }
 | |
|   void GenerateErrorImpl(const GLenum err, const std::string& text) const;
 | |
| 
 | |
|   void GenerateError(const webgl::ErrorInfo& err) {
 | |
|     GenerateError(err.type, "%s", err.info.c_str());
 | |
|   }
 | |
| 
 | |
|   template <typename... Args>
 | |
|   void GenerateError(const GLenum err, const char* const fmt,
 | |
|                      const Args&... args) const {
 | |
|     MOZ_ASSERT(FuncName());
 | |
| 
 | |
|     nsCString text;
 | |
|     text.AppendPrintf("WebGL warning: %s: ", FuncName());
 | |
| 
 | |
| #ifdef __clang__
 | |
| #  pragma clang diagnostic push
 | |
| #  pragma clang diagnostic ignored "-Wformat-security"
 | |
| #elif defined(__GNUC__)
 | |
| #  pragma GCC diagnostic push
 | |
| #  pragma GCC diagnostic ignored "-Wformat-security"
 | |
| #endif
 | |
|     text.AppendPrintf(fmt, args...);
 | |
| #ifdef __clang__
 | |
| #  pragma clang diagnostic pop
 | |
| #elif defined(__GNUC__)
 | |
| #  pragma GCC diagnostic pop
 | |
| #endif
 | |
| 
 | |
|     GenerateErrorImpl(err, text);
 | |
|   }
 | |
| 
 | |
|   template <typename... Args>
 | |
|   void ErrorInvalidEnum(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(LOCAL_GL_INVALID_ENUM, fmt, args...);
 | |
|   }
 | |
|   template <typename... Args>
 | |
|   void ErrorInvalidOperation(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(LOCAL_GL_INVALID_OPERATION, fmt, args...);
 | |
|   }
 | |
|   template <typename... Args>
 | |
|   void ErrorInvalidValue(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(LOCAL_GL_INVALID_VALUE, fmt, args...);
 | |
|   }
 | |
|   template <typename... Args>
 | |
|   void ErrorInvalidFramebufferOperation(const char* const fmt,
 | |
|                                         const Args&... args) const {
 | |
|     GenerateError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION, fmt, args...);
 | |
|   }
 | |
|   template <typename... Args>
 | |
|   void ErrorOutOfMemory(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(LOCAL_GL_OUT_OF_MEMORY, fmt, args...);
 | |
|   }
 | |
| 
 | |
|   template <typename... Args>
 | |
|   void ErrorImplementationBug(const char* const fmt,
 | |
|                               const Args&... args) const {
 | |
|     const nsPrintfCString newFmt(
 | |
|         "Implementation bug, please file at %s! %s",
 | |
|         "https://bugzilla.mozilla.org/"
 | |
|         "enter_bug.cgi?product=Core&component=Canvas%3A+WebGL",
 | |
|         fmt);
 | |
|     GenerateError(LOCAL_GL_OUT_OF_MEMORY, newFmt.BeginReading(), args...);
 | |
|     MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
 | |
|     NS_ERROR("WebGLContext::ErrorImplementationBug");
 | |
|   }
 | |
| 
 | |
|   void ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const;
 | |
|   void ErrorInvalidEnumArg(const char* argName, GLenum val) const;
 | |
| 
 | |
|   static const char* ErrorName(GLenum error);
 | |
| 
 | |
|   void JsWarning(const std::string& text) const;
 | |
| 
 | |
|   /**
 | |
|    * Return displayable name for GLenum.
 | |
|    * This version is like gl::GLenumToStr but with out the GL_ prefix to
 | |
|    * keep consistency with how errors are reported from WebGL.
 | |
|    * Returns hex formatted version of glenum if glenum is unknown.
 | |
|    */
 | |
|   static void EnumName(GLenum val, nsCString* out_name);
 | |
| 
 | |
|   void DummyReadFramebufferOperation();
 | |
| 
 | |
|   dom::ContentParentId GetContentId() const;
 | |
| 
 | |
|   WebGLTexture* GetActiveTex(const GLenum texTarget) const;
 | |
| 
 | |
|   gl::GLContext* GL() const { return gl; }
 | |
| 
 | |
|   bool IsPremultAlpha() const { return mOptions.premultipliedAlpha; }
 | |
| 
 | |
|   bool IsPreservingDrawingBuffer() const {
 | |
|     return mOptions.preserveDrawingBuffer;
 | |
|   }
 | |
| 
 | |
|   // Present to compositor
 | |
|  private:
 | |
|   bool PresentInto(gl::SwapChain& swapChain);
 | |
|   bool PresentIntoXR(gl::SwapChain& swapChain, const gl::MozFramebuffer& xrFb);
 | |
| 
 | |
|  public:
 | |
|   // Present swaps the front and back buffers of the swap chain for compositing.
 | |
|   // This assumes the framebuffer may directly alias with the back buffer,
 | |
|   // dependent on remoting state or other concerns. Framebuffer and swap chain
 | |
|   // surface formats are assumed to be similar to enable this aliasing. As such,
 | |
|   // the back buffer may be invalidated by this swap with the front buffer,
 | |
|   // unless overriden by explicitly setting the preserveDrawingBuffer option,
 | |
|   // which may incur a further copy to preserve the back buffer.
 | |
|   void Present(
 | |
|       WebGLFramebuffer*, layers::TextureType, const bool webvr,
 | |
|       const webgl::SwapChainOptions& options = webgl::SwapChainOptions());
 | |
|   // CopyToSwapChain forces a copy from the supplied framebuffer into the back
 | |
|   // buffer before swapping the front and back buffers of the swap chain for
 | |
|   // compositing. The formats of the framebuffer and the swap chain buffers
 | |
|   // may differ subject to available format conversion options. Since this
 | |
|   // operation uses an explicit copy, it inherently preserves the framebuffer
 | |
|   // without need to set the preserveDrawingBuffer option.
 | |
|   bool CopyToSwapChain(
 | |
|       WebGLFramebuffer*, layers::TextureType,
 | |
|       const webgl::SwapChainOptions& options = webgl::SwapChainOptions(),
 | |
|       layers::RemoteTextureOwnerClient* ownerClient = nullptr);
 | |
|   // In use cases where a framebuffer is used as an offscreen framebuffer and
 | |
|   // does not need to be committed to the swap chain, it may still be useful
 | |
|   // for the implementation to delineate distinct frames, such as when sharing
 | |
|   // a single WebGLContext amongst many distinct users. EndOfFrame signals that
 | |
|   // frame rendering is complete so that any implementation side-effects such
 | |
|   // as resetting internal profile counters or resource queues may be handled
 | |
|   // appropriately.
 | |
|   void EndOfFrame();
 | |
|   RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot();
 | |
|   Maybe<uvec2> FrontBufferSnapshotInto(
 | |
|       const Maybe<Range<uint8_t>> dest,
 | |
|       const Maybe<size_t> destStride = Nothing());
 | |
|   Maybe<uvec2> FrontBufferSnapshotInto(
 | |
|       const std::shared_ptr<gl::SharedSurface>& front,
 | |
|       const Maybe<Range<uint8_t>> dest,
 | |
|       const Maybe<size_t> destStride = Nothing());
 | |
|   Maybe<uvec2> SnapshotInto(GLuint srcFb, const gfx::IntSize& size,
 | |
|                             const Range<uint8_t>& dest,
 | |
|                             const Maybe<size_t> destStride = Nothing());
 | |
|   gl::SwapChain* GetSwapChain(WebGLFramebuffer*, const bool webvr);
 | |
|   Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
 | |
|                                                   const bool webvr);
 | |
| 
 | |
|   void ClearVRSwapChain();
 | |
| 
 | |
|   void RunContextLossTimer();
 | |
|   void CheckForContextLoss();
 | |
|   void HandlePendingContextLoss();
 | |
| 
 | |
|   bool TryToRestoreContext();
 | |
| 
 | |
|   void AssertCachedBindings() const;
 | |
|   void AssertCachedGlobalState() const;
 | |
| 
 | |
|   // WebIDL WebGLRenderingContext API
 | |
|   void Commit();
 | |
| 
 | |
|   uvec2 DrawingBufferSize();
 | |
| 
 | |
|  public:
 | |
|   void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
 | |
| 
 | |
|   // This is the entrypoint. Don't test against it directly.
 | |
|   bool IsContextLost() const {
 | |
|     auto* self = const_cast<WebGLContext*>(this);
 | |
|     if (self->mPendingContextLoss.exchange(false)) {
 | |
|       self->HandlePendingContextLoss();
 | |
|     }
 | |
|     return mIsContextLost;
 | |
|   }
 | |
| 
 | |
|   // -
 | |
| 
 | |
|   RefPtr<WebGLBuffer> CreateBuffer();
 | |
|   RefPtr<WebGLFramebuffer> CreateFramebuffer();
 | |
|   RefPtr<WebGLFramebuffer> CreateOpaqueFramebuffer(
 | |
|       const webgl::OpaqueFramebufferOptions& options);
 | |
|   RefPtr<WebGLProgram> CreateProgram();
 | |
|   RefPtr<WebGLQuery> CreateQuery();
 | |
|   RefPtr<WebGLRenderbuffer> CreateRenderbuffer();
 | |
|   RefPtr<WebGLShader> CreateShader(GLenum type);
 | |
|   RefPtr<WebGLTexture> CreateTexture();
 | |
|   RefPtr<WebGLVertexArray> CreateVertexArray();
 | |
| 
 | |
|   // -
 | |
| 
 | |
|   void AttachShader(WebGLProgram& prog, WebGLShader& shader);
 | |
|   void BindAttribLocation(WebGLProgram& prog, GLuint location,
 | |
|                           const std::string& name) const;
 | |
|   void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
 | |
|   void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
 | |
|   void BindVertexArray(WebGLVertexArray* vao);
 | |
|   void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
 | |
|   void BlendEquationSeparate(Maybe<GLuint> i, GLenum modeRGB, GLenum modeAlpha);
 | |
|   void BlendFuncSeparate(Maybe<GLuint> i, GLenum srcRGB, GLenum dstRGB,
 | |
|                          GLenum srcAlpha, GLenum dstAlpha);
 | |
|   GLenum CheckFramebufferStatus(GLenum target);
 | |
|   void Clear(GLbitfield mask);
 | |
|   void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
 | |
|   void ClearDepth(GLclampf v);
 | |
|   void ClearStencil(GLint v);
 | |
|   void ColorMask(Maybe<GLuint> i, uint8_t mask);
 | |
|   void CompileShader(WebGLShader& shader);
 | |
| 
 | |
|  private:
 | |
|   void CompileShaderANGLE(WebGLShader* shader);
 | |
|   void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource);
 | |
| 
 | |
|  public:
 | |
|   void CullFace(GLenum face);
 | |
|   void DepthFunc(GLenum func);
 | |
|   void DepthMask(WebGLboolean b);
 | |
|   void DepthRange(GLclampf zNear, GLclampf zFar);
 | |
|   void DetachShader(WebGLProgram& prog, const WebGLShader& shader);
 | |
|   void DrawBuffers(const std::vector<GLenum>& buffers);
 | |
|   void Flush();
 | |
|   void Finish();
 | |
| 
 | |
|   void FramebufferAttach(GLenum target, GLenum attachSlot,
 | |
|                          GLenum bindImageTarget,
 | |
|                          const webgl::FbAttachInfo& toAttach);
 | |
| 
 | |
|   void FrontFace(GLenum mode);
 | |
| 
 | |
|   Maybe<double> GetBufferParameter(GLenum target, GLenum pname);
 | |
|   webgl::CompileResult GetCompileResult(const WebGLShader&) const;
 | |
|   GLenum GetError();
 | |
|   GLint GetFragDataLocation(const WebGLProgram&, const std::string& name) const;
 | |
| 
 | |
|   Maybe<double> GetFramebufferAttachmentParameter(WebGLFramebuffer*,
 | |
|                                                   GLenum attachment,
 | |
|                                                   GLenum pname) const;
 | |
| 
 | |
|   Maybe<double> GetRenderbufferParameter(const WebGLRenderbuffer&,
 | |
|                                          GLenum pname) const;
 | |
|   webgl::LinkResult GetLinkResult(const WebGLProgram&) const;
 | |
| 
 | |
|   Maybe<webgl::ShaderPrecisionFormat> GetShaderPrecisionFormat(
 | |
|       GLenum shadertype, GLenum precisiontype) const;
 | |
| 
 | |
|   webgl::GetUniformData GetUniform(const WebGLProgram&, uint32_t loc) const;
 | |
| 
 | |
|   void Hint(GLenum target, GLenum mode);
 | |
| 
 | |
|   void LineWidth(GLfloat width);
 | |
|   void LinkProgram(WebGLProgram& prog);
 | |
|   void PolygonOffset(GLfloat factor, GLfloat units);
 | |
|   void ProvokingVertex(webgl::ProvokingVertex) const;
 | |
| 
 | |
|   ////
 | |
| 
 | |
|   webgl::PackingInfo ValidImplementationColorReadPI(
 | |
|       const webgl::FormatUsageInfo* usage) const;
 | |
| 
 | |
|  protected:
 | |
|   webgl::ReadPixelsResult ReadPixelsImpl(const webgl::ReadPixelsDesc&,
 | |
|                                          uintptr_t dest, uint64_t availBytes);
 | |
|   bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
 | |
|                               const webgl::ReadPixelsDesc&, uintptr_t dest,
 | |
|                               uint64_t dataLen, uint32_t rowStride);
 | |
| 
 | |
|  public:
 | |
|   void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset);
 | |
|   webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc&,
 | |
|                                          const Range<uint8_t>& dest);
 | |
| 
 | |
|   ////
 | |
| 
 | |
|   void RenderbufferStorageMultisample(WebGLRenderbuffer&, uint32_t samples,
 | |
|                                       GLenum internalformat, uint32_t width,
 | |
|                                       uint32_t height) const;
 | |
| 
 | |
|  public:
 | |
|   void SampleCoverage(GLclampf value, WebGLboolean invert);
 | |
|   void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
 | |
|   void ShaderSource(WebGLShader& shader, const std::string& source) const;
 | |
|   void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
 | |
|   void StencilMaskSeparate(GLenum face, GLuint mask);
 | |
|   void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
 | |
|                          GLenum dppass);
 | |
| 
 | |
|   //////////////////////////
 | |
| 
 | |
|   void UniformData(uint32_t loc, bool transpose,
 | |
|                    const Span<const webgl::UniformDataVal>& data) const;
 | |
| 
 | |
|   ////////////////////////////////////
 | |
| 
 | |
|   void UseProgram(WebGLProgram* prog);
 | |
| 
 | |
|   bool ValidateAttribArraySetter(uint32_t count, uint32_t arrayLength);
 | |
|   bool ValidateProgram(const WebGLProgram& prog) const;
 | |
|   void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // Buffer Objects (WebGLContextBuffers.cpp)
 | |
|   void BindBuffer(GLenum target, WebGLBuffer* buffer);
 | |
|   void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
 | |
|                        uint64_t offset, uint64_t size);
 | |
| 
 | |
|   void BufferData(GLenum target, uint64_t dataLen, const uint8_t* data,
 | |
|                   GLenum usage) const;
 | |
|   void UninitializedBufferData_SizeOnly(GLenum target, uint64_t dataLen,
 | |
|                                         GLenum usage) const;
 | |
|   // The unsynchronized flag may allow for better performance when
 | |
|   // interleaving buffer updates with draw calls. However, care must
 | |
|   // be taken. This has similar semantics to glMapBufferRange's
 | |
|   // GL_MAP_UNSYNCHRONIZED_BIT: the results of any pending operations
 | |
|   // that reference the region of the buffer being updated are
 | |
|   // undefined.
 | |
|   void BufferSubData(GLenum target, uint64_t dstByteOffset, uint64_t srcDataLen,
 | |
|                      const uint8_t* srcData, bool unsynchronized = false) const;
 | |
| 
 | |
|  protected:
 | |
|   // bound buffer state
 | |
|   RefPtr<WebGLBuffer> mBoundArrayBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundCopyReadBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundCopyWriteBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundPixelPackBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundPixelUnpackBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
 | |
|   RefPtr<WebGLBuffer> mBoundUniformBuffer;
 | |
| 
 | |
|   std::vector<IndexedBufferBinding> mIndexedUniformBufferBindings;
 | |
| 
 | |
|   RefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
 | |
|   RefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
 | |
|                                                     GLuint index);
 | |
| 
 | |
|   // -
 | |
| 
 | |
|   void GenErrorIllegalUse(GLenum useTarget, uint32_t useId, GLenum boundTarget,
 | |
|                           uint32_t boundId) const;
 | |
| 
 | |
|   bool ValidateBufferForNonTf(const WebGLBuffer&, GLenum nonTfTarget,
 | |
|                               uint32_t nonTfId) const;
 | |
| 
 | |
|   bool ValidateBufferForNonTf(const WebGLBuffer* const nonTfBuffer,
 | |
|                               const GLenum nonTfTarget,
 | |
|                               const uint32_t nonTfId = -1) const {
 | |
|     if (!nonTfBuffer) return true;
 | |
|     return ValidateBufferForNonTf(*nonTfBuffer, nonTfTarget, nonTfId);
 | |
|   }
 | |
| 
 | |
|   bool ValidateBuffersForTf(const WebGLTransformFeedback&,
 | |
|                             const webgl::LinkedProgramInfo&) const;
 | |
|   bool ValidateBuffersForTf(
 | |
|       const std::vector<webgl::BufferAndIndex>& tfBuffers) const;
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // Queries (WebGL2ContextQueries.cpp)
 | |
|  protected:
 | |
|   RefPtr<WebGLQuery> mQuerySlot_SamplesPassed;
 | |
|   RefPtr<WebGLQuery> mQuerySlot_TFPrimsWritten;
 | |
|   RefPtr<WebGLQuery> mQuerySlot_TimeElapsed;
 | |
| 
 | |
|   RefPtr<WebGLQuery>* ValidateQuerySlotByTarget(GLenum target);
 | |
| 
 | |
|  public:
 | |
|   void BeginQuery(GLenum target, WebGLQuery& query);
 | |
|   void EndQuery(GLenum target);
 | |
|   Maybe<double> GetQueryParameter(const WebGLQuery& query, GLenum pname) const;
 | |
|   void QueryCounter(WebGLQuery&) const;
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // State and State Requests (WebGLContextState.cpp)
 | |
|   void SetEnabled(GLenum cap, Maybe<GLuint> i, bool enabled);
 | |
|   bool GetStencilBits(GLint* const out_stencilBits) const;
 | |
| 
 | |
|   virtual Maybe<double> GetParameter(GLenum pname);
 | |
|   Maybe<std::string> GetString(GLenum pname) const;
 | |
| 
 | |
|   bool IsEnabled(GLenum cap);
 | |
| 
 | |
|  private:
 | |
|   static StaticMutex sLruMutex;
 | |
|   static std::list<WebGLContext*> sLru MOZ_GUARDED_BY(sLruMutex);
 | |
| 
 | |
|   // State tracking slots
 | |
|   bool mDitherEnabled = true;
 | |
|   bool mRasterizerDiscardEnabled = false;
 | |
|   bool mScissorTestEnabled = false;
 | |
|   bool mDepthTestEnabled = false;
 | |
|   bool mStencilTestEnabled = false;
 | |
|   GLenum mGenerateMipmapHint = LOCAL_GL_DONT_CARE;
 | |
| 
 | |
|   struct ScissorRect final {
 | |
|     GLint x;
 | |
|     GLint y;
 | |
|     GLsizei w;
 | |
|     GLsizei h;
 | |
| 
 | |
|     void Apply(gl::GLContext&) const;
 | |
|   };
 | |
|   ScissorRect mScissorRect = {};
 | |
| 
 | |
|   bool ValidateCapabilityEnum(GLenum cap);
 | |
|   bool* GetStateTrackingSlot(GLenum cap, GLuint i);
 | |
| 
 | |
|   // Allocation debugging variables
 | |
|   mutable uint64_t mDataAllocGLCallCount = 0;
 | |
| 
 | |
|   void OnDataAllocCall() const { mDataAllocGLCallCount++; }
 | |
| 
 | |
|   uint64_t GetNumGLDataAllocCalls() const { return mDataAllocGLCallCount; }
 | |
| 
 | |
|   void OnEndOfFrame();
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // Texture funcions (WebGLContextTextures.cpp)
 | |
|  public:
 | |
|   void ActiveTexture(uint32_t texUnit);
 | |
|   void BindTexture(GLenum texTarget, WebGLTexture* tex);
 | |
|   void GenerateMipmap(GLenum texTarget);
 | |
| 
 | |
|   Maybe<double> GetTexParameter(const WebGLTexture&, GLenum pname) const;
 | |
|   void TexParameter_base(GLenum texTarget, GLenum pname,
 | |
|                          const FloatOrInt& param);
 | |
| 
 | |
|   virtual bool IsTexParamValid(GLenum pname) const;
 | |
| 
 | |
|   ////////////////////////////////////
 | |
|   // Uploads
 | |
| 
 | |
|   // CompressedTexSubImage if `sub`
 | |
|   void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
 | |
|                           GLenum format, uvec3 offset, uvec3 size,
 | |
|                           const Range<const uint8_t>& src,
 | |
|                           const uint32_t pboImageSize,
 | |
|                           const Maybe<uint64_t>& pboOffset) const;
 | |
| 
 | |
|   // CopyTexSubImage if `!respectFormat`
 | |
|   void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
 | |
|                     uvec3 dstOffset, const ivec2& srcOffset,
 | |
|                     const uvec2& size) const;
 | |
| 
 | |
|   // TexSubImage if `!respectFormat`
 | |
|   void TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
 | |
|                 const webgl::PackingInfo& pi,
 | |
|                 const webgl::TexUnpackBlobDesc&) const;
 | |
| 
 | |
|   void TexStorage(GLenum texTarget, uint32_t levels, GLenum sizedFormat,
 | |
|                   uvec3 size) const;
 | |
| 
 | |
|   UniquePtr<webgl::TexUnpackBlob> ToTexUnpackBytes(
 | |
|       const WebGLTexImageData& imageData);
 | |
| 
 | |
|   UniquePtr<webgl::TexUnpackBytes> ToTexUnpackBytes(WebGLTexPboOffset& aPbo);
 | |
| 
 | |
|   ////////////////////////////////////
 | |
|   // WebGLTextureUpload.cpp
 | |
|  protected:
 | |
|   bool ValidateTexImageSpecification(uint8_t funcDims, GLenum texImageTarget,
 | |
|                                      GLint level, GLsizei width, GLsizei height,
 | |
|                                      GLsizei depth, GLint border,
 | |
|                                      TexImageTarget* const out_target,
 | |
|                                      WebGLTexture** const out_texture,
 | |
|                                      webgl::ImageInfo** const out_imageInfo);
 | |
|   bool ValidateTexImageSelection(uint8_t funcDims, GLenum texImageTarget,
 | |
|                                  GLint level, GLint xOffset, GLint yOffset,
 | |
|                                  GLint zOffset, GLsizei width, GLsizei height,
 | |
|                                  GLsizei depth,
 | |
|                                  TexImageTarget* const out_target,
 | |
|                                  WebGLTexture** const out_texture,
 | |
|                                  webgl::ImageInfo** const out_imageInfo);
 | |
|   bool ValidateUnpackInfo(bool usePBOs, GLenum format, GLenum type,
 | |
|                           webgl::PackingInfo* const out);
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // Vertices Feature (WebGLContextVertices.cpp)
 | |
|   GLenum mPrimRestartTypeBytes = 0;
 | |
| 
 | |
|  public:
 | |
|   void DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertexCount,
 | |
|                            GLsizei instanceCount);
 | |
|   void DrawElementsInstanced(GLenum mode, GLsizei vertexCount, GLenum type,
 | |
|                              WebGLintptr byteOffset, GLsizei instanceCount);
 | |
| 
 | |
|   void EnableVertexAttribArray(GLuint index);
 | |
|   void DisableVertexAttribArray(GLuint index);
 | |
| 
 | |
|   Maybe<double> GetVertexAttrib(GLuint index, GLenum pname);
 | |
| 
 | |
|   ////
 | |
| 
 | |
|   void VertexAttrib4T(GLuint index, const webgl::TypedQuad&);
 | |
| 
 | |
|   ////
 | |
| 
 | |
|   void VertexAttribPointer(uint32_t index, const webgl::VertAttribPointerDesc&);
 | |
| 
 | |
|   void VertexAttribDivisor(GLuint index, GLuint divisor);
 | |
| 
 | |
|  private:
 | |
|   WebGLBuffer* DrawElements_check(GLsizei indexCount, GLenum type,
 | |
|                                   WebGLintptr byteOffset,
 | |
|                                   GLsizei instanceCount);
 | |
|   void Draw_cleanup();
 | |
| 
 | |
|   void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
 | |
|                             const GLfloat* ptr);
 | |
|   void VertexAttrib2fv_base(GLuint index, uint32_t arrayLength,
 | |
|                             const GLfloat* ptr);
 | |
|   void VertexAttrib3fv_base(GLuint index, uint32_t arrayLength,
 | |
|                             const GLfloat* ptr);
 | |
|   void VertexAttrib4fv_base(GLuint index, uint32_t arrayLength,
 | |
|                             const GLfloat* ptr);
 | |
| 
 | |
|   bool BindArrayAttribToLocation0(WebGLProgram* prog);
 | |
| 
 | |
|   // -----------------------------------------------------------------------------
 | |
|   // PROTECTED
 | |
|  protected:
 | |
|   WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need() const;
 | |
|   bool DoFakeVertexAttrib0(uint64_t fakeVertexCount,
 | |
|                            WebGLVertexAttrib0Status whatDoesAttrib0Need);
 | |
|   void UndoFakeVertexAttrib0();
 | |
| 
 | |
|   bool mResetLayer = true;
 | |
|   bool mOptionsFrozen = false;
 | |
|   bool mIsMesa = false;
 | |
|   bool mLoseContextOnMemoryPressure = false;
 | |
|   bool mCanLoseContextInForeground = true;
 | |
|   bool mShouldPresent = false;
 | |
|   bool mDisableFragHighP = false;
 | |
|   bool mForceResizeOnPresent = false;
 | |
|   bool mVRReady = false;
 | |
| 
 | |
|   template <typename WebGLObjectType>
 | |
|   void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
 | |
| 
 | |
|   GLuint mActiveTexture = 0;
 | |
|   GLenum mDefaultFB_DrawBuffer0 = LOCAL_GL_BACK;
 | |
|   GLenum mDefaultFB_ReadBuffer = LOCAL_GL_BACK;
 | |
| 
 | |
|   mutable GLenum mWebGLError = 0;
 | |
| 
 | |
|   std::unique_ptr<webgl::ShaderValidator> CreateShaderValidator(
 | |
|       GLenum shaderType) const;
 | |
| 
 | |
|   // some GL constants
 | |
|   uint32_t mGLMaxFragmentUniformVectors = 0;
 | |
|   uint32_t mGLMaxVertexUniformVectors = 0;
 | |
|   uint32_t mGLMaxVertexOutputVectors = 0;
 | |
|   uint32_t mGLMaxFragmentInputVectors = 0;
 | |
| 
 | |
|   uint32_t mGLMaxVertexTextureImageUnits = 0;
 | |
|   uint32_t mGLMaxFragmentTextureImageUnits = 0;
 | |
|   uint32_t mGLMaxCombinedTextureImageUnits = 0;
 | |
| 
 | |
|   // ES3:
 | |
|   uint32_t mGLMinProgramTexelOffset = 0;
 | |
|   uint32_t mGLMaxProgramTexelOffset = 0;
 | |
| 
 | |
|  public:
 | |
|   auto GLMaxDrawBuffers() const { return mLimits->maxColorDrawBuffers; }
 | |
| 
 | |
|   uint32_t MaxValidDrawBuffers() const {
 | |
|     if (IsWebGL2() ||
 | |
|         IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
 | |
|       return GLMaxDrawBuffers();
 | |
|     }
 | |
|     return 1;
 | |
|   }
 | |
| 
 | |
|   GLenum LastColorAttachmentEnum() const {
 | |
|     return LOCAL_GL_COLOR_ATTACHMENT0 + MaxValidDrawBuffers() - 1;
 | |
|   }
 | |
| 
 | |
|   const auto& Options() const { return mOptions; }
 | |
| 
 | |
|  protected:
 | |
|   uint32_t mGLMaxRenderbufferSize = 0;
 | |
| 
 | |
|  public:
 | |
|   const auto& Limits() const { return *mLimits; }
 | |
|   auto MaxVertexAttribs() const { return mLimits->maxVertexAttribs; }
 | |
|   auto GLMaxTextureUnits() const { return mLimits->maxTexUnits; }
 | |
| 
 | |
|   bool IsFormatValidForFB(TexInternalFormat format) const;
 | |
| 
 | |
|  protected:
 | |
|   // -------------------------------------------------------------------------
 | |
|   // WebGL extensions (implemented in WebGLContextExtensions.cpp)
 | |
| 
 | |
|   EnumeratedArray<WebGLExtensionID, std::unique_ptr<WebGLExtensionBase>,
 | |
|                   size_t(WebGLExtensionID::Max)>
 | |
|       mExtensions;
 | |
| 
 | |
|  public:
 | |
|   void RequestExtension(WebGLExtensionID, bool explicitly = true);
 | |
| 
 | |
|   // returns true if the extension has been enabled by calling getExtension.
 | |
|   bool IsExtensionEnabled(const WebGLExtensionID id) const {
 | |
|     return bool(mExtensions[id]);
 | |
|   }
 | |
| 
 | |
|   bool IsExtensionExplicit(WebGLExtensionID) const;
 | |
|   void WarnIfImplicit(WebGLExtensionID) const;
 | |
| 
 | |
|   bool IsExtensionSupported(WebGLExtensionID) const;
 | |
| 
 | |
|   // -------------------------------------------------------------------------
 | |
|   // WebGL 2 specifics (implemented in WebGL2Context.cpp)
 | |
|  public:
 | |
|   virtual bool IsWebGL2() const { return false; }
 | |
| 
 | |
|   struct FailureReason {
 | |
|     nsCString key;  // For reporting.
 | |
|     nsCString info;
 | |
| 
 | |
|     FailureReason() = default;
 | |
| 
 | |
|     template <typename A, typename B>
 | |
|     FailureReason(const A& _key, const B& _info)
 | |
|         : key(nsCString(_key)), info(nsCString(_info)) {}
 | |
|   };
 | |
| 
 | |
|  protected:
 | |
|   bool InitWebGL2(FailureReason* const out_failReason);
 | |
| 
 | |
|   bool CreateAndInitGL(bool forceEnabled,
 | |
|                        std::vector<FailureReason>* const out_failReasons);
 | |
| 
 | |
|   // -------------------------------------------------------------------------
 | |
|   // Validation functions (implemented in WebGLContextValidate.cpp)
 | |
|   bool InitAndValidateGL(FailureReason* const out_failReason);
 | |
| 
 | |
|   bool ValidateBlendEquationEnum(GLenum cap, const char* info);
 | |
|   bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
 | |
|                                            const char* info);
 | |
|   bool ValidateStencilOpEnum(GLenum action, const char* info);
 | |
|   bool ValidateFaceEnum(GLenum face);
 | |
|   bool ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
 | |
|                             WebGLTexImageFunc func, WebGLTexDimensions dims);
 | |
|   bool ValidateAttribPointer(bool integerMode, GLuint index, GLint size,
 | |
|                              GLenum type, WebGLboolean normalized,
 | |
|                              GLsizei stride, WebGLintptr byteOffset,
 | |
|                              const char* info);
 | |
|   bool ValidateStencilParamsForDrawCall() const;
 | |
| 
 | |
|   bool ValidateCopyTexImage(TexInternalFormat srcFormat,
 | |
|                             TexInternalFormat dstformat, WebGLTexImageFunc func,
 | |
|                             WebGLTexDimensions dims);
 | |
| 
 | |
|   bool ValidateTexImage(TexImageTarget texImageTarget, GLint level,
 | |
|                         GLenum internalFormat, GLint xoffset, GLint yoffset,
 | |
|                         GLint zoffset, GLint width, GLint height, GLint depth,
 | |
|                         GLint border, GLenum format, GLenum type,
 | |
|                         WebGLTexImageFunc func, WebGLTexDimensions dims);
 | |
|   bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
 | |
|                               WebGLTexDimensions dims);
 | |
|   bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
 | |
|                             WebGLTexDimensions dims);
 | |
|   bool ValidateTexImageFormatAndType(GLenum format, GLenum type,
 | |
|                                      WebGLTexImageFunc func,
 | |
|                                      WebGLTexDimensions dims);
 | |
|   bool ValidateCompTexImageInternalFormat(GLenum format, WebGLTexImageFunc func,
 | |
|                                           WebGLTexDimensions dims);
 | |
|   bool ValidateCopyTexImageInternalFormat(GLenum format, WebGLTexImageFunc func,
 | |
|                                           WebGLTexDimensions dims);
 | |
|   bool ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
 | |
|                             GLint width, GLint height, GLint depth,
 | |
|                             WebGLTexImageFunc func, WebGLTexDimensions dims);
 | |
|   bool ValidateTexSubImageSize(GLint x, GLint y, GLint z, GLsizei width,
 | |
|                                GLsizei height, GLsizei depth, GLsizei baseWidth,
 | |
|                                GLsizei baseHeight, GLsizei baseDepth,
 | |
|                                WebGLTexImageFunc func, WebGLTexDimensions dims);
 | |
|   bool ValidateCompTexImageSize(GLint level, GLenum internalFormat,
 | |
|                                 GLint xoffset, GLint yoffset, GLsizei width,
 | |
|                                 GLsizei height, GLsizei levelWidth,
 | |
|                                 GLsizei levelHeight, WebGLTexImageFunc func,
 | |
|                                 WebGLTexDimensions dims);
 | |
|   bool ValidateCompTexImageDataSize(GLint level, GLenum internalFormat,
 | |
|                                     GLsizei width, GLsizei height,
 | |
|                                     uint32_t byteLength, WebGLTexImageFunc func,
 | |
|                                     WebGLTexDimensions dims);
 | |
| 
 | |
|   bool HasDrawBuffers() const {
 | |
|     return IsWebGL2() ||
 | |
|            IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
 | |
|   }
 | |
| 
 | |
|   RefPtr<WebGLBuffer>* ValidateBufferSlot(GLenum target);
 | |
| 
 | |
|  public:
 | |
|   WebGLBuffer* ValidateBufferSelection(GLenum target) const;
 | |
| 
 | |
|  protected:
 | |
|   IndexedBufferBinding* ValidateIndexedBufferSlot(GLenum target, GLuint index);
 | |
| 
 | |
|   bool ValidateIndexedBufferBinding(
 | |
|       GLenum target, GLuint index,
 | |
|       RefPtr<WebGLBuffer>** const out_genericBinding,
 | |
|       IndexedBufferBinding** const out_indexedBinding);
 | |
| 
 | |
|  public:
 | |
|   bool ValidateNonNegative(const char* argName, int64_t val) const {
 | |
|     if (MOZ_UNLIKELY(val < 0)) {
 | |
|       ErrorInvalidValue("`%s` must be non-negative.", argName);
 | |
|       return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   template <typename T>
 | |
|   bool ValidateNonNull(const char* const argName,
 | |
|                        const dom::Nullable<T>& maybe) const {
 | |
|     if (maybe.IsNull()) {
 | |
|       ErrorInvalidValue("%s: Cannot be null.", argName);
 | |
|       return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   ////
 | |
| 
 | |
|  protected:
 | |
|   void DestroyResourcesAndContext();
 | |
| 
 | |
|   // helpers
 | |
| 
 | |
|   bool ConvertImage(size_t width, size_t height, size_t srcStride,
 | |
|                     size_t dstStride, const uint8_t* src, uint8_t* dst,
 | |
|                     WebGLTexelFormat srcFormat, bool srcPremultiplied,
 | |
|                     WebGLTexelFormat dstFormat, bool dstPremultiplied,
 | |
|                     size_t dstTexelSize);
 | |
| 
 | |
|   //////
 | |
|  public:
 | |
|   template <typename T>
 | |
|   bool ValidateObject(const char* const argName, const T& object) const {
 | |
|     // Todo: Remove all callers.
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   template <typename T>
 | |
|   bool ValidateObject(const char* const argName, const T* const object) const {
 | |
|     // Todo: Remove most (all?) callers.
 | |
|     if (!object) {
 | |
|       ErrorInvalidOperation(
 | |
|           "%s: Object argument cannot have been marked for"
 | |
|           " deletion.",
 | |
|           argName);
 | |
|       return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   ////
 | |
| 
 | |
|  private:
 | |
|   void LoseContextLruLocked(webgl::ContextLossReason reason)
 | |
|       MOZ_REQUIRES(sLruMutex);
 | |
| 
 | |
|  public:
 | |
|   void LoseContext(
 | |
|       webgl::ContextLossReason reason = webgl::ContextLossReason::None);
 | |
| 
 | |
|  protected:
 | |
|   nsTArray<RefPtr<WebGLTexture>> mBound2DTextures;
 | |
|   nsTArray<RefPtr<WebGLTexture>> mBoundCubeMapTextures;
 | |
|   nsTArray<RefPtr<WebGLTexture>> mBound3DTextures;
 | |
|   nsTArray<RefPtr<WebGLTexture>> mBound2DArrayTextures;
 | |
|   nsTArray<RefPtr<WebGLSampler>> mBoundSamplers;
 | |
| 
 | |
|   void ResolveTexturesForDraw() const;
 | |
| 
 | |
|   RefPtr<WebGLProgram> mCurrentProgram;
 | |
|   RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
 | |
| 
 | |
|   bool ValidateFramebufferTarget(GLenum target) const;
 | |
|   bool ValidateInvalidateFramebuffer(GLenum target,
 | |
|                                      const Span<const GLenum>& attachments,
 | |
|                                      std::vector<GLenum>* const scopedVector,
 | |
|                                      GLsizei* const out_glNumAttachments,
 | |
|                                      const GLenum** const out_glAttachments);
 | |
| 
 | |
|   RefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
 | |
|   RefPtr<WebGLFramebuffer> mBoundReadFramebuffer;
 | |
|   RefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
 | |
|   RefPtr<WebGLVertexArray> mBoundVertexArray;
 | |
| 
 | |
|  public:
 | |
|   const auto& BoundReadFb() const { return mBoundReadFramebuffer; }
 | |
| 
 | |
|  protected:
 | |
|   RefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
 | |
|   RefPtr<WebGLVertexArray> mDefaultVertexArray;
 | |
| 
 | |
|   ////////////////////////////////////
 | |
| 
 | |
|  protected:
 | |
|   GLuint mEmptyTFO = 0;
 | |
| 
 | |
|   // Generic Vertex Attributes
 | |
|   // Though CURRENT_VERTEX_ATTRIB is listed under "Vertex Shader State" in the
 | |
|   // spec state tables, this isn't vertex shader /object/ state. This array is
 | |
|   // merely state useful to vertex shaders, but is global state.
 | |
|   std::vector<webgl::AttribBaseType> mGenericVertexAttribTypes;
 | |
|   CacheInvalidator mGenericVertexAttribTypeInvalidator;
 | |
| 
 | |
|   GLuint mFakeVertexAttrib0BufferObject = 0;
 | |
|   intptr_t mFakeVertexAttrib0BufferObjectSize = 0;
 | |
|   bool mFakeVertexAttrib0DataDefined = false;
 | |
|   alignas(alignof(float)) uint8_t
 | |
|       mGenericVertexAttrib0Data[sizeof(float) * 4] = {};
 | |
|   alignas(alignof(float)) uint8_t
 | |
|       mFakeVertexAttrib0Data[sizeof(float) * 4] = {};
 | |
| 
 | |
|   GLint mStencilRefFront = 0;
 | |
|   GLint mStencilRefBack = 0;
 | |
|   GLuint mStencilValueMaskFront = 0;
 | |
|   GLuint mStencilValueMaskBack = 0;
 | |
|   GLuint mStencilWriteMaskFront = 0;
 | |
|   GLuint mStencilWriteMaskBack = 0;
 | |
|   uint8_t mColorWriteMask0 = 0xf;  // bitmask
 | |
|   mutable uint8_t mDriverColorMask0 = 0xf;
 | |
|   bool mDepthWriteMask = true;
 | |
|   GLfloat mColorClearValue[4] = {0, 0, 0, 0};
 | |
|   GLint mStencilClearValue = 0;
 | |
|   GLfloat mDepthClearValue = 1.0f;
 | |
| 
 | |
|   std::bitset<webgl::kMaxDrawBuffers> mColorWriteMaskNonzero = -1;
 | |
|   std::bitset<webgl::kMaxDrawBuffers> mBlendEnabled = 0;
 | |
| 
 | |
|   GLint mViewportX = 0;
 | |
|   GLint mViewportY = 0;
 | |
|   GLsizei mViewportWidth = 0;
 | |
|   GLsizei mViewportHeight = 0;
 | |
|   bool mAlreadyWarnedAboutViewportLargerThanDest = false;
 | |
| 
 | |
|   GLfloat mLineWidth = 1.0;
 | |
| 
 | |
|   WebGLContextLossHandler mContextLossHandler;
 | |
| 
 | |
|   // Used for some hardware (particularly Tegra 2 and 4) that likes to
 | |
|   // be Flushed while doing hundreds of draw calls.
 | |
|   mutable uint64_t mDrawCallsSinceLastFlush = 0;
 | |
| 
 | |
|   mutable uint64_t mWarningCount = 0;
 | |
|   const uint64_t mMaxWarnings = StaticPrefs::webgl_max_warnings_per_context();
 | |
|   bool mAlreadyWarnedAboutFakeVertexAttrib0 = false;
 | |
| 
 | |
|   bool ShouldGenerateWarnings() const { return mWarningCount < mMaxWarnings; }
 | |
| 
 | |
|   bool ShouldGeneratePerfWarnings() const {
 | |
|     return mNumPerfWarnings < mMaxPerfWarnings;
 | |
|   }
 | |
| 
 | |
|   bool mNeedsFakeNoAlpha = false;
 | |
|   bool mNeedsFakeNoDepth = false;
 | |
|   bool mNeedsFakeNoStencil = false;
 | |
| 
 | |
|   bool mDriverDepthTest = false;
 | |
|   bool mDriverStencilTest = false;
 | |
| 
 | |
|   bool mNeedsLegacyVertexAttrib0Handling = false;
 | |
|   bool mMaybeNeedsLegacyVertexAttrib0Handling = false;
 | |
|   bool mNeedsIndexValidation = false;
 | |
|   bool mBug_DrawArraysInstancedUserAttribFetchAffectedByFirst = false;
 | |
| 
 | |
|   const bool mAllowFBInvalidation = StaticPrefs::webgl_allow_fb_invalidation();
 | |
| 
 | |
|   bool Has64BitTimestamps() const;
 | |
| 
 | |
|   // --
 | |
| 
 | |
|   const uint8_t mMsaaSamples =
 | |
|       static_cast<uint8_t>(StaticPrefs::webgl_msaa_samples());
 | |
|   mutable uvec2 mRequestedSize;
 | |
|   mutable UniquePtr<gl::MozFramebuffer> mDefaultFB;
 | |
|   mutable bool mDefaultFB_IsInvalid = false;
 | |
|   mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
 | |
| 
 | |
|   gl::SwapChain mSwapChain;
 | |
|   gl::SwapChain mWebVRSwapChain;
 | |
| 
 | |
|   RefPtr<layers::RemoteTextureOwnerClient> mRemoteTextureOwner;
 | |
| 
 | |
|   bool PushRemoteTexture(
 | |
|       WebGLFramebuffer*, gl::SwapChain&, std::shared_ptr<gl::SharedSurface>,
 | |
|       const webgl::SwapChainOptions& options,
 | |
|       layers::RemoteTextureOwnerClient* ownerClient = nullptr);
 | |
| 
 | |
|   void EnsureContextLostRemoteTextureOwner(
 | |
|       const webgl::SwapChainOptions& options);
 | |
| 
 | |
|  public:
 | |
|   void WaitForTxn(layers::RemoteTextureOwnerId ownerId,
 | |
|                   layers::RemoteTextureTxnType txnType,
 | |
|                   layers::RemoteTextureTxnId txnId);
 | |
| 
 | |
|   // --
 | |
| 
 | |
|  protected:
 | |
|   bool EnsureDefaultFB();
 | |
|   bool ValidateAndInitFB(
 | |
|       const WebGLFramebuffer* fb,
 | |
|       GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
 | |
|   void DoBindFB(const WebGLFramebuffer* fb,
 | |
|                 GLenum target = LOCAL_GL_FRAMEBUFFER) const;
 | |
| 
 | |
|   bool BindCurFBForDraw();
 | |
|   bool BindCurFBForColorRead(
 | |
|       const webgl::FormatUsageInfo** out_format, uint32_t* out_width,
 | |
|       uint32_t* out_height,
 | |
|       GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
 | |
|   void DoColorMask(Maybe<GLuint> i, uint8_t bitmask) const;
 | |
|   void BlitBackbufferToCurDriverFB(
 | |
|       WebGLFramebuffer* const srcAsWebglFb = nullptr,
 | |
|       const gl::MozFramebuffer* const srcAsMozFb = nullptr,
 | |
|       bool srcIsBGRA = false) const;
 | |
|   bool BindDefaultFBForRead();
 | |
| 
 | |
|   // --
 | |
| 
 | |
|  public:
 | |
|   // console logging helpers
 | |
|   template <typename... Args>
 | |
|   void GenerateWarning(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(0, fmt, args...);
 | |
|   }
 | |
| 
 | |
|   template <typename... Args>
 | |
|   void GeneratePerfWarning(const char* const fmt, const Args&... args) const {
 | |
|     GenerateError(webgl::kErrorPerfWarning, fmt, args...);
 | |
|   }
 | |
| 
 | |
|  public:
 | |
|   UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
 | |
| 
 | |
|   virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage(
 | |
|       gl::GLContext* gl) const;
 | |
| 
 | |
|   const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
 | |
| 
 | |
|   // Friend list
 | |
|   friend class ScopedCopyTexImageSource;
 | |
|   friend class ScopedResolveTexturesForDraw;
 | |
|   friend class webgl::TexUnpackBlob;
 | |
|   friend class webgl::TexUnpackBytes;
 | |
|   friend class webgl::TexUnpackImage;
 | |
|   friend class webgl::TexUnpackSurface;
 | |
|   friend struct webgl::UniformInfo;
 | |
|   friend class WebGLTexture;
 | |
|   friend class WebGLFBAttachPoint;
 | |
|   friend class WebGLFramebuffer;
 | |
|   friend class WebGLRenderbuffer;
 | |
|   friend class WebGLProgram;
 | |
|   friend class WebGLQuery;
 | |
|   friend class WebGLBuffer;
 | |
|   friend class WebGLSampler;
 | |
|   friend class WebGLShader;
 | |
|   friend class WebGLSync;
 | |
|   friend class WebGLTransformFeedback;
 | |
|   friend class WebGLVertexArray;
 | |
|   friend class WebGLVertexArrayFake;
 | |
|   friend class WebGLVertexArrayGL;
 | |
| };
 | |
| 
 | |
| // Returns `value` rounded to the next highest multiple of `multiple`.
 | |
| // AKA PadToAlignment, StrideForAlignment.
 | |
| template <typename V, typename M>
 | |
| V RoundUpToMultipleOf(const V& value, const M& multiple) {
 | |
|   return ((value + multiple - 1) / multiple) * multiple;
 | |
| }
 | |
| 
 | |
| class ScopedFBRebinder final {
 | |
|  private:
 | |
|   const WebGLContext* const mWebGL;
 | |
| 
 | |
|  public:
 | |
|   explicit ScopedFBRebinder(const WebGLContext* const webgl) : mWebGL(webgl) {}
 | |
|   ~ScopedFBRebinder();
 | |
| };
 | |
| 
 | |
| // -
 | |
| 
 | |
| constexpr inline bool IsBufferTargetLazilyBound(const GLenum target) {
 | |
|   return target != LOCAL_GL_ELEMENT_ARRAY_BUFFER;
 | |
| }
 | |
| 
 | |
| void DoBindBuffer(gl::GLContext&, GLenum target, const WebGLBuffer*);
 | |
| 
 | |
| class ScopedLazyBind final {
 | |
|  private:
 | |
|   gl::GLContext& mGL;
 | |
|   const GLenum mTarget;
 | |
| 
 | |
|  public:
 | |
|   ScopedLazyBind(gl::GLContext* const gl, const GLenum target,
 | |
|                  const WebGLBuffer* const buf)
 | |
|       : mGL(*gl), mTarget(IsBufferTargetLazilyBound(target) ? target : 0) {
 | |
|     if (mTarget) {
 | |
|       DoBindBuffer(mGL, mTarget, buf);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ~ScopedLazyBind() {
 | |
|     if (mTarget) {
 | |
|       DoBindBuffer(mGL, mTarget, nullptr);
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| ////
 | |
| 
 | |
| bool Intersect(int32_t srcSize, int32_t read0, int32_t readSize,
 | |
|                int32_t* out_intRead0, int32_t* out_intWrite0,
 | |
|                int32_t* out_intSize);
 | |
| 
 | |
| uint64_t AvailGroups(uint64_t totalAvailItems, uint64_t firstItemOffset,
 | |
|                      uint32_t groupSize, uint32_t groupStride);
 | |
| 
 | |
| ////
 | |
| 
 | |
| class ScopedDrawCallWrapper final {
 | |
|  public:
 | |
|   WebGLContext& mWebGL;
 | |
| 
 | |
|   explicit ScopedDrawCallWrapper(WebGLContext& webgl);
 | |
|   ~ScopedDrawCallWrapper();
 | |
| };
 | |
| 
 | |
| namespace webgl {
 | |
| 
 | |
| class ScopedPrepForResourceClear final {
 | |
|   const WebGLContext& webgl;
 | |
| 
 | |
|  public:
 | |
|   explicit ScopedPrepForResourceClear(const WebGLContext&);
 | |
|   ~ScopedPrepForResourceClear();
 | |
| };
 | |
| 
 | |
| struct IndexedName final {
 | |
|   std::string name;
 | |
|   uint64_t index;
 | |
| };
 | |
| Maybe<IndexedName> ParseIndexed(const std::string& str);
 | |
| 
 | |
| }  // namespace webgl
 | |
| 
 | |
| webgl::LinkActiveInfo GetLinkActiveInfo(
 | |
|     gl::GLContext& gl, const GLuint prog, const bool webgl2,
 | |
|     const std::unordered_map<std::string, std::string>& nameUnmap);
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif
 | 
