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