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