1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef WEBGLCONTEXT_H_
7 #define WEBGLCONTEXT_H_
8 
9 #include <memory>
10 #include <stdarg.h>
11 
12 #include "GLContextTypes.h"
13 #include "GLDefs.h"
14 #include "GLScreenBuffer.h"
15 #include "js/ScalarType.h"  // js::Scalar::Type
16 #include "mozilla/Attributes.h"
17 #include "mozilla/CheckedInt.h"
18 #include "mozilla/dom/BindingDeclarations.h"
19 #include "mozilla/dom/HTMLCanvasElement.h"
20 #include "mozilla/dom/Nullable.h"
21 #include "mozilla/dom/TypedArray.h"
22 #include "mozilla/EnumeratedArray.h"
23 #include "mozilla/gfx/2D.h"
24 #include "mozilla/Mutex.h"
25 #include "mozilla/UniquePtr.h"
26 #include "mozilla/WeakPtr.h"
27 #include "nsICanvasRenderingContextInternal.h"
28 #include "nsTArray.h"
29 #include "SurfaceTypes.h"
30 #include "ScopedGLHelpers.h"
31 #include "TexUnpackBlob.h"
32 #include "mozilla/WeakPtr.h"
33 
34 // Local
35 #include "CacheInvalidator.h"
36 #include "WebGLContextLossHandler.h"
37 #include "WebGLExtensions.h"
38 #include "WebGLObjectModel.h"
39 #include "WebGLStrongTypes.h"
40 #include "WebGLTypes.h"
41 
42 // Generated
43 #include "nsICanvasRenderingContextInternal.h"
44 #include "mozilla/dom/HTMLCanvasElement.h"
45 #include "mozilla/dom/WebGLRenderingContextBinding.h"
46 #include "mozilla/dom/WebGL2RenderingContextBinding.h"
47 
48 #include <list>
49 
50 class nsIDocShell;
51 
52 // WebGL-only GLenums
53 // clang-format off
54 #define LOCAL_GL_BROWSER_DEFAULT_WEBGL              0x9244
55 #define LOCAL_GL_CONTEXT_LOST_WEBGL                 0x9242
56 #define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL      0x9247
57 #define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
58 #define LOCAL_GL_UNPACK_FLIP_Y_WEBGL                0x9240
59 #define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL     0x9241
60 // clang-format on
61 
62 namespace mozilla {
63 class HostWebGLContext;
64 class ScopedCopyTexImageSource;
65 class ScopedDrawCallWrapper;
66 class ScopedResolveTexturesForDraw;
67 class WebGLBuffer;
68 class WebGLExtensionBase;
69 class WebGLFramebuffer;
70 class WebGLProgram;
71 class WebGLQuery;
72 class WebGLRenderbuffer;
73 class WebGLSampler;
74 class WebGLShader;
75 class WebGLSync;
76 class WebGLTexture;
77 class WebGLTransformFeedback;
78 class WebGLVertexArray;
79 
80 namespace dom {
81 class Document;
82 class Element;
83 class ImageData;
84 class OwningHTMLCanvasElementOrOffscreenCanvas;
85 struct WebGLContextAttributes;
86 }  // namespace dom
87 
88 namespace gfx {
89 class SourceSurface;
90 class VRLayerChild;
91 }  // namespace gfx
92 
93 namespace gl {
94 class GLScreenBuffer;
95 class MozFramebuffer;
96 class Texture;
97 }  // namespace gl
98 
99 namespace layers {
100 class CompositableHost;
101 class SurfaceDescriptor;
102 }  // namespace layers
103 
104 namespace webgl {
105 class AvailabilityRunnable;
106 struct CachedDrawFetchLimits;
107 struct FbAttachInfo;
108 struct FormatInfo;
109 class FormatUsageAuthority;
110 struct FormatUsageInfo;
111 struct ImageInfo;
112 struct LinkedProgramInfo;
113 struct SamplerUniformInfo;
114 struct SamplingState;
115 class ScopedPrepForResourceClear;
116 class ShaderValidator;
117 class TexUnpackBlob;
118 struct UniformInfo;
119 struct UniformBlockInfo;
120 struct VertAttribPointerDesc;
121 }  // namespace webgl
122 
123 struct WebGLTexImageData {
124   TexImageTarget mTarget;
125   int32_t mRowLength;
126   uint32_t mWidth;
127   uint32_t mHeight;
128   uint32_t mDepth;
129   gfxAlphaType mSrcAlphaType;
130 };
131 
132 struct WebGLTexPboOffset {
133   TexImageTarget mTarget;
134   uint32_t mWidth;
135   uint32_t mHeight;
136   uint32_t mDepth;
137   WebGLsizeiptr mPboOffset;
138   bool mHasExpectedImageSize;
139   GLsizei mExpectedImageSize;
140 };
141 
142 WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
143 
144 void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
145 
146 // From WebGLContextUtils
147 TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
148 
149 struct WebGLIntOrFloat {
150   const enum { Int, Float, Uint } mType;
151 
152   union {
153     GLint i;
154     GLfloat f;
155     GLuint u;
156   } mValue;
157 
WebGLIntOrFloatWebGLIntOrFloat158   explicit WebGLIntOrFloat(GLint i) : mType(Int) { mValue.i = i; }
WebGLIntOrFloatWebGLIntOrFloat159   explicit WebGLIntOrFloat(GLfloat f) : mType(Float) { mValue.f = f; }
160 
AsIntWebGLIntOrFloat161   GLint AsInt() const {
162     return (mType == Int) ? mValue.i : NS_lroundf(mValue.f);
163   }
AsFloatWebGLIntOrFloat164   GLfloat AsFloat() const {
165     return (mType == Float) ? mValue.f : GLfloat(mValue.i);
166   }
167 };
168 
169 struct IndexedBufferBinding {
170   RefPtr<WebGLBuffer> mBufferBinding;
171   uint64_t mRangeStart;
172   uint64_t mRangeSize;
173 
174   IndexedBufferBinding();
175 
176   uint64_t ByteCount() const;
177 };
178 
179 ////////////////////////////////////
180 
181 namespace webgl {
182 
183 class AvailabilityRunnable final : public Runnable {
184  public:
185   const WeakPtr<const ClientWebGLContext> mWebGL;
186   std::vector<WeakPtr<WebGLQueryJS>> mQueries;
187   std::vector<WeakPtr<WebGLSyncJS>> mSyncs;
188 
189   explicit AvailabilityRunnable(const ClientWebGLContext* webgl);
190   ~AvailabilityRunnable();
191 
192   NS_IMETHOD Run() override;
193 };
194 
195 struct BufferAndIndex final {
196   const WebGLBuffer* buffer = nullptr;
197   uint32_t id = -1;
198 };
199 
200 }  // namespace webgl
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 
204 class WebGLContext : public VRefCounted, public SupportsWeakPtr {
205   friend class ScopedDrawCallWrapper;
206   friend class ScopedDrawWithTransformFeedback;
207   friend class ScopedFakeVertexAttrib0;
208   friend class ScopedFBRebinder;
209   friend class WebGL2Context;
210   friend class WebGLContextUserData;
211   friend class WebGLExtensionCompressedTextureASTC;
212   friend class WebGLExtensionCompressedTextureBPTC;
213   friend class WebGLExtensionCompressedTextureES3;
214   friend class WebGLExtensionCompressedTextureETC1;
215   friend class WebGLExtensionCompressedTexturePVRTC;
216   friend class WebGLExtensionCompressedTextureRGTC;
217   friend class WebGLExtensionCompressedTextureS3TC;
218   friend class WebGLExtensionCompressedTextureS3TC_SRGB;
219   friend class WebGLExtensionDepthTexture;
220   friend class WebGLExtensionDisjointTimerQuery;
221   friend class WebGLExtensionDrawBuffers;
222   friend class WebGLExtensionLoseContext;
223   friend class WebGLExtensionMOZDebug;
224   friend class WebGLExtensionVertexArray;
225   friend class WebGLMemoryTracker;
226   friend class webgl::AvailabilityRunnable;
227   friend struct webgl::LinkedProgramInfo;
228   friend struct webgl::SamplerUniformInfo;
229   friend class webgl::ScopedPrepForResourceClear;
230   friend struct webgl::UniformBlockInfo;
231 
232   friend const webgl::CachedDrawFetchLimits* ValidateDraw(WebGLContext*, GLenum,
233                                                           uint32_t);
234   friend RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
235       WebGLProgram* prog, gl::GLContext* gl);
236 
237   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(WebGLContext, override)
238 
239   enum {
240     UNPACK_FLIP_Y_WEBGL = 0x9240,
241     UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
242     // We throw InvalidOperation in TexImage if we fail to use GPU fast-path
243     // for texture copy when it is set to true, only for debug purpose.
244     UNPACK_REQUIRE_FASTPATH = 0x10001,
245     CONTEXT_LOST_WEBGL = 0x9242,
246     UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
247     BROWSER_DEFAULT_WEBGL = 0x9244,
248     UNMASKED_VENDOR_WEBGL = 0x9245,
249     UNMASKED_RENDERER_WEBGL = 0x9246
250   };
251 
252  private:
253   class LruPosition final {
254     std::list<WebGLContext*>::iterator mItr;
255 
256     void reset();
257 
258    public:
259     LruPosition();
260     explicit LruPosition(WebGLContext&);
261 
262     LruPosition& operator=(LruPosition&& rhs) {
263       reset();
264       std::swap(mItr, rhs.mItr);
265       rhs.reset();
266       return *this;
267     }
268 
~LruPosition()269     ~LruPosition() { reset(); }
270   };
271 
272   mutable LruPosition mLruPosition;
273 
274  public:
BumpLru()275   void BumpLru() {
276     LruPosition next{*this};
277     mLruPosition = std::move(next);
278   }
279 
280   void LoseLruContextIfLimitExceeded();
281 
282   // -
283 
284   // We've had issues in the past with nulling `gl` without actually releasing
285   // all of our resources. This construction ensures that we are aware that we
286   // should only null `gl` in DestroyResourcesAndContext.
287   RefPtr<gl::GLContext> mGL_OnlyClearInDestroyResourcesAndContext;
288 
289  public:
290   // Grab a const reference so we can see changes, but can't make changes.
291   const decltype(mGL_OnlyClearInDestroyResourcesAndContext)& gl;
292 
293  public:
294   void CheckForInactivity();
295 
296  protected:
297   const WeakPtr<HostWebGLContext> mHost;
298   const bool mResistFingerprinting;
299   WebGLContextOptions mOptions;
300   const uint32_t mPrincipalKey;
301   Maybe<webgl::Limits> mLimits;
302 
303   bool mIsContextLost = false;
304   const uint32_t mMaxPerfWarnings;
305   mutable uint64_t mNumPerfWarnings = 0;
306   const uint32_t mMaxAcceptableFBStatusInvals;
307 
308   uint64_t mNextFenceId = 1;
309   uint64_t mCompletedFenceId = 0;
310 
311   std::unique_ptr<gl::Texture> mIncompleteTexOverride;
312 
313  public:
314   class FuncScope;
315 
316  private:
317   mutable FuncScope* mFuncScope = nullptr;
318 
319  public:
320   static RefPtr<WebGLContext> Create(HostWebGLContext&,
321                                      const webgl::InitContextDesc&,
322                                      webgl::InitContextResult* out);
323 
324  private:
325   void FinishInit();
326 
327  protected:
328   WebGLContext(HostWebGLContext&, const webgl::InitContextDesc&);
329   virtual ~WebGLContext();
330 
331   RefPtr<layers::CompositableHost> mCompositableHost;
332 
333   layers::LayersBackend mBackend = layers::LayersBackend::LAYERS_NONE;
334 
335  public:
336   void Resize(uvec2 size);
337 
338   void SetCompositableHost(RefPtr<layers::CompositableHost>& aCompositableHost);
339 
340   /**
341    * An abstract base class to be implemented by callers wanting to be notified
342    * that a refresh has occurred. Callers must ensure an observer is removed
343    * before it is destroyed.
344    */
345   virtual void DidRefresh();
346 
347   void OnMemoryPressure();
348 
349   // -
350 
351   /*
352 
353   Here are the bind calls that are supposed to be fully-validated client side,
354   so that client's binding state doesn't diverge:
355   * AttachShader
356   * DetachShader
357   * BindFramebuffer
358   * FramebufferAttach
359   * BindBuffer
360   * BindBufferRange
361   * BindTexture
362   * UseProgram
363   * BindSampler
364   * BindTransformFeedback
365   * BindVertexArray
366   * BeginQuery
367   * EndQuery
368   * ActiveTexture
369 
370   */
371 
CurFuncScope()372   const auto& CurFuncScope() const { return *mFuncScope; }
373   const char* FuncName() const;
374 
375   class FuncScope final {
376    public:
377     const WebGLContext& mWebGL;
378     const char* const mFuncName;
379     bool mBindFailureGuard = false;
380 
381    public:
382     FuncScope(const WebGLContext& webgl, const char* funcName);
383     ~FuncScope();
384   };
385 
GenerateErrorImpl(const GLenum err,const nsACString & text)386   void GenerateErrorImpl(const GLenum err, const nsACString& text) const {
387     GenerateErrorImpl(err, std::string(text.BeginReading()));
388   }
389   void GenerateErrorImpl(const GLenum err, const std::string& text) const;
390 
GenerateError(const webgl::ErrorInfo & err)391   void GenerateError(const webgl::ErrorInfo& err) {
392     GenerateError(err.type, "%s", err.info.c_str());
393   }
394 
395   template <typename... Args>
GenerateError(const GLenum err,const char * const fmt,const Args &...args)396   void GenerateError(const GLenum err, const char* const fmt,
397                      const Args&... args) const {
398     MOZ_ASSERT(FuncName());
399 
400     nsCString text;
401     text.AppendPrintf("WebGL warning: %s: ", FuncName());
402 
403 #ifdef __clang__
404 #  pragma clang diagnostic push
405 #  pragma clang diagnostic ignored "-Wformat-security"
406 #elif defined(__GNUC__)
407 #  pragma GCC diagnostic push
408 #  pragma GCC diagnostic ignored "-Wformat-security"
409 #endif
410     text.AppendPrintf(fmt, args...);
411 #ifdef __clang__
412 #  pragma clang diagnostic pop
413 #elif defined(__GNUC__)
414 #  pragma GCC diagnostic pop
415 #endif
416 
417     GenerateErrorImpl(err, text);
418   }
419 
420   template <typename... Args>
ErrorInvalidEnum(const char * const fmt,const Args &...args)421   void ErrorInvalidEnum(const char* const fmt, const Args&... args) const {
422     GenerateError(LOCAL_GL_INVALID_ENUM, fmt, args...);
423   }
424   template <typename... Args>
ErrorInvalidOperation(const char * const fmt,const Args &...args)425   void ErrorInvalidOperation(const char* const fmt, const Args&... args) const {
426     GenerateError(LOCAL_GL_INVALID_OPERATION, fmt, args...);
427   }
428   template <typename... Args>
ErrorInvalidValue(const char * const fmt,const Args &...args)429   void ErrorInvalidValue(const char* const fmt, const Args&... args) const {
430     GenerateError(LOCAL_GL_INVALID_VALUE, fmt, args...);
431   }
432   template <typename... Args>
ErrorInvalidFramebufferOperation(const char * const fmt,const Args &...args)433   void ErrorInvalidFramebufferOperation(const char* const fmt,
434                                         const Args&... args) const {
435     GenerateError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION, fmt, args...);
436   }
437   template <typename... Args>
ErrorOutOfMemory(const char * const fmt,const Args &...args)438   void ErrorOutOfMemory(const char* const fmt, const Args&... args) const {
439     GenerateError(LOCAL_GL_OUT_OF_MEMORY, fmt, args...);
440   }
441 
442   template <typename... Args>
ErrorImplementationBug(const char * const fmt,const Args &...args)443   void ErrorImplementationBug(const char* const fmt,
444                               const Args&... args) const {
445     const nsPrintfCString newFmt(
446         "Implementation bug, please file at %s! %s",
447         "https://bugzilla.mozilla.org/"
448         "enter_bug.cgi?product=Core&component=Canvas%3A+WebGL",
449         fmt);
450     GenerateError(LOCAL_GL_OUT_OF_MEMORY, newFmt.BeginReading(), args...);
451     MOZ_ASSERT(false, "WebGLContext::ErrorImplementationBug");
452     NS_ERROR("WebGLContext::ErrorImplementationBug");
453   }
454 
455   void ErrorInvalidEnumInfo(const char* info, GLenum enumValue) const;
456   void ErrorInvalidEnumArg(const char* argName, GLenum val) const;
457 
458   static const char* ErrorName(GLenum error);
459 
460   /**
461    * Return displayable name for GLenum.
462    * This version is like gl::GLenumToStr but with out the GL_ prefix to
463    * keep consistency with how errors are reported from WebGL.
464    * Returns hex formatted version of glenum if glenum is unknown.
465    */
466   static void EnumName(GLenum val, nsCString* out_name);
467 
468   void DummyReadFramebufferOperation();
469 
470   WebGLTexture* GetActiveTex(const GLenum texTarget) const;
471 
472   already_AddRefed<layers::Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
473                                                  layers::Layer* oldLayer,
474                                                  layers::LayerManager* manager);
475 
476   Maybe<ICRData> InitializeCanvasRenderer(layers::LayersBackend backend);
477 
GL()478   gl::GLContext* GL() const { return gl; }
479 
IsPremultAlpha()480   bool IsPremultAlpha() const { return mOptions.premultipliedAlpha; }
481 
IsPreservingDrawingBuffer()482   bool IsPreservingDrawingBuffer() const {
483     return mOptions.preserveDrawingBuffer;
484   }
485 
486   // Present to compositor
487  private:
488   bool PresentInto(gl::SwapChain& swapChain);
489   bool PresentIntoXR(gl::SwapChain& swapChain, const gl::MozFramebuffer& xrFb);
490 
491  public:
492   void Present(WebGLFramebuffer*, layers::TextureType, const bool webvr);
493   RefPtr<gfx::DataSourceSurface> GetFrontBufferSnapshot();
494   Maybe<uvec2> FrontBufferSnapshotInto(Maybe<Range<uint8_t>>);
495   Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebuffer*,
496                                                   const bool webvr);
497 
498   void ClearVRSwapChain();
499 
500   void RunContextLossTimer();
501   void CheckForContextLoss();
502 
503   bool TryToRestoreContext();
504 
505   void AssertCachedBindings() const;
506   void AssertCachedGlobalState() const;
507 
508   // WebIDL WebGLRenderingContext API
509   void Commit();
510 
511   uvec2 DrawingBufferSize();
512 
513  public:
514   void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
515 
516   // This is the entrypoint. Don't test against it directly.
IsContextLost()517   bool IsContextLost() const { return mIsContextLost; }
518 
519   // -
520 
521   RefPtr<WebGLBuffer> CreateBuffer();
522   RefPtr<WebGLFramebuffer> CreateFramebuffer();
523   RefPtr<WebGLFramebuffer> CreateOpaqueFramebuffer(
524       const webgl::OpaqueFramebufferOptions& options);
525   RefPtr<WebGLProgram> CreateProgram();
526   RefPtr<WebGLQuery> CreateQuery();
527   RefPtr<WebGLRenderbuffer> CreateRenderbuffer();
528   RefPtr<WebGLShader> CreateShader(GLenum type);
529   RefPtr<WebGLTexture> CreateTexture();
530   RefPtr<WebGLVertexArray> CreateVertexArray();
531 
532   // -
533 
534   void AttachShader(WebGLProgram& prog, WebGLShader& shader);
535   void BindAttribLocation(WebGLProgram& prog, GLuint location,
536                           const std::string& name) const;
537   void BindFramebuffer(GLenum target, WebGLFramebuffer* fb);
538   void BindRenderbuffer(GLenum target, WebGLRenderbuffer* fb);
539   void BindVertexArray(WebGLVertexArray* vao);
540   void BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
541   void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
542   void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha,
543                          GLenum dstAlpha);
544   GLenum CheckFramebufferStatus(GLenum target);
545   void Clear(GLbitfield mask);
546   void ClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a);
547   void ClearDepth(GLclampf v);
548   void ClearStencil(GLint v);
549   void ColorMask(WebGLboolean r, WebGLboolean g, WebGLboolean b,
550                  WebGLboolean a);
551   void CompileShader(WebGLShader& shader);
552 
553  private:
554   void CompileShaderANGLE(WebGLShader* shader);
555   void CompileShaderBypass(WebGLShader* shader, const nsCString& shaderSource);
556 
557  public:
558   void CullFace(GLenum face);
559   void DepthFunc(GLenum func);
560   void DepthMask(WebGLboolean b);
561   void DepthRange(GLclampf zNear, GLclampf zFar);
562   void DetachShader(WebGLProgram& prog, const WebGLShader& shader);
563   void DrawBuffers(const std::vector<GLenum>& buffers);
564   void Flush();
565   void Finish();
566 
567   void FramebufferAttach(GLenum target, GLenum attachSlot,
568                          GLenum bindImageTarget,
569                          const webgl::FbAttachInfo& toAttach);
570 
571   void FrontFace(GLenum mode);
572 
573   Maybe<double> GetBufferParameter(GLenum target, GLenum pname);
574   webgl::CompileResult GetCompileResult(const WebGLShader&) const;
575   GLenum GetError();
576   GLint GetFragDataLocation(const WebGLProgram&, const std::string& name) const;
577 
578   Maybe<double> GetFramebufferAttachmentParameter(WebGLFramebuffer*,
579                                                   GLenum attachment,
580                                                   GLenum pname) const;
581 
582   Maybe<double> GetRenderbufferParameter(const WebGLRenderbuffer&,
583                                          GLenum pname) const;
584   webgl::LinkResult GetLinkResult(const WebGLProgram&) const;
585 
586   Maybe<webgl::ShaderPrecisionFormat> GetShaderPrecisionFormat(
587       GLenum shadertype, GLenum precisiontype) const;
588 
589   webgl::GetUniformData GetUniform(const WebGLProgram&, uint32_t loc) const;
590 
591   void Hint(GLenum target, GLenum mode);
592 
593   void LineWidth(GLfloat width);
594   void LinkProgram(WebGLProgram& prog);
595   void PolygonOffset(GLfloat factor, GLfloat units);
596 
597   ////
598 
599   webgl::PackingInfo ValidImplementationColorReadPI(
600       const webgl::FormatUsageInfo* usage) const;
601 
602  protected:
603   webgl::ReadPixelsResult ReadPixelsImpl(const webgl::ReadPixelsDesc&,
604                                          uintptr_t dest, uint64_t availBytes);
605   bool DoReadPixelsAndConvert(const webgl::FormatInfo* srcFormat,
606                               const webgl::ReadPixelsDesc&, uintptr_t dest,
607                               uint64_t dataLen, uint32_t rowStride);
608 
609  public:
610   void ReadPixelsPbo(const webgl::ReadPixelsDesc&, uint64_t offset);
611   webgl::ReadPixelsResult ReadPixelsInto(const webgl::ReadPixelsDesc&,
612                                          const Range<uint8_t>& dest);
613 
614   ////
615 
616   void RenderbufferStorageMultisample(WebGLRenderbuffer&, uint32_t samples,
617                                       GLenum internalformat, uint32_t width,
618                                       uint32_t height) const;
619 
620  public:
621   void SampleCoverage(GLclampf value, WebGLboolean invert);
622   void Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
623   void ShaderSource(WebGLShader& shader, const std::string& source) const;
624   void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
625   void StencilMaskSeparate(GLenum face, GLuint mask);
626   void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
627                          GLenum dppass);
628 
629   //////////////////////////
630 
631   void UniformData(uint32_t loc, bool transpose,
632                    const Range<const uint8_t>& data) const;
633 
634   ////////////////////////////////////
635 
636   void UseProgram(WebGLProgram* prog);
637 
638   bool ValidateAttribArraySetter(uint32_t count, uint32_t arrayLength);
639   bool ValidateProgram(const WebGLProgram& prog) const;
640   void Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
641 
642   // -----------------------------------------------------------------------------
643   // Buffer Objects (WebGLContextBuffers.cpp)
644   void BindBuffer(GLenum target, WebGLBuffer* buffer);
645   void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buf,
646                        uint64_t offset, uint64_t size);
647 
648   void BufferData(GLenum target, uint64_t dataLen, const uint8_t* data,
649                   GLenum usage) const;
650   void BufferSubData(GLenum target, uint64_t dstByteOffset, uint64_t srcDataLen,
651                      const uint8_t* srcData) const;
652 
653  protected:
654   // bound buffer state
655   RefPtr<WebGLBuffer> mBoundArrayBuffer;
656   RefPtr<WebGLBuffer> mBoundCopyReadBuffer;
657   RefPtr<WebGLBuffer> mBoundCopyWriteBuffer;
658   RefPtr<WebGLBuffer> mBoundPixelPackBuffer;
659   RefPtr<WebGLBuffer> mBoundPixelUnpackBuffer;
660   RefPtr<WebGLBuffer> mBoundTransformFeedbackBuffer;
661   RefPtr<WebGLBuffer> mBoundUniformBuffer;
662 
663   std::vector<IndexedBufferBinding> mIndexedUniformBufferBindings;
664 
665   RefPtr<WebGLBuffer>& GetBufferSlotByTarget(GLenum target);
666   RefPtr<WebGLBuffer>& GetBufferSlotByTargetIndexed(GLenum target,
667                                                     GLuint index);
668 
669   // -
670 
671   void GenErrorIllegalUse(GLenum useTarget, uint32_t useId, GLenum boundTarget,
672                           uint32_t boundId) const;
673 
674   bool ValidateBufferForNonTf(const WebGLBuffer&, GLenum nonTfTarget,
675                               uint32_t nonTfId) const;
676 
677   bool ValidateBufferForNonTf(const WebGLBuffer* const nonTfBuffer,
678                               const GLenum nonTfTarget,
679                               const uint32_t nonTfId = -1) const {
680     if (!nonTfBuffer) return true;
681     return ValidateBufferForNonTf(*nonTfBuffer, nonTfTarget, nonTfId);
682   }
683 
684   bool ValidateBuffersForTf(const WebGLTransformFeedback&,
685                             const webgl::LinkedProgramInfo&) const;
686   bool ValidateBuffersForTf(
687       const std::vector<webgl::BufferAndIndex>& tfBuffers) const;
688 
689   // -----------------------------------------------------------------------------
690   // Queries (WebGL2ContextQueries.cpp)
691  protected:
692   RefPtr<WebGLQuery> mQuerySlot_SamplesPassed;
693   RefPtr<WebGLQuery> mQuerySlot_TFPrimsWritten;
694   RefPtr<WebGLQuery> mQuerySlot_TimeElapsed;
695 
696   RefPtr<WebGLQuery>* ValidateQuerySlotByTarget(GLenum target);
697 
698  public:
699   void BeginQuery(GLenum target, WebGLQuery& query);
700   void EndQuery(GLenum target);
701   Maybe<double> GetQueryParameter(const WebGLQuery& query, GLenum pname) const;
702   void QueryCounter(WebGLQuery&) const;
703 
704   // -----------------------------------------------------------------------------
705   // State and State Requests (WebGLContextState.cpp)
706  private:
707   void SetEnabled(const char* funcName, GLenum cap, bool enabled);
708 
709  public:
Disable(GLenum cap)710   void Disable(GLenum cap) { SetEnabled("disabled", cap, false); }
Enable(GLenum cap)711   void Enable(GLenum cap) { SetEnabled("enabled", cap, true); }
712   bool GetStencilBits(GLint* const out_stencilBits) const;
713 
714   virtual Maybe<double> GetParameter(GLenum pname);
715   Maybe<std::string> GetString(GLenum pname) const;
716 
717   bool IsEnabled(GLenum cap);
718 
719  private:
720   // State tracking slots
721   realGLboolean mDitherEnabled = 1;
722   realGLboolean mRasterizerDiscardEnabled = 0;
723   realGLboolean mScissorTestEnabled = 0;
724   realGLboolean mDepthTestEnabled = 0;
725   realGLboolean mStencilTestEnabled = 0;
726   realGLboolean mBlendEnabled = 0;
727   GLenum mGenerateMipmapHint = 0;
728 
729   struct ScissorRect final {
730     GLint x;
731     GLint y;
732     GLsizei w;
733     GLsizei h;
734 
735     void Apply(gl::GLContext&) const;
736   };
737   ScissorRect mScissorRect = {};
738 
739   bool ValidateCapabilityEnum(GLenum cap);
740   realGLboolean* GetStateTrackingSlot(GLenum cap);
741 
742   // Allocation debugging variables
743   mutable uint64_t mDataAllocGLCallCount = 0;
744 
OnDataAllocCall()745   void OnDataAllocCall() const { mDataAllocGLCallCount++; }
746 
GetNumGLDataAllocCalls()747   uint64_t GetNumGLDataAllocCalls() const { return mDataAllocGLCallCount; }
748 
749   void OnEndOfFrame();
750 
751   // -----------------------------------------------------------------------------
752   // Texture funcions (WebGLContextTextures.cpp)
753  public:
754   void ActiveTexture(uint32_t texUnit);
755   void BindTexture(GLenum texTarget, WebGLTexture* tex);
756   void GenerateMipmap(GLenum texTarget);
757 
758   Maybe<double> GetTexParameter(const WebGLTexture&, GLenum pname) const;
759   void TexParameter_base(GLenum texTarget, GLenum pname,
760                          const FloatOrInt& param);
761 
762   virtual bool IsTexParamValid(GLenum pname) const;
763 
764   ////////////////////////////////////
765   // Uploads
766 
767   // CompressedTexSubImage if `sub`
768   void CompressedTexImage(bool sub, GLenum imageTarget, uint32_t level,
769                           GLenum format, uvec3 offset, uvec3 size,
770                           const Range<const uint8_t>& src,
771                           const uint32_t pboImageSize,
772                           const Maybe<uint64_t>& pboOffset) const;
773 
774   // CopyTexSubImage if `!respectFormat`
775   void CopyTexImage(GLenum imageTarget, uint32_t level, GLenum respecFormat,
776                     uvec3 dstOffset, const ivec2& srcOffset,
777                     const uvec2& size) const;
778 
779   // TexSubImage if `!respectFormat`
780   void TexImage(uint32_t level, GLenum respecFormat, uvec3 offset,
781                 const webgl::PackingInfo& pi,
782                 const webgl::TexUnpackBlobDesc&) const;
783 
784   void TexStorage(GLenum texTarget, uint32_t levels, GLenum sizedFormat,
785                   uvec3 size) const;
786 
787   UniquePtr<webgl::TexUnpackBlob> ToTexUnpackBytes(
788       const WebGLTexImageData& imageData);
789 
790   UniquePtr<webgl::TexUnpackBytes> ToTexUnpackBytes(WebGLTexPboOffset& aPbo);
791 
792   ////////////////////////////////////
793   // WebGLTextureUpload.cpp
794  protected:
795   bool ValidateTexImageSpecification(uint8_t funcDims, GLenum texImageTarget,
796                                      GLint level, GLsizei width, GLsizei height,
797                                      GLsizei depth, GLint border,
798                                      TexImageTarget* const out_target,
799                                      WebGLTexture** const out_texture,
800                                      webgl::ImageInfo** const out_imageInfo);
801   bool ValidateTexImageSelection(uint8_t funcDims, GLenum texImageTarget,
802                                  GLint level, GLint xOffset, GLint yOffset,
803                                  GLint zOffset, GLsizei width, GLsizei height,
804                                  GLsizei depth,
805                                  TexImageTarget* const out_target,
806                                  WebGLTexture** const out_texture,
807                                  webgl::ImageInfo** const out_imageInfo);
808   bool ValidateUnpackInfo(bool usePBOs, GLenum format, GLenum type,
809                           webgl::PackingInfo* const out);
810 
811   // -----------------------------------------------------------------------------
812   // Vertices Feature (WebGLContextVertices.cpp)
813   GLenum mPrimRestartTypeBytes = 0;
814 
815  public:
816   void DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertexCount,
817                            GLsizei instanceCount);
818   void DrawElementsInstanced(GLenum mode, GLsizei vertexCount, GLenum type,
819                              WebGLintptr byteOffset, GLsizei instanceCount);
820 
821   void EnableVertexAttribArray(GLuint index);
822   void DisableVertexAttribArray(GLuint index);
823 
824   Maybe<double> GetVertexAttrib(GLuint index, GLenum pname);
825 
826   ////
827 
828   void VertexAttrib4T(GLuint index, const webgl::TypedQuad&);
829 
830   ////
831 
832   void VertexAttribPointer(uint32_t index, const webgl::VertAttribPointerDesc&);
833 
834   void VertexAttribDivisor(GLuint index, GLuint divisor);
835 
836  private:
837   WebGLBuffer* DrawElements_check(GLsizei indexCount, GLenum type,
838                                   WebGLintptr byteOffset,
839                                   GLsizei instanceCount);
840   void Draw_cleanup();
841 
842   void VertexAttrib1fv_base(GLuint index, uint32_t arrayLength,
843                             const GLfloat* ptr);
844   void VertexAttrib2fv_base(GLuint index, uint32_t arrayLength,
845                             const GLfloat* ptr);
846   void VertexAttrib3fv_base(GLuint index, uint32_t arrayLength,
847                             const GLfloat* ptr);
848   void VertexAttrib4fv_base(GLuint index, uint32_t arrayLength,
849                             const GLfloat* ptr);
850 
851   bool BindArrayAttribToLocation0(WebGLProgram* prog);
852 
853   // -----------------------------------------------------------------------------
854   // PROTECTED
855  protected:
856   WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need() const;
857   bool DoFakeVertexAttrib0(uint64_t vertexCount);
858   void UndoFakeVertexAttrib0();
859 
860   bool mResetLayer = true;
861   bool mOptionsFrozen = false;
862   bool mIsMesa = false;
863   bool mLoseContextOnMemoryPressure = false;
864   bool mCanLoseContextInForeground = true;
865   bool mShouldPresent = false;
866   bool mDisableFragHighP = false;
867   bool mForceResizeOnPresent = false;
868   bool mVRReady = false;
869 
870   template <typename WebGLObjectType>
871   void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
872 
873   GLuint mActiveTexture = 0;
874   GLenum mDefaultFB_DrawBuffer0 = 0;
875   GLenum mDefaultFB_ReadBuffer = 0;
876 
877   mutable GLenum mWebGLError = 0;
878 
879   std::unique_ptr<webgl::ShaderValidator> CreateShaderValidator(
880       GLenum shaderType) const;
881 
882   // some GL constants
883   uint32_t mGLMaxFragmentUniformVectors = 0;
884   uint32_t mGLMaxVertexUniformVectors = 0;
885   uint32_t mGLMaxVertexOutputVectors = 0;
886   uint32_t mGLMaxFragmentInputVectors = 0;
887 
888   uint32_t mGLMaxVertexTextureImageUnits = 0;
889   uint32_t mGLMaxFragmentTextureImageUnits = 0;
890   uint32_t mGLMaxCombinedTextureImageUnits = 0;
891 
892   // ES3:
893   uint32_t mGLMinProgramTexelOffset = 0;
894   uint32_t mGLMaxProgramTexelOffset = 0;
895 
896  public:
GLMaxDrawBuffers()897   auto GLMaxDrawBuffers() const { return mLimits->maxColorDrawBuffers; }
898 
MaxValidDrawBuffers()899   uint32_t MaxValidDrawBuffers() const {
900     if (IsWebGL2() ||
901         IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
902       return GLMaxDrawBuffers();
903     }
904     return 1;
905   }
906 
LastColorAttachmentEnum()907   GLenum LastColorAttachmentEnum() const {
908     return LOCAL_GL_COLOR_ATTACHMENT0 + MaxValidDrawBuffers() - 1;
909   }
910 
Options()911   const auto& Options() const { return mOptions; }
912 
913  protected:
914   uint32_t mGLMaxRenderbufferSize = 0;
915 
916  public:
Limits()917   const auto& Limits() const { return *mLimits; }
MaxVertexAttribs()918   auto MaxVertexAttribs() const { return mLimits->maxVertexAttribs; }
GLMaxTextureUnits()919   auto GLMaxTextureUnits() const { return mLimits->maxTexUnits; }
920 
921   bool IsFormatValidForFB(TexInternalFormat format) const;
922 
923  protected:
924   // -------------------------------------------------------------------------
925   // WebGL extensions (implemented in WebGLContextExtensions.cpp)
926 
927   EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max,
928                   std::unique_ptr<WebGLExtensionBase>>
929       mExtensions;
930 
931  public:
932   void RequestExtension(WebGLExtensionID, bool explicitly = true);
933 
934   // returns true if the extension has been enabled by calling getExtension.
IsExtensionEnabled(const WebGLExtensionID id)935   bool IsExtensionEnabled(const WebGLExtensionID id) const {
936     return bool(mExtensions[id]);
937   }
938 
939   bool IsExtensionExplicit(WebGLExtensionID) const;
940   void WarnIfImplicit(WebGLExtensionID) const;
941 
942   bool IsExtensionSupported(WebGLExtensionID) const;
943 
944   // -------------------------------------------------------------------------
945   // WebGL 2 specifics (implemented in WebGL2Context.cpp)
946  public:
IsWebGL2()947   virtual bool IsWebGL2() const { return false; }
948 
949   struct FailureReason {
950     nsCString key;  // For reporting.
951     nsCString info;
952 
953     FailureReason() = default;
954 
955     template <typename A, typename B>
FailureReasonFailureReason956     FailureReason(const A& _key, const B& _info)
957         : key(nsCString(_key)), info(nsCString(_info)) {}
958   };
959 
960  protected:
961   bool InitWebGL2(FailureReason* const out_failReason);
962 
963   bool CreateAndInitGL(bool forceEnabled,
964                        std::vector<FailureReason>* const out_failReasons);
965 
966   // -------------------------------------------------------------------------
967   // Validation functions (implemented in WebGLContextValidate.cpp)
968   bool InitAndValidateGL(FailureReason* const out_failReason);
969 
970   bool ValidateBlendEquationEnum(GLenum cap, const char* info);
971   bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
972                                            const char* info);
973   bool ValidateStencilOpEnum(GLenum action, const char* info);
974   bool ValidateFaceEnum(GLenum face);
975   bool ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
976                             WebGLTexImageFunc func, WebGLTexDimensions dims);
977   bool ValidateAttribPointer(bool integerMode, GLuint index, GLint size,
978                              GLenum type, WebGLboolean normalized,
979                              GLsizei stride, WebGLintptr byteOffset,
980                              const char* info);
981   bool ValidateStencilParamsForDrawCall() const;
982 
983   bool ValidateCopyTexImage(TexInternalFormat srcFormat,
984                             TexInternalFormat dstformat, WebGLTexImageFunc func,
985                             WebGLTexDimensions dims);
986 
987   bool ValidateTexImage(TexImageTarget texImageTarget, GLint level,
988                         GLenum internalFormat, GLint xoffset, GLint yoffset,
989                         GLint zoffset, GLint width, GLint height, GLint depth,
990                         GLint border, GLenum format, GLenum type,
991                         WebGLTexImageFunc func, WebGLTexDimensions dims);
992   bool ValidateTexImageFormat(GLenum internalFormat, WebGLTexImageFunc func,
993                               WebGLTexDimensions dims);
994   bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func,
995                             WebGLTexDimensions dims);
996   bool ValidateTexImageFormatAndType(GLenum format, GLenum type,
997                                      WebGLTexImageFunc func,
998                                      WebGLTexDimensions dims);
999   bool ValidateCompTexImageInternalFormat(GLenum format, WebGLTexImageFunc func,
1000                                           WebGLTexDimensions dims);
1001   bool ValidateCopyTexImageInternalFormat(GLenum format, WebGLTexImageFunc func,
1002                                           WebGLTexDimensions dims);
1003   bool ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
1004                             GLint width, GLint height, GLint depth,
1005                             WebGLTexImageFunc func, WebGLTexDimensions dims);
1006   bool ValidateTexSubImageSize(GLint x, GLint y, GLint z, GLsizei width,
1007                                GLsizei height, GLsizei depth, GLsizei baseWidth,
1008                                GLsizei baseHeight, GLsizei baseDepth,
1009                                WebGLTexImageFunc func, WebGLTexDimensions dims);
1010   bool ValidateCompTexImageSize(GLint level, GLenum internalFormat,
1011                                 GLint xoffset, GLint yoffset, GLsizei width,
1012                                 GLsizei height, GLsizei levelWidth,
1013                                 GLsizei levelHeight, WebGLTexImageFunc func,
1014                                 WebGLTexDimensions dims);
1015   bool ValidateCompTexImageDataSize(GLint level, GLenum internalFormat,
1016                                     GLsizei width, GLsizei height,
1017                                     uint32_t byteLength, WebGLTexImageFunc func,
1018                                     WebGLTexDimensions dims);
1019 
HasDrawBuffers()1020   bool HasDrawBuffers() const {
1021     return IsWebGL2() ||
1022            IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
1023   }
1024 
1025   RefPtr<WebGLBuffer>* ValidateBufferSlot(GLenum target);
1026 
1027  public:
1028   WebGLBuffer* ValidateBufferSelection(GLenum target) const;
1029 
1030  protected:
1031   IndexedBufferBinding* ValidateIndexedBufferSlot(GLenum target, GLuint index);
1032 
1033   bool ValidateIndexedBufferBinding(
1034       GLenum target, GLuint index,
1035       RefPtr<WebGLBuffer>** const out_genericBinding,
1036       IndexedBufferBinding** const out_indexedBinding);
1037 
1038  public:
ValidateNonNegative(const char * argName,int64_t val)1039   bool ValidateNonNegative(const char* argName, int64_t val) const {
1040     if (MOZ_UNLIKELY(val < 0)) {
1041       ErrorInvalidValue("`%s` must be non-negative.", argName);
1042       return false;
1043     }
1044     return true;
1045   }
1046 
1047   template <typename T>
ValidateNonNull(const char * const argName,const dom::Nullable<T> & maybe)1048   bool ValidateNonNull(const char* const argName,
1049                        const dom::Nullable<T>& maybe) const {
1050     if (maybe.IsNull()) {
1051       ErrorInvalidValue("%s: Cannot be null.", argName);
1052       return false;
1053     }
1054     return true;
1055   }
1056 
1057   ////
1058 
1059  protected:
1060   void DestroyResourcesAndContext();
1061 
1062   // helpers
1063 
1064   bool ConvertImage(size_t width, size_t height, size_t srcStride,
1065                     size_t dstStride, const uint8_t* src, uint8_t* dst,
1066                     WebGLTexelFormat srcFormat, bool srcPremultiplied,
1067                     WebGLTexelFormat dstFormat, bool dstPremultiplied,
1068                     size_t dstTexelSize);
1069 
1070   //////
1071  public:
1072   template <typename T>
ValidateObject(const char * const argName,const T & object)1073   bool ValidateObject(const char* const argName, const T& object) const {
1074     // Todo: Remove all callers.
1075     return true;
1076   }
1077 
1078   template <typename T>
ValidateObject(const char * const argName,const T * const object)1079   bool ValidateObject(const char* const argName, const T* const object) const {
1080     // Todo: Remove most (all?) callers.
1081     if (!object) {
1082       ErrorInvalidOperation(
1083           "%s: Object argument cannot have been marked for"
1084           " deletion.",
1085           argName);
1086       return false;
1087     }
1088     return true;
1089   }
1090 
1091   ////
1092 
1093  public:
1094   void LoseContext(
1095       webgl::ContextLossReason reason = webgl::ContextLossReason::None);
1096 
1097  protected:
1098   nsTArray<RefPtr<WebGLTexture>> mBound2DTextures;
1099   nsTArray<RefPtr<WebGLTexture>> mBoundCubeMapTextures;
1100   nsTArray<RefPtr<WebGLTexture>> mBound3DTextures;
1101   nsTArray<RefPtr<WebGLTexture>> mBound2DArrayTextures;
1102   nsTArray<RefPtr<WebGLSampler>> mBoundSamplers;
1103 
1104   void ResolveTexturesForDraw() const;
1105 
1106   RefPtr<WebGLProgram> mCurrentProgram;
1107   RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
1108 
1109   bool ValidateFramebufferTarget(GLenum target) const;
1110   bool ValidateInvalidateFramebuffer(GLenum target,
1111                                      const Range<const GLenum>& attachments,
1112                                      std::vector<GLenum>* const scopedVector,
1113                                      GLsizei* const out_glNumAttachments,
1114                                      const GLenum** const out_glAttachments);
1115 
1116   RefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
1117   RefPtr<WebGLFramebuffer> mBoundReadFramebuffer;
1118   RefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
1119   RefPtr<WebGLVertexArray> mBoundVertexArray;
1120 
1121  public:
BoundReadFb()1122   const auto& BoundReadFb() const { return mBoundReadFramebuffer; }
1123 
1124  protected:
1125   RefPtr<WebGLTransformFeedback> mDefaultTransformFeedback;
1126   RefPtr<WebGLVertexArray> mDefaultVertexArray;
1127 
1128   ////////////////////////////////////
1129 
1130  protected:
1131   GLuint mEmptyTFO = 0;
1132 
1133   // Generic Vertex Attributes
1134   // Though CURRENT_VERTEX_ATTRIB is listed under "Vertex Shader State" in the
1135   // spec state tables, this isn't vertex shader /object/ state. This array is
1136   // merely state useful to vertex shaders, but is global state.
1137   std::vector<webgl::AttribBaseType> mGenericVertexAttribTypes;
1138   CacheInvalidator mGenericVertexAttribTypeInvalidator;
1139 
1140   GLuint mFakeVertexAttrib0BufferObject = 0;
1141   size_t mFakeVertexAttrib0BufferObjectSize = 0;
1142   bool mFakeVertexAttrib0DataDefined = false;
1143   alignas(alignof(float)) uint8_t
1144       mGenericVertexAttrib0Data[sizeof(float) * 4] = {};
1145   alignas(alignof(float)) uint8_t
1146       mFakeVertexAttrib0Data[sizeof(float) * 4] = {};
1147 
1148   GLint mStencilRefFront = 0;
1149   GLint mStencilRefBack = 0;
1150   GLuint mStencilValueMaskFront = 0;
1151   GLuint mStencilValueMaskBack = 0;
1152   GLuint mStencilWriteMaskFront = 0;
1153   GLuint mStencilWriteMaskBack = 0;
1154   uint8_t mColorWriteMask = 0xf;  // bitmask
1155   realGLboolean mDepthWriteMask = 0;
1156   GLfloat mColorClearValue[4];
1157   GLint mStencilClearValue = 0;
1158   GLfloat mDepthClearValue = 0.0;
1159 
1160   GLint mViewportX = 0;
1161   GLint mViewportY = 0;
1162   GLsizei mViewportWidth = 0;
1163   GLsizei mViewportHeight = 0;
1164   bool mAlreadyWarnedAboutViewportLargerThanDest = false;
1165 
1166   GLfloat mLineWidth = 0.0;
1167 
1168   WebGLContextLossHandler mContextLossHandler;
1169 
1170   // Used for some hardware (particularly Tegra 2 and 4) that likes to
1171   // be Flushed while doing hundreds of draw calls.
1172   mutable uint64_t mDrawCallsSinceLastFlush = 0;
1173 
1174   mutable uint64_t mWarningCount = 0;
1175   const uint64_t mMaxWarnings;
1176   bool mAlreadyWarnedAboutFakeVertexAttrib0 = false;
1177 
ShouldGenerateWarnings()1178   bool ShouldGenerateWarnings() const { return mWarningCount < mMaxWarnings; }
1179 
ShouldGeneratePerfWarnings()1180   bool ShouldGeneratePerfWarnings() const {
1181     return mNumPerfWarnings < mMaxPerfWarnings;
1182   }
1183 
1184   bool mNeedsFakeNoAlpha = false;
1185   bool mNeedsFakeNoDepth = false;
1186   bool mNeedsFakeNoStencil = false;
1187   bool mNeedsFakeNoStencil_UserFBs = false;
1188 
1189   mutable uint8_t mDriverColorMask = 0;
1190   bool mDriverDepthTest = false;
1191   bool mDriverStencilTest = false;
1192 
1193   bool mNeedsIndexValidation = false;
1194 
1195   const bool mAllowFBInvalidation;
1196 
1197   bool Has64BitTimestamps() const;
1198 
1199   // --
1200 
1201   const uint8_t mMsaaSamples;
1202   mutable uvec2 mRequestedSize;
1203   mutable UniquePtr<gl::MozFramebuffer> mDefaultFB;
1204   mutable bool mDefaultFB_IsInvalid = false;
1205   mutable UniquePtr<gl::MozFramebuffer> mResolvedDefaultFB;
1206 
1207   gl::SwapChain mSwapChain;
1208   gl::SwapChain mWebVRSwapChain;
1209 
1210   // --
1211 
1212   bool EnsureDefaultFB();
1213   bool ValidateAndInitFB(
1214       const WebGLFramebuffer* fb,
1215       GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
1216   void DoBindFB(const WebGLFramebuffer* fb,
1217                 GLenum target = LOCAL_GL_FRAMEBUFFER) const;
1218 
1219   bool BindCurFBForDraw();
1220   bool BindCurFBForColorRead(
1221       const webgl::FormatUsageInfo** out_format, uint32_t* out_width,
1222       uint32_t* out_height,
1223       GLenum incompleteFbError = LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
1224   void DoColorMask(uint8_t bitmask) const;
1225   void BlitBackbufferToCurDriverFB(
1226       const gl::MozFramebuffer* const source = nullptr) const;
1227   bool BindDefaultFBForRead();
1228 
1229   // --
1230 
1231  public:
1232   // console logging helpers
1233   template <typename... Args>
GenerateWarning(const char * const fmt,const Args &...args)1234   void GenerateWarning(const char* const fmt, const Args&... args) const {
1235     GenerateError(0, fmt, args...);
1236   }
1237 
1238   template <typename... Args>
GeneratePerfWarning(const char * const fmt,const Args &...args)1239   void GeneratePerfWarning(const char* const fmt, const Args&... args) const {
1240     GenerateError(webgl::kErrorPerfWarning, fmt, args...);
1241   }
1242 
1243  public:
1244   UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
1245 
1246   virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage(
1247       gl::GLContext* gl) const;
1248 
1249   const decltype(mBound2DTextures)* TexListForElemType(GLenum elemType) const;
1250 
1251   // Friend list
1252   friend class ScopedCopyTexImageSource;
1253   friend class ScopedResolveTexturesForDraw;
1254   friend class webgl::TexUnpackBlob;
1255   friend class webgl::TexUnpackBytes;
1256   friend class webgl::TexUnpackImage;
1257   friend class webgl::TexUnpackSurface;
1258   friend struct webgl::UniformInfo;
1259   friend class WebGLTexture;
1260   friend class WebGLFBAttachPoint;
1261   friend class WebGLFramebuffer;
1262   friend class WebGLRenderbuffer;
1263   friend class WebGLProgram;
1264   friend class WebGLQuery;
1265   friend class WebGLBuffer;
1266   friend class WebGLSampler;
1267   friend class WebGLShader;
1268   friend class WebGLSync;
1269   friend class WebGLTransformFeedback;
1270   friend class WebGLVertexArray;
1271   friend class WebGLVertexArrayFake;
1272   friend class WebGLVertexArrayGL;
1273 };
1274 
1275 // Returns `value` rounded to the next highest multiple of `multiple`.
1276 // AKA PadToAlignment, StrideForAlignment.
1277 template <typename V, typename M>
RoundUpToMultipleOf(const V & value,const M & multiple)1278 V RoundUpToMultipleOf(const V& value, const M& multiple) {
1279   return ((value + multiple - 1) / multiple) * multiple;
1280 }
1281 
1282 const char* GetEnumName(GLenum val, const char* defaultRet = "<unknown>");
1283 std::string EnumString(GLenum val);
1284 
1285 class ScopedFBRebinder final {
1286  private:
1287   const WebGLContext* const mWebGL;
1288 
1289  public:
ScopedFBRebinder(const WebGLContext * const webgl)1290   explicit ScopedFBRebinder(const WebGLContext* const webgl) : mWebGL(webgl) {}
1291   ~ScopedFBRebinder();
1292 };
1293 
1294 // -
1295 
IsBufferTargetLazilyBound(const GLenum target)1296 constexpr inline bool IsBufferTargetLazilyBound(const GLenum target) {
1297   return target != LOCAL_GL_ELEMENT_ARRAY_BUFFER;
1298 }
1299 
1300 void DoBindBuffer(gl::GLContext&, GLenum target, const WebGLBuffer*);
1301 
1302 class ScopedLazyBind final {
1303  private:
1304   gl::GLContext& mGL;
1305   const GLenum mTarget;
1306 
1307  public:
ScopedLazyBind(gl::GLContext * const gl,const GLenum target,const WebGLBuffer * const buf)1308   ScopedLazyBind(gl::GLContext* const gl, const GLenum target,
1309                  const WebGLBuffer* const buf)
1310       : mGL(*gl), mTarget(IsBufferTargetLazilyBound(target) ? target : 0) {
1311     if (mTarget) {
1312       DoBindBuffer(mGL, mTarget, buf);
1313     }
1314   }
1315 
~ScopedLazyBind()1316   ~ScopedLazyBind() {
1317     if (mTarget) {
1318       DoBindBuffer(mGL, mTarget, nullptr);
1319     }
1320   }
1321 };
1322 
1323 ////
1324 
1325 bool Intersect(int32_t srcSize, int32_t read0, int32_t readSize,
1326                int32_t* out_intRead0, int32_t* out_intWrite0,
1327                int32_t* out_intSize);
1328 
1329 uint64_t AvailGroups(uint64_t totalAvailItems, uint64_t firstItemOffset,
1330                      uint32_t groupSize, uint32_t groupStride);
1331 
1332 ////
1333 
1334 class ScopedDrawCallWrapper final {
1335  public:
1336   WebGLContext& mWebGL;
1337 
1338   explicit ScopedDrawCallWrapper(WebGLContext& webgl);
1339   ~ScopedDrawCallWrapper();
1340 };
1341 
1342 namespace webgl {
1343 
1344 class ScopedPrepForResourceClear final {
1345   const WebGLContext& webgl;
1346 
1347  public:
1348   explicit ScopedPrepForResourceClear(const WebGLContext&);
1349   ~ScopedPrepForResourceClear();
1350 };
1351 
1352 struct IndexedName final {
1353   std::string name;
1354   uint64_t index;
1355 };
1356 Maybe<IndexedName> ParseIndexed(const std::string& str);
1357 
1358 }  // namespace webgl
1359 
1360 webgl::LinkActiveInfo GetLinkActiveInfo(
1361     gl::GLContext& gl, const GLuint prog, const bool webgl2,
1362     const std::unordered_map<std::string, std::string>& nameUnmap);
1363 
1364 }  // namespace mozilla
1365 
1366 #endif
1367