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