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