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