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