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