2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "ActivityStateChangeObserver.h"
31 #include "ExceptionOr.h"
32 #include "GPUBasedCanvasRenderingContext.h"
33 #include "GraphicsContext3D.h"
34 #include "ImageBuffer.h"
35 #include "SuspendableTimer.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>
51 #include "WebGLVertexArrayObject.h"
56 class ANGLEInstancedArrays;
58 class EXTTextureFilterAnisotropic;
59 class EXTShaderTextureLOD;
62 class HTMLImageElement;
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;
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;
89 class WebGLLoseContext;
92 class WebGLSharedObject;
93 class WebGLShaderPrecisionFormat;
94 class WebGLUniformLocation;
97 class HTMLVideoElement;
100 #if ENABLE(OFFSCREEN_CANVAS)
101 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>, RefPtr<OffscreenCanvas>>;
103 using WebGLCanvas = WTF::Variant<RefPtr<HTMLCanvasElement>>;
106 class WebGLRenderingContextBase : public GraphicsContext3D::Client, public GPUBasedCanvasRenderingContext, private ActivityStateChangeObserver {
107 WTF_MAKE_ISO_ALLOCATED(WebGLRenderingContextBase);
109 static std::unique_ptr<WebGLRenderingContextBase> create(CanvasBase&, WebGLContextAttributes&, const String&);
110 virtual ~WebGLRenderingContextBase();
112 WebGLCanvas canvas();
114 int drawingBufferWidth() const;
115 int drawingBufferHeight() const;
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);
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>&&);
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*);
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);
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);
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();
156 void cullFace(GC3Denum mode);
158 void deleteBuffer(WebGLBuffer*);
159 void deleteFramebuffer(WebGLFramebuffer*);
160 void deleteProgram(WebGLProgram*);
161 void deleteRenderbuffer(WebGLRenderbuffer*);
162 void deleteShader(WebGLShader*);
163 void deleteTexture(WebGLTexture*);
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);
174 void enable(GC3Denum cap);
175 void enableVertexAttribArray(GC3Duint index);
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);
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();
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);
207 bool extensionIsEnabled(const String&);
209 bool isPreservingDrawingBuffer() const { return m_attributes.preserveDrawingBuffer; }
210 void setPreserveDrawingBuffer(bool value) { m_attributes.preserveDrawingBuffer = value; }
212 bool preventBufferClearForInspector() const { return m_preventBufferClearForInspector; }
213 void setPreventBufferClearForInspector(bool value) { m_preventBufferClearForInspector = value; }
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*);
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);
243 void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&);
246 using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>;
248 using TexImageSource = WTF::Variant<RefPtr<ImageBitmap>, RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>;
251 ExceptionOr<void> texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Optional<TexImageSource>);
253 void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
254 void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
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>&&);
259 template <class TypedArray, class DataType>
262 using VariantType = Variant<RefPtr<TypedArray>, Vector<DataType>>;
264 TypedList(VariantType&& variant)
265 : m_variant(WTFMove(variant))
269 const DataType* data() const
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(); }
277 GC3Dsizei length() const
279 return WTF::switchOn(m_variant,
280 [] (const RefPtr<TypedArray>& typedArray) -> GC3Dsizei { return typedArray->length(); },
281 [] (const Vector<DataType>& vector) -> GC3Dsizei { return vector.size(); }
286 VariantType m_variant;
289 using Float32List = TypedList<Float32Array, float>;
290 using Int32List = TypedList<Int32Array, int>;
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);
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);
302 void uniform1fv(const WebGLUniformLocation*, Float32List&&);
303 void uniform2fv(const WebGLUniformLocation*, Float32List&&);
304 void uniform3fv(const WebGLUniformLocation*, Float32List&&);
305 void uniform4fv(const WebGLUniformLocation*, Float32List&&);
307 void uniform1iv(const WebGLUniformLocation*, Int32List&&);
308 void uniform2iv(const WebGLUniformLocation*, Int32List&&);
309 void uniform3iv(const WebGLUniformLocation*, Int32List&&);
310 void uniform4iv(const WebGLUniformLocation*, Int32List&&);
312 void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
313 void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
314 void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&);
316 void useProgram(WebGLProgram*);
317 void validateProgram(WebGLProgram*);
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);
324 void vertexAttrib1fv(GC3Duint index, Float32List&&);
325 void vertexAttrib2fv(GC3Duint index, Float32List&&);
326 void vertexAttrib3fv(GC3Duint index, Float32List&&);
327 void vertexAttrib4fv(GC3Duint index, Float32List&&);
329 void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
330 GC3Dsizei stride, long long offset);
332 void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
334 // WEBKIT_lose_context support
335 enum LostContextMode {
336 // Lost context occurred at the graphics system level.
339 // Lost context provoked by WEBKIT_lose_context.
342 void forceLostContext(LostContextMode);
343 void forceRestoreContext();
344 void loseContextImpl(LostContextMode);
345 WEBCORE_EXPORT void simulateContextChanged();
347 GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
348 WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
349 PlatformLayer* platformLayer() const override;
351 void reshape(int width, int height) override;
353 void markLayerComposited() final;
354 void paintRenderingResultsToCanvas() override;
355 RefPtr<ImageData> paintRenderingResultsToImageData();
357 void removeSharedObject(WebGLSharedObject&);
358 void removeContextObject(WebGLContextObject&);
360 unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; }
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);
367 // Used for testing only, from Internals.
368 WEBCORE_EXPORT void setFailNextGPUStatusCheck();
370 // GraphicsContext3D::Client
371 void didComposite() override;
372 void forceContextLost() override;
373 void recycleContext() override;
374 void dispatchContextChangedNotification() override;
377 bool hasPendingActivity() const final;
380 WebGLRenderingContextBase(CanvasBase&, WebGLContextAttributes);
381 WebGLRenderingContextBase(CanvasBase&, Ref<GraphicsContext3D>&&, WebGLContextAttributes);
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;
399 virtual void initializeNewContext();
400 virtual void initializeVertexArrayObjects() = 0;
404 void stop() override;
405 const char* activeDOMObjectName() const override;
406 void suspend(ReasonForSuspension) override;
407 void resume() override;
409 void addSharedObject(WebGLSharedObject&);
410 void addContextObject(WebGLContextObject&);
411 void detachAndRemoveAllObjects();
413 void destroyGraphicsContext3D();
414 void markContextChanged();
415 void markContextChangedAndNotifyCanvasObserver();
417 void addActivityStateChangeObserverIfNecessary();
418 void removeActivityStateChangeObserver();
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; }
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);
431 // Basic validation of count and offset against number of elements in element array buffer
432 bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset);
434 // Conservative but quick index validation
435 virtual bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) = 0;
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);
441 bool validateWebGLObject(const char*, WebGLObject*);
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);
447 // Adds a compressed texture format.
448 void addCompressedTextureFormat(GC3Denum);
450 RefPtr<Image> drawImageIntoBuffer(Image&, int width, int height, int deviceScaleFactor);
453 RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy);
456 WebGLTexture::TextureExtensionFlag textureExtensionFlags() const;
458 bool enableSupportedExtension(ASCIILiteral extensionNameLiteral);
460 RefPtr<GraphicsContext3D> m_context;
461 RefPtr<WebGLContextGroup> m_contextGroup;
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;
474 bool m_markedCanvasDirty;
475 HashSet<WebGLContextObject*> m_contextObjects;
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;
486 RefPtr<WebGLVertexArrayObjectBase> m_defaultVertexArrayObject;
487 RefPtr<WebGLVertexArrayObjectBase> m_boundVertexArrayObject;
489 void setBoundVertexArrayObject(WebGLVertexArrayObjectBase* arrayObject)
491 m_boundVertexArrayObject = arrayObject ? arrayObject : m_defaultVertexArrayObject;
494 class VertexAttribValue {
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 };
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;
527 Vector<TextureUnitState> m_textureUnits;
528 HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_unrenderableTextureUnits;
530 unsigned long m_activeTextureUnit;
532 RefPtr<WebGLTexture> m_blackTexture2D;
533 RefPtr<WebGLTexture> m_blackTextureCubeMap;
535 Vector<GC3Denum> m_compressedTextureFormats;
537 // Fixed-size cache of reusable image buffers for video texImage2D calls.
538 class LRUImageBufferCache {
540 LRUImageBufferCache(int capacity);
541 // The pointer returned is owned by the image buffer map.
542 ImageBuffer* imageBuffer(const IntSize& size);
544 void bubbleToFront(size_t idx);
545 Vector<std::unique_ptr<ImageBuffer>> m_buffers;
547 LRUImageBufferCache m_generatedImageCache { 0 };
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;
556 GC3Dint m_maxDrawBuffers;
557 GC3Dint m_maxColorAttachments;
558 GC3Denum m_backDrawBuffer;
559 bool m_drawBuffersWebGLRequirementsChecked;
560 bool m_drawBuffersSupported;
562 GC3Dint m_packAlignment;
563 GC3Dint m_unpackAlignment;
565 bool m_unpackPremultiplyAlpha;
566 GC3Denum m_unpackColorspaceConversion;
567 bool m_contextLost { false };
568 LostContextMode m_contextLostMode { SyntheticLostContext };
569 WebGLContextAttributes m_attributes;
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;
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;
584 bool m_isGLES2Compliant;
585 bool m_isGLES2NPOTStrict;
586 bool m_isDepthStencilSupported;
587 bool m_isRobustnessEXTSupported;
589 bool m_synthesizedErrorsToConsole { true };
590 int m_numGLErrorsToConsoleAllowed;
592 bool m_preventBufferClearForInspector { false };
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();
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;
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);
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);
643 // Helper to restore state that clearing the framebuffer may destroy.
644 void restoreStateAfterClear();
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);
651 bool checkTextureCompleteness(const char*, bool);
653 void createFallbackBlackTextures1x1();
655 // Helper function for copyTex{Sub}Image, check whether the internalformat
656 // and the color buffer format of the current bound framebuffer combination
658 bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
659 GC3Denum colorBufferFormat);
661 // Helper function to get the bound framebuffer's color buffer format.
662 GC3Denum getBoundFramebufferColorFormat();
664 // Helper function to get the bound framebuffer's width.
665 int getBoundFramebufferWidth();
667 // Helper function to get the bound framebuffer's height.
668 int getBoundFramebufferHeight();
670 // Helper function to verify limits on the length of uniform and attribute locations.
671 bool validateLocationLength(const char* functionName, const String&);
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);
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&);
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);
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);
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);
694 enum TexFuncValidationFunctionType {
700 enum TexFuncValidationSourceType {
701 SourceArrayBufferView,
704 SourceHTMLImageElement,
705 SourceHTMLCanvasElement,
707 SourceHTMLVideoElement,
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);
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);
725 enum NullDisposition {
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,
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);
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);
749 // Helper function for validating compressed texture formats.
750 bool validateCompressedTexFormat(GC3Denum format);
752 // Helper function to validate compressed texture dimensions are valid for
754 bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
756 // Helper function to validate compressed texture dimensions are valid for
758 bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
759 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
761 // Helper function to validate mode for draw{Arrays/Elements}.
762 bool validateDrawMode(const char* functionName, GC3Denum);
764 // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
765 bool validateStencilSettings(const char* functionName);
767 // Helper function to validate stencil func.
768 bool validateStencilFunc(const char* functionName, GC3Denum);
770 // Helper function for texParameterf and texParameteri.
771 void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
773 // Helper function to print errors and warnings to console.
774 void printToConsole(MessageLevel, const String&);
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;
780 // Helper function to validate blend equation mode.
781 virtual bool validateBlendEquation(const char* functionName, GC3Denum) = 0;
783 // Helper function to validate blend func factors.
784 bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
786 // Helper function to validate a GL capability.
787 virtual bool validateCapability(const char* functionName, GC3Denum) = 0;
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);
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);
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*);
804 ExceptionOr<bool> validateHTMLVideoElement(const char* functionName, HTMLVideoElement*);
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);
811 // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
812 // Return false if caller should return without further processing.
813 bool deleteObject(WebGLObject*);
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);
820 // Helpers for simulating vertexAttrib0.
821 void initVertexAttrib0();
822 Optional<bool> simulateVertexAttrib0(GC3Duint numVertex);
823 bool validateSimulatedVertexAttrib0(GC3Duint numVertex);
824 void restoreStatesAfterVertexAttrib0Simulation();
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);
830 String ensureNotNull(const String&) const;
832 // Enable or disable stencil test based on user setting and whether the current FBO has a stencil buffer.
833 void applyStencilTest();
835 // Helper for enabling or disabling a capability.
836 void enableOrDisable(GC3Denum capability, bool enable);
838 // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
839 IntSize clampedCanvasSize();
841 virtual GC3Dint getMaxDrawBuffers() = 0;
842 virtual GC3Dint getMaxColorAttachments() = 0;
844 void setBackDrawBuffer(GC3Denum);
846 void restoreCurrentFramebuffer();
847 void restoreCurrentTexture2D();
849 // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements.
850 bool supportsDrawBuffers();
852 #if ENABLE(OFFSCREEN_CANVAS)
853 OffscreenCanvas* offscreenCanvas();
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);
860 void dispatchContextLostEvent();
861 void dispatchContextChangedEvent();
862 // Helper for restoration after context lost.
863 void maybeRestoreContext();
865 bool validateArrayBufferType(const char* functionName, GC3Denum type, Optional<JSC::TypedArrayType>);
866 void registerWithWebGLStateTracker();
867 void checkForContextLossHandling();
869 void activityStateDidChange(OptionSet<ActivityState::Flag> oldActivityState, OptionSet<ActivityState::Flag> newActivityState) override;
871 WebGLStateTracker::Token m_trackerToken;
872 Timer m_checkForContextLossHandlingTimer;
873 bool m_isSuspended { false };
876 template <typename T>
877 inline Optional<T> WebGLRenderingContextBase::checkedAddAndMultiply(T value, T add, T multiply)
879 Checked<T, RecordOverflow> checkedResult = Checked<T>(value);
880 checkedResult += Checked<T>(add);
881 checkedResult *= Checked<T>(multiply);
882 if (checkedResult.hasOverflowed())
885 return checkedResult.unsafeGet();
889 inline unsigned WebGLRenderingContextBase::getMaxIndex(const RefPtr<JSC::ArrayBuffer> elementArrayBuffer, GC3Dintptr uoffset, GC3Dsizei n)
891 unsigned maxIndex = 0;
895 // WebGL 2 spec enforces that GL_PRIMITIVE_RESTART_FIXED_INDEX is always enabled, so ignore the restart index.
897 restartIndex = std::numeric_limits<T>::max();
900 // Make uoffset an element offset.
901 uoffset /= sizeof(T);
902 const T* p = static_cast<const T*>(elementArrayBuffer->data()) + uoffset;
904 if (*p != restartIndex && *p > maxIndex)
912 } // namespace WebCore
914 SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGLRenderingContextBase, isWebGL())