WebGL 2 Conformance: primitive restart and draw_primitive_restart WebGL2 sample
[WebKit-https.git] / Source / WebCore / html / canvas / WebGLRenderingContextBase.h
1 /*
2  * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #if ENABLE(WEBGL)
29
30 #include "ActivityStateChangeObserver.h"
31 #include "ExceptionOr.h"
32 #include "GPUBasedCanvasRenderingContext.h"
33 #include "GraphicsContext3D.h"
34 #include "ImageBuffer.h"
35 #include "Timer.h"
36 #include "WebGLAny.h"
37 #include "WebGLBuffer.h"
38 #include "WebGLContextAttributes.h"
39 #include "WebGLFramebuffer.h"
40 #include "WebGLProgram.h"
41 #include "WebGLRenderbuffer.h"
42 #include "WebGLStateTracker.h"
43 #include "WebGLTexture.h"
44 #include "WebGLVertexArrayObjectOES.h"
45 #include <JavaScriptCore/ConsoleTypes.h>
46 #include <limits>
47 #include <memory>
48
49 #if ENABLE(WEBGL2)
50 #include "WebGLVertexArrayObject.h"
51 #endif
52
53 namespace WebCore {
54
55 class ANGLEInstancedArrays;
56 class EXTBlendMinMax;
57 class EXTTextureFilterAnisotropic;
58 class EXTShaderTextureLOD;
59 class EXTsRGB;
60 class EXTFragDepth;
61 class HTMLImageElement;
62 class ImageData;
63 class IntSize;
64 class OESStandardDerivatives;
65 class OESTextureFloat;
66 class OESTextureFloatLinear;
67 class OESTextureHalfFloat;
68 class OESTextureHalfFloatLinear;
69 class OESVertexArrayObject;
70 class OESElementIndexUint;
71 class OffscreenCanvas;
72 class WebGLActiveInfo;
73 class WebGLContextGroup;
74 class WebGLContextObject;
75 class WebGLCompressedTextureASTC;
76 class WebGLCompressedTextureATC;
77 class WebGLCompressedTexturePVRTC;
78 class WebGLCompressedTextureS3TC;
79 class WebGLDebugRendererInfo;
80 class WebGLDebugShaders;
81 class WebGLDepthTexture;
82 class WebGLDrawBuffers;
83 class WebGLExtension;
84 class WebGLLoseContext;
85 class WebGLObject;
86 class WebGLShader;
87 class WebGLSharedObject;
88 class WebGLShaderPrecisionFormat;
89 class WebGLUniformLocation;
90
91 #if ENABLE(VIDEO)
92 class HTMLVideoElement;
93 #endif
94
95 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>, RefPtr<OffscreenCanvas>>;
96
97 class WebGLRenderingContextBase : public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
98 public:
99     static std::unique_ptr<WebGLRenderingContextBase> create(CanvasBase&, WebGLContextAttributes&, const String&);
100     virtual ~WebGLRenderingContextBase();
101
102     WebGLCanvas canvas();
103
104     int drawingBufferWidth() const;
105     int drawingBufferHeight() const;
106
107     void activeTexture(GC3Denum texture);
108     void attachShader(WebGLProgram*, WebGLShader*);
109     void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name);
110     void bindBuffer(GC3Denum target, WebGLBuffer*);
111     void bindFramebuffer(GC3Denum target, WebGLFramebuffer*);
112     void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*);
113     void bindTexture(GC3Denum target, WebGLTexture*);
114     void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
115     void blendEquation(GC3Denum mode);
116     void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
117     void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
118     void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
119
120     using BufferDataSource = WTF::Variant<RefPtr<ArrayBuffer>, RefPtr<ArrayBufferView>>;
121     void bufferData(GC3Denum target, long long size, GC3Denum usage);
122     void bufferData(GC3Denum target, std::optional<BufferDataSource>&&, GC3Denum usage);
123     void bufferSubData(GC3Denum target, long long offset, std::optional<BufferDataSource>&&);
124
125     GC3Denum checkFramebufferStatus(GC3Denum target);
126     virtual void clear(GC3Dbitfield mask) = 0;
127     void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
128     void clearDepth(GC3Dfloat);
129     void clearStencil(GC3Dint);
130     void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
131     void compileShader(WebGLShader*);
132
133     void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data);
134     void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data);
135
136     void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
137     void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
138
139     RefPtr<WebGLBuffer> createBuffer();
140     RefPtr<WebGLFramebuffer> createFramebuffer();
141     RefPtr<WebGLProgram> createProgram();
142     RefPtr<WebGLRenderbuffer> createRenderbuffer();
143     RefPtr<WebGLShader> createShader(GC3Denum type);
144     RefPtr<WebGLTexture> createTexture();
145
146     void cullFace(GC3Denum mode);
147
148     void deleteBuffer(WebGLBuffer*);
149     void deleteFramebuffer(WebGLFramebuffer*);
150     void deleteProgram(WebGLProgram*);
151     void deleteRenderbuffer(WebGLRenderbuffer*);
152     void deleteShader(WebGLShader*);
153     void deleteTexture(WebGLTexture*);
154
155     void depthFunc(GC3Denum);
156     void depthMask(GC3Dboolean);
157     void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
158     void detachShader(WebGLProgram*, WebGLShader*);
159     void disable(GC3Denum cap);
160     void disableVertexAttribArray(GC3Duint index);
161     void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count);
162     void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset);
163
164     void enable(GC3Denum cap);
165     void enableVertexAttribArray(GC3Duint index);
166     void finish();
167     void flush();
168     void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*);
169     void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level);
170     void frontFace(GC3Denum mode);
171     void generateMipmap(GC3Denum target);
172
173     RefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index);
174     RefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index);
175     std::optional<Vector<RefPtr<WebGLShader>>> getAttachedShaders(WebGLProgram*);
176     GC3Dint getAttribLocation(WebGLProgram*, const String& name);
177     WebGLAny getBufferParameter(GC3Denum target, GC3Denum pname);
178     std::optional<WebGLContextAttributes> getContextAttributes();
179     GC3Denum getError();
180     virtual WebGLExtension* getExtension(const String& name) = 0;
181     virtual WebGLAny getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) = 0;
182     virtual WebGLAny getParameter(GC3Denum pname) = 0;
183     WebGLAny getProgramParameter(WebGLProgram*, GC3Denum pname);
184     String getProgramInfoLog(WebGLProgram*);
185     WebGLAny getRenderbufferParameter(GC3Denum target, GC3Denum pname);
186     WebGLAny getShaderParameter(WebGLShader*, GC3Denum pname);
187     String getShaderInfoLog(WebGLShader*);
188     RefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType);
189     String getShaderSource(WebGLShader*);
190     virtual std::optional<Vector<String>> getSupportedExtensions() = 0;
191     WebGLAny getTexParameter(GC3Denum target, GC3Denum pname);
192     WebGLAny getUniform(WebGLProgram*, const WebGLUniformLocation*);
193     RefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&);
194     WebGLAny getVertexAttrib(GC3Duint index, GC3Denum pname);
195     long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
196
197     bool extensionIsEnabled(const String&);
198
199     bool isPreservingDrawingBuffer() const { return m_attributes.preserveDrawingBuffer; }
200     void setPreserveDrawingBuffer(bool value) { m_attributes.preserveDrawingBuffer = value; }
201
202     bool preventBufferClearForInspector() const { return m_preventBufferClearForInspector; }
203     void setPreventBufferClearForInspector(bool value) { m_preventBufferClearForInspector = value; }
204
205     virtual void hint(GC3Denum target, GC3Denum mode) = 0;
206     GC3Dboolean isBuffer(WebGLBuffer*);
207     bool isContextLost() const;
208     GC3Dboolean isEnabled(GC3Denum cap);
209     GC3Dboolean isFramebuffer(WebGLFramebuffer*);
210     GC3Dboolean isProgram(WebGLProgram*);
211     GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
212     GC3Dboolean isShader(WebGLShader*);
213     GC3Dboolean isTexture(WebGLTexture*);
214
215     void lineWidth(GC3Dfloat);
216     void linkProgram(WebGLProgram*);
217     bool linkProgramWithoutInvalidatingAttribLocations(WebGLProgram*);
218     void pixelStorei(GC3Denum pname, GC3Dint param);
219     void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
220     void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels);
221     void releaseShaderCompiler();
222     virtual void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) = 0;
223     void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
224     void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
225     void shaderSource(WebGLShader*, const String&);
226     void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
227     void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
228     void stencilMask(GC3Duint);
229     void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
230     void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
231     void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
232
233     void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&);
234
235 #if ENABLE(VIDEO)
236     using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
237 #else
238     using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
239 #endif
240
241     ExceptionOr<void> texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, std::optional<TexImageSource>);
242
243     void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
244     void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
245
246     void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&);
247     ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, std::optional<TexImageSource>&&);
248
249     template <class TypedArray, class DataType>
250     class TypedList {
251     public:
252         using VariantType = Variant<RefPtr<TypedArray>, Vector<DataType>>;
253
254         TypedList(VariantType&& variant)
255             : m_variant(WTFMove(variant))
256         {
257         }
258
259         const DataType* data() const
260         {
261             return WTF::switchOn(m_variant,
262                 [] (const RefPtr<TypedArray>& typedArray) -> const DataType* { return typedArray->data(); },
263                 [] (const Vector<DataType>& vector) -> const DataType* { return vector.data(); }
264             );
265         }
266
267         GC3Dsizei length() const
268         {
269             return WTF::switchOn(m_variant,
270                 [] (const RefPtr<TypedArray>& typedArray) -> GC3Dsizei { return typedArray->length(); },
271                 [] (const Vector<DataType>& vector) -> GC3Dsizei { return vector.size(); }
272             );
273         }
274
275     private:
276         VariantType m_variant;
277     };
278
279     using Float32List = TypedList<Float32Array, float>;
280     using Int32List = TypedList<Int32Array, int>;
281
282     void uniform1f(const WebGLUniformLocation*, GC3Dfloat x);
283     void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y);
284     void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
285     void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
286
287     void uniform1i(const WebGLUniformLocation*, GC3Dint x);
288     void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y);
289     void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z);
290     void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w);
291
292     void uniform1fv(const WebGLUniformLocation*, Float32List&&);
293     void uniform2fv(const WebGLUniformLocation*, Float32List&&);
294     void uniform3fv(const WebGLUniformLocation*, Float32List&&);
295     void uniform4fv(const WebGLUniformLocation*, Float32List&&);
296
297     void uniform1iv(const WebGLUniformLocation*, Int32List&&);
298     void uniform2iv(const WebGLUniformLocation*, Int32List&&);
299     void uniform3iv(const WebGLUniformLocation*, Int32List&&);
300     void uniform4iv(const WebGLUniformLocation*, Int32List&&);
301
302     void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
303     void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
304     void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
305
306     void useProgram(WebGLProgram*);
307     void validateProgram(WebGLProgram*);
308
309     void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
310     void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
311     void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
312     void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
313
314     void vertexAttrib1fv(GC3Duint index, Float32List&&);
315     void vertexAttrib2fv(GC3Duint index, Float32List&&);
316     void vertexAttrib3fv(GC3Duint index, Float32List&&);
317     void vertexAttrib4fv(GC3Duint index, Float32List&&);
318
319     void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
320         GC3Dsizei stride, long long offset);
321
322     void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
323
324     // WEBKIT_lose_context support
325     enum LostContextMode {
326         // Lost context occurred at the graphics system level.
327         RealLostContext,
328
329         // Lost context provoked by WEBKIT_lose_context.
330         SyntheticLostContext
331     };
332     void forceLostContext(LostContextMode);
333     void recycleContext();
334     void forceRestoreContext();
335     void loseContextImpl(LostContextMode);
336     void dispatchContextChangedEvent();
337     WEBCORE_EXPORT void simulateContextChanged();
338
339     GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
340     WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
341     PlatformLayer* platformLayer() const override;
342
343     void reshape(int width, int height) override;
344
345     void markLayerComposited() final;
346     void paintRenderingResultsToCanvas() override;
347     RefPtr<ImageData> paintRenderingResultsToImageData();
348
349     void removeSharedObject(WebGLSharedObject&);
350     void removeContextObject(WebGLContextObject&);
351     
352     unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
353
354     // Instanced Array helper functions.
355     void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
356     void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount);
357     void vertexAttribDivisor(GC3Duint index, GC3Duint divisor);
358
359     // Used for testing only, from Internals.
360     WEBCORE_EXPORT void setFailNextGPUStatusCheck();
361
362 protected:
363     WebGLRenderingContextBase(CanvasBase&, WebGLContextAttributes);
364     WebGLRenderingContextBase(CanvasBase&, Ref<GraphicsContext3D>&&, WebGLContextAttributes);
365
366     friend class WebGLDrawBuffers;
367     friend class WebGLFramebuffer;
368     friend class WebGLObject;
369     friend class OESVertexArrayObject;
370     friend class WebGLDebugShaders;
371     friend class WebGLCompressedTextureASTC;
372     friend class WebGLCompressedTextureATC;
373     friend class WebGLCompressedTexturePVRTC;
374     friend class WebGLCompressedTextureS3TC;
375     friend class WebGLRenderingContextErrorMessageCallback;
376     friend class WebGLVertexArrayObjectOES;
377     friend class WebGLVertexArrayObject;
378     friend class WebGLVertexArrayObjectBase;
379
380     virtual void initializeNewContext();
381     virtual void initializeVertexArrayObjects() = 0;
382     void setupFlags();
383
384     // ActiveDOMObject
385     bool hasPendingActivity() const override;
386     void stop() override;
387     const char* activeDOMObjectName() const override;
388     bool canSuspendForDocumentSuspension() const override;
389
390     void addSharedObject(WebGLSharedObject&);
391     void addContextObject(WebGLContextObject&);
392     void detachAndRemoveAllObjects();
393
394     void destroyGraphicsContext3D();
395     void markContextChanged();
396     void markContextChangedAndNotifyCanvasObserver();
397
398     void addActivityStateChangeObserverIfNecessary();
399     void removeActivityStateChangeObserver();
400
401     // Query whether it is built on top of compliant GLES2 implementation.
402     bool isGLES2Compliant() { return m_isGLES2Compliant; }
403     // Query if the GL implementation is NPOT strict.
404     bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
405     // Query if depth_stencil buffer is supported.
406     bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
407
408     // Helper to return the size in bytes of OpenGL data types
409     // like GL_FLOAT, GL_INT, etc.
410     unsigned int sizeInBytes(GC3Denum type);
411
412     // Basic validation of count and offset against number of elements in element array buffer
413     bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
414
415     // Conservative but quick index validation
416     virtual bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) = 0;
417
418     // Precise but slow index validation -- only done if conservative checks fail
419     bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired);
420     bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0);
421
422     bool validateWebGLObject(const char*, WebGLObject*);
423
424     bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
425     bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount);
426     bool validateNPOTTextureLevel(GC3Dsizei width, GC3Dsizei height, GC3Dint level, const char* functionName);
427
428     // Adds a compressed texture format.
429     void addCompressedTextureFormat(GC3Denum);
430
431     RefPtr<Image> drawImageIntoBuffer(Image&, int width, int height, int deviceScaleFactor);
432
433 #if ENABLE(VIDEO)
434     RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy);
435 #endif
436
437     WebGLTexture::TextureExtensionFlag textureExtensionFlags() const;
438
439     bool enableSupportedExtension(ASCIILiteral extensionNameLiteral);
440
441     RefPtr<GraphicsContext3D> m_context;
442     RefPtr<WebGLContextGroup> m_contextGroup;
443
444     // Dispatches a context lost event once it is determined that one is needed.
445     // This is used both for synthetic and real context losses. For real ones, it's
446     // likely that there's no JavaScript on the stack, but that might be dependent
447     // on how exactly the platform discovers that the context was lost. For better
448     // portability we always defer the dispatch of the event.
449     Timer m_dispatchContextLostEventTimer;
450     bool m_restoreAllowed { false };
451     Timer m_restoreTimer;
452
453     bool m_needsUpdate;
454     bool m_markedCanvasDirty;
455     HashSet<WebGLContextObject*> m_contextObjects;
456
457     // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
458     RefPtr<WebGLBuffer> m_boundArrayBuffer;
459     RefPtr<WebGLBuffer> m_boundCopyReadBuffer;
460     RefPtr<WebGLBuffer> m_boundCopyWriteBuffer;
461     RefPtr<WebGLBuffer> m_boundPixelPackBuffer;
462     RefPtr<WebGLBuffer> m_boundPixelUnpackBuffer;
463     RefPtr<WebGLBuffer> m_boundTransformFeedbackBuffer;
464     RefPtr<WebGLBuffer> m_boundUniformBuffer;
465
466     RefPtr<WebGLVertexArrayObjectBase> m_defaultVertexArrayObject;
467     RefPtr<WebGLVertexArrayObjectBase> m_boundVertexArrayObject;
468
469     void setBoundVertexArrayObject(WebGLVertexArrayObjectBase* arrayObject)
470     {
471         m_boundVertexArrayObject = arrayObject ? arrayObject : m_defaultVertexArrayObject;
472     }
473     
474     class VertexAttribValue {
475     public:
476         VertexAttribValue()
477         {
478             initValue();
479         }
480         
481         void initValue()
482         {
483             value[0] = 0.0f;
484             value[1] = 0.0f;
485             value[2] = 0.0f;
486             value[3] = 1.0f;
487         }
488         
489         GC3Dfloat value[4];
490     };
491     Vector<VertexAttribValue> m_vertexAttribValue;
492     unsigned m_maxVertexAttribs;
493     RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
494     long m_vertexAttrib0BufferSize { 0 };
495     GC3Dfloat m_vertexAttrib0BufferValue[4];
496     bool m_forceAttrib0BufferRefill { true };
497     bool m_vertexAttrib0UsedBefore { false };
498
499     RefPtr<WebGLProgram> m_currentProgram;
500     RefPtr<WebGLFramebuffer> m_framebufferBinding;
501     RefPtr<WebGLFramebuffer> m_readFramebufferBinding;
502     RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
503     struct TextureUnitState {
504         RefPtr<WebGLTexture> texture2DBinding;
505         RefPtr<WebGLTexture> textureCubeMapBinding;
506     };
507     Vector<TextureUnitState> m_textureUnits;
508     HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_unrenderableTextureUnits;
509
510     unsigned long m_activeTextureUnit;
511
512     RefPtr<WebGLTexture> m_blackTexture2D;
513     RefPtr<WebGLTexture> m_blackTextureCubeMap;
514
515     Vector<GC3Denum> m_compressedTextureFormats;
516
517     // Fixed-size cache of reusable image buffers for video texImage2D calls.
518     class LRUImageBufferCache {
519     public:
520         LRUImageBufferCache(int capacity);
521         // The pointer returned is owned by the image buffer map.
522         ImageBuffer* imageBuffer(const IntSize& size);
523     private:
524         void bubbleToFront(size_t idx);
525         Vector<std::unique_ptr<ImageBuffer>> m_buffers;
526     };
527     LRUImageBufferCache m_generatedImageCache { 0 };
528
529     GC3Dint m_maxTextureSize;
530     GC3Dint m_maxCubeMapTextureSize;
531     GC3Dint m_maxRenderbufferSize;
532     GC3Dint m_maxViewportDims[2] { 0, 0 };
533     GC3Dint m_maxTextureLevel;
534     GC3Dint m_maxCubeMapTextureLevel;
535
536     GC3Dint m_maxDrawBuffers;
537     GC3Dint m_maxColorAttachments;
538     GC3Denum m_backDrawBuffer;
539     bool m_drawBuffersWebGLRequirementsChecked;
540     bool m_drawBuffersSupported;
541
542     GC3Dint m_packAlignment;
543     GC3Dint m_unpackAlignment;
544     bool m_unpackFlipY;
545     bool m_unpackPremultiplyAlpha;
546     GC3Denum m_unpackColorspaceConversion;
547     bool m_contextLost { false };
548     LostContextMode m_contextLostMode { SyntheticLostContext };
549     WebGLContextAttributes m_attributes;
550
551     bool m_layerCleared;
552     GC3Dfloat m_clearColor[4];
553     bool m_scissorEnabled;
554     GC3Dfloat m_clearDepth;
555     GC3Dint m_clearStencil;
556     GC3Dboolean m_colorMask[4];
557     GC3Dboolean m_depthMask;
558
559     bool m_stencilEnabled;
560     GC3Duint m_stencilMask, m_stencilMaskBack;
561     GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
562     GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
563
564     bool m_isGLES2Compliant;
565     bool m_isGLES2NPOTStrict;
566     bool m_isDepthStencilSupported;
567     bool m_isRobustnessEXTSupported;
568
569     bool m_synthesizedErrorsToConsole { true };
570     int m_numGLErrorsToConsoleAllowed;
571
572     bool m_preventBufferClearForInspector { false };
573
574     // A WebGLRenderingContext can be created in a state where it appears as
575     // a valid and active context, but will not execute any important operations
576     // until its load policy is completely resolved.
577     bool m_isPendingPolicyResolution { false };
578     bool m_hasRequestedPolicyResolution { false };
579     bool isContextLostOrPending();
580
581     // Enabled extension objects.
582     // FIXME: Move some of these to WebGLRenderingContext, the ones not needed for WebGL2
583     std::unique_ptr<EXTFragDepth> m_extFragDepth;
584     std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax;
585     std::unique_ptr<EXTsRGB> m_extsRGB;
586     std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
587     std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD;
588     std::unique_ptr<OESTextureFloat> m_oesTextureFloat;
589     std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear;
590     std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat;
591     std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
592     std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives;
593     std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject;
594     std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint;
595     std::unique_ptr<WebGLLoseContext> m_webglLoseContext;
596     std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
597     std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders;
598     std::unique_ptr<WebGLCompressedTextureASTC> m_webglCompressedTextureASTC;
599     std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
600     std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
601     std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
602     std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture;
603     std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers;
604     std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays;
605
606     // Helpers for getParameter and other similar functions.
607     bool getBooleanParameter(GC3Denum);
608     Vector<bool> getBooleanArrayParameter(GC3Denum);
609     float getFloatParameter(GC3Denum);
610     int getIntParameter(GC3Denum);
611     unsigned getUnsignedIntParameter(GC3Denum);
612     long long getInt64Parameter(GC3Denum);
613     RefPtr<Float32Array> getWebGLFloatArrayParameter(GC3Denum);
614     RefPtr<Int32Array> getWebGLIntArrayParameter(GC3Denum);
615
616     // Clear the backbuffer if it was composited since the last operation.
617     // clearMask is set to the bitfield of any clear that would happen anyway at this time
618     // and the function returns true if that clear is now unnecessary.
619     bool clearIfComposited(GC3Dbitfield clearMask = 0);
620
621     // Helper to restore state that clearing the framebuffer may destroy.
622     void restoreStateAfterClear();
623
624     void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels);
625     void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
626     void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels);
627     void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha);
628
629     bool checkTextureCompleteness(const char*, bool);
630
631     void createFallbackBlackTextures1x1();
632
633     // Helper function for copyTex{Sub}Image, check whether the internalformat
634     // and the color buffer format of the current bound framebuffer combination
635     // is valid.
636     bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
637                                                         GC3Denum colorBufferFormat);
638
639     // Helper function to get the bound framebuffer's color buffer format.
640     GC3Denum getBoundFramebufferColorFormat();
641
642     // Helper function to get the bound framebuffer's width.
643     int getBoundFramebufferWidth();
644
645     // Helper function to get the bound framebuffer's height.
646     int getBoundFramebufferHeight();
647
648     // Helper function to verify limits on the length of uniform and attribute locations.
649     bool validateLocationLength(const char* functionName, const String&);
650
651     // Helper function to check if size is non-negative.
652     // Generate GL error and return false for negative inputs; otherwise, return true.
653     bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
654
655     // Helper function to check if all characters in the string belong to the
656     // ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
657     bool validateString(const char* functionName, const String&);
658
659     // Helper function to check target and texture bound to the target.
660     // Generate GL errors and return 0 if target is invalid or texture bound is
661     // null.  Otherwise, return the texture bound to the target.
662     RefPtr<WebGLTexture> validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
663
664     // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
665     // Generates GL error and returns false if parameters are invalid.
666     bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level);
667
668     // Helper function to check input level for functions {copy}Tex{Sub}Image.
669     // Generates GL error and returns false if level is invalid.
670     bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
671
672     enum TexFuncValidationFunctionType {
673         TexImage,
674         TexSubImage,
675         CopyTexImage
676     };
677
678     enum TexFuncValidationSourceType {
679         SourceArrayBufferView,
680         SourceImageBitmap,
681         SourceImageData,
682         SourceHTMLImageElement,
683         SourceHTMLCanvasElement,
684 #if ENABLE(VIDEO)
685         SourceHTMLVideoElement,
686 #endif
687     };
688
689     // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
690     // Otherwise, it would return quickly without doing other work.
691     bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
692         GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
693
694     // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
695     // Generates GL error and returns false if parameters are invalid.
696     bool validateTexFuncParameters(const char* functionName,
697         TexFuncValidationFunctionType,
698         GC3Denum target, GC3Dint level,
699         GC3Denum internalformat,
700         GC3Dsizei width, GC3Dsizei height, GC3Dint border,
701         GC3Denum format, GC3Denum type);
702
703     enum NullDisposition {
704         NullAllowed,
705         NullNotAllowed
706     };
707
708     // Helper function to validate that the given ArrayBufferView
709     // is of the correct type and contains enough data for the texImage call.
710     // Generates GL error and returns false if parameters are invalid.
711     bool validateTexFuncData(const char* functionName, GC3Dint level,
712         GC3Dsizei width, GC3Dsizei height,
713         GC3Denum internalformat, GC3Denum format, GC3Denum type,
714         ArrayBufferView* pixels,
715         NullDisposition);
716
717     // Helper function to validate a given texture format is settable as in
718     // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
719     // copyTexSubImage2D.
720     // Generates GL error and returns false if the format is not settable.
721     bool validateSettableTexInternalFormat(const char* functionName, GC3Denum format);
722
723     // Helper function to validate compressed texture data is correct size
724     // for the given format and dimensions.
725     bool validateCompressedTexFuncData(const char* functionName, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& pixels);
726
727     // Helper function for validating compressed texture formats.
728     bool validateCompressedTexFormat(GC3Denum format);
729
730     // Helper function to validate compressed texture dimensions are valid for
731     // the given format.
732     bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
733
734     // Helper function to validate compressed texture dimensions are valid for
735     // the given format.
736     bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
737                                             GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
738
739     // Helper function to validate mode for draw{Arrays/Elements}.
740     bool validateDrawMode(const char* functionName, GC3Denum);
741
742     // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
743     bool validateStencilSettings(const char* functionName);
744
745     // Helper function to validate stencil func.
746     bool validateStencilFunc(const char* functionName, GC3Denum);
747
748     // Helper function for texParameterf and texParameteri.
749     void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
750
751     // Helper function to print errors and warnings to console.
752     void printToConsole(MessageLevel, const String&);
753
754     // Helper function to validate input parameters for framebuffer functions.
755     // Generate GL error if parameters are illegal.
756     virtual bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) = 0;
757
758     // Helper function to validate blend equation mode.
759     virtual bool validateBlendEquation(const char* functionName, GC3Denum) = 0;
760
761     // Helper function to validate blend func factors.
762     bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
763
764     // Helper function to validate a GL capability.
765     virtual bool validateCapability(const char* functionName, GC3Denum) = 0;
766
767     // Helper function to validate input parameters for uniform functions.
768     bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Float32List&, GC3Dsizei mod);
769     bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Int32List&, GC3Dsizei mod);
770     bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
771     bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, const Float32List&, GC3Dsizei mod);
772     bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, const void*, GC3Dsizei, GC3Dsizei mod);
773
774     // Helper function to validate parameters for bufferData.
775     // Return the current bound buffer to target, or 0 if parameters are invalid.
776     WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
777
778     // Helper function for tex{Sub}Image2D to make sure image is ready.
779     ExceptionOr<bool> validateHTMLImageElement(const char* functionName, HTMLImageElement*);
780     ExceptionOr<bool> validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*);
781 #if ENABLE(VIDEO)
782     ExceptionOr<bool> validateHTMLVideoElement(const char* functionName, HTMLVideoElement*);
783 #endif
784
785     // Helper functions for vertexAttribNf{v}.
786     void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
787     void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32List&&, GC3Dsizei expectedSize);
788
789     // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
790     // Return false if caller should return without further processing.
791     bool deleteObject(WebGLObject*);
792
793     // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
794     // If the object has already been deleted, set deleted to true upon return.
795     // Return false if caller should return without further processing.
796     bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
797
798     // Helpers for simulating vertexAttrib0.
799     void initVertexAttrib0();
800     std::optional<bool> simulateVertexAttrib0(GC3Duint numVertex);
801     bool validateSimulatedVertexAttrib0(GC3Duint numVertex);
802     void restoreStatesAfterVertexAttrib0Simulation();
803
804     void dispatchContextLostEvent();
805     // Helper for restoration after context lost.
806     void maybeRestoreContext();
807
808     // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message to the JavaScript console.
809     enum ConsoleDisplayPreference { DisplayInConsole, DontDisplayInConsole };
810     void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
811
812     String ensureNotNull(const String&) const;
813
814     // Enable or disable stencil test based on user setting and whether the current FBO has a stencil buffer.
815     void applyStencilTest();
816
817     // Helper for enabling or disabling a capability.
818     void enableOrDisable(GC3Denum capability, bool enable);
819
820     // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
821     IntSize clampedCanvasSize();
822
823     virtual GC3Dint getMaxDrawBuffers() = 0;
824     virtual GC3Dint getMaxColorAttachments() = 0;
825
826     void setBackDrawBuffer(GC3Denum);
827
828     void restoreCurrentFramebuffer();
829     void restoreCurrentTexture2D();
830
831     // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
832     bool supportsDrawBuffers();
833
834     HTMLCanvasElement* htmlCanvas();
835     OffscreenCanvas* offscreenCanvas();
836
837     template <typename T> inline std::optional<T> checkedAddAndMultiply(T value, T add, T multiply);
838     template <typename T> unsigned getMaxIndex(const RefPtr<JSC::ArrayBuffer> elementArrayBuffer, GC3Dintptr uoffset, GC3Dsizei n);
839
840 private:
841     bool validateArrayBufferType(const char* functionName, GC3Denum type, std::optional<JSC::TypedArrayType>);
842     void registerWithWebGLStateTracker();
843     void checkForContextLossHandling();
844
845     void activityStateDidChange(OptionSet<ActivityState::Flag> oldActivityState, OptionSet<ActivityState::Flag> newActivityState) override;
846
847     WebGLStateTracker::Token m_trackerToken;
848     Timer m_checkForContextLossHandlingTimer;
849 };
850
851 template <typename T>
852 inline std::optional<T> WebGLRenderingContextBase::checkedAddAndMultiply(T value, T add, T multiply)
853 {
854     Checked<T, RecordOverflow> checkedResult = Checked<T>(value);
855     checkedResult += Checked<T>(add);
856     checkedResult *= Checked<T>(multiply);
857     if (checkedResult.hasOverflowed())
858         return std::nullopt;
859
860     return checkedResult.unsafeGet();
861 }
862
863 template<typename T>
864 inline unsigned WebGLRenderingContextBase::getMaxIndex(const RefPtr<JSC::ArrayBuffer> elementArrayBuffer, GC3Dintptr uoffset, GC3Dsizei n)
865 {
866     unsigned maxIndex = 0;
867     T restartIndex = 0;
868
869 #if ENABLE(WEBGL2)
870     // WebGL 2 spec enforces that GL_PRIMITIVE_RESTART_FIXED_INDEX is always enabled, so ignore the restart index.
871     if (isWebGL2())
872         restartIndex = std::numeric_limits<T>::max();
873 #endif
874
875     // Make uoffset an element offset.
876     uoffset /= sizeof(T);
877     const T* p = static_cast<const T*>(elementArrayBuffer->data()) + uoffset;
878     while (n-- > 0) {
879         if (*p != restartIndex && *p > maxIndex)
880             maxIndex = *p;
881         ++p;
882     }
883
884     return maxIndex;
885 }
886
887 } // namespace WebCore
888
889 SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGLRenderingContextBase, isWebGL())
890
891 #endif