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