1/*
2 * Copyright (C) 2009 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 COMPUTER, 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 COMPUTER, 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#ifndef WebGLRenderingContext_h
27#define WebGLRenderingContext_h
28
29#include "core/dom/ActiveDOMObject.h"
30#include "core/html/canvas/CanvasRenderingContext.h"
31#include "core/html/canvas/WebGLGetInfo.h"
32#include "core/page/Page.h"
33#include "platform/Timer.h"
34#include "platform/graphics/GraphicsContext3D.h"
35#include "platform/graphics/ImageBuffer.h"
36
37#include "wtf/Float32Array.h"
38#include "wtf/Int32Array.h"
39#include "wtf/OwnPtr.h"
40#include "wtf/text/WTFString.h"
41
42namespace blink { class WebLayer; }
43
44namespace WebCore {
45
46class ANGLEInstancedArrays;
47class DrawingBuffer;
48class EXTFragDepth;
49class EXTTextureFilterAnisotropic;
50class ExceptionState;
51class HTMLImageElement;
52class HTMLVideoElement;
53class ImageBuffer;
54class ImageData;
55class IntSize;
56class OESElementIndexUint;
57class OESStandardDerivatives;
58class OESTextureFloat;
59class OESTextureFloatLinear;
60class OESTextureHalfFloat;
61class OESTextureHalfFloatLinear;
62class OESVertexArrayObject;
63class WebGLActiveInfo;
64class WebGLBuffer;
65class WebGLCompressedTextureATC;
66class WebGLCompressedTexturePVRTC;
67class WebGLCompressedTextureS3TC;
68class WebGLContextAttributes;
69class WebGLContextGroup;
70class WebGLContextObject;
71class WebGLDebugRendererInfo;
72class WebGLDebugShaders;
73class WebGLDepthTexture;
74class WebGLDrawBuffers;
75class WebGLExtension;
76class WebGLFramebuffer;
77class WebGLLoseContext;
78class WebGLObject;
79class WebGLProgram;
80class WebGLRenderbuffer;
81class WebGLShader;
82class WebGLShaderPrecisionFormat;
83class WebGLSharedObject;
84class WebGLTexture;
85class WebGLUniformLocation;
86class WebGLVertexArrayObjectOES;
87
88class WebGLRenderingContext : public CanvasRenderingContext, public ActiveDOMObject, private Page::MultisamplingChangedObserver {
89public:
90    static PassOwnPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*);
91    virtual ~WebGLRenderingContext();
92
93    virtual bool is3d() const { return true; }
94    virtual bool isAccelerated() const { return true; }
95
96    int drawingBufferWidth() const;
97    int drawingBufferHeight() const;
98
99    void activeTexture(GC3Denum texture);
100    void attachShader(WebGLProgram*, WebGLShader*);
101    void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name);
102    void bindBuffer(GC3Denum target, WebGLBuffer*);
103    void bindFramebuffer(GC3Denum target, WebGLFramebuffer*);
104    void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*);
105    void bindTexture(GC3Denum target, WebGLTexture*);
106    void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
107    void blendEquation(GC3Denum mode);
108    void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha);
109    void blendFunc(GC3Denum sfactor, GC3Denum dfactor);
110    void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha);
111
112    void bufferData(GC3Denum target, long long size, GC3Denum usage);
113    void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage);
114    void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage);
115    void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data);
116    void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data);
117
118    GC3Denum checkFramebufferStatus(GC3Denum target);
119    void clear(GC3Dbitfield mask);
120    void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha);
121    void clearDepth(GC3Dfloat);
122    void clearStencil(GC3Dint);
123    void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha);
124    void compileShader(WebGLShader*);
125
126    void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
127                              GC3Dsizei height, GC3Dint border, ArrayBufferView* data);
128    void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
129                                 GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data);
130
131    void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border);
132    void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
133
134    PassRefPtr<WebGLBuffer> createBuffer();
135    PassRefPtr<WebGLFramebuffer> createFramebuffer();
136    PassRefPtr<WebGLProgram> createProgram();
137    PassRefPtr<WebGLRenderbuffer> createRenderbuffer();
138    PassRefPtr<WebGLShader> createShader(GC3Denum type);
139    PassRefPtr<WebGLTexture> createTexture();
140
141    void cullFace(GC3Denum mode);
142
143    void deleteBuffer(WebGLBuffer*);
144    void deleteFramebuffer(WebGLFramebuffer*);
145    void deleteProgram(WebGLProgram*);
146    void deleteRenderbuffer(WebGLRenderbuffer*);
147    void deleteShader(WebGLShader*);
148    void deleteTexture(WebGLTexture*);
149
150    void depthFunc(GC3Denum);
151    void depthMask(GC3Dboolean);
152    void depthRange(GC3Dfloat zNear, GC3Dfloat zFar);
153    void detachShader(WebGLProgram*, WebGLShader*);
154    void disable(GC3Denum cap);
155    void disableVertexAttribArray(GC3Duint index);
156    void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count);
157    void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset);
158
159    void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount);
160    void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount);
161
162    void enable(GC3Denum cap);
163    void enableVertexAttribArray(GC3Duint index);
164    void finish();
165    void flush();
166    void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*);
167    void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level);
168    void frontFace(GC3Denum mode);
169    void generateMipmap(GC3Denum target);
170
171    PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index);
172    PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index);
173    bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader> >&);
174    GC3Dint getAttribLocation(WebGLProgram*, const String& name);
175    WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname);
176    PassRefPtr<WebGLContextAttributes> getContextAttributes();
177    GC3Denum getError();
178    PassRefPtr<WebGLExtension> getExtension(const String& name);
179    WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname);
180    WebGLGetInfo getParameter(GC3Denum pname);
181    WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname);
182    String getProgramInfoLog(WebGLProgram*);
183    WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname);
184    WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname);
185    String getShaderInfoLog(WebGLShader*);
186    PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType);
187    String getShaderSource(WebGLShader*);
188    Vector<String> getSupportedExtensions();
189    WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname);
190    WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*);
191    PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&);
192    WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname);
193    long long getVertexAttribOffset(GC3Duint index, GC3Denum pname);
194
195    void hint(GC3Denum target, GC3Denum mode);
196    GC3Dboolean isBuffer(WebGLBuffer*);
197    bool isContextLost();
198    GC3Dboolean isEnabled(GC3Denum cap);
199    GC3Dboolean isFramebuffer(WebGLFramebuffer*);
200    GC3Dboolean isProgram(WebGLProgram*);
201    GC3Dboolean isRenderbuffer(WebGLRenderbuffer*);
202    GC3Dboolean isShader(WebGLShader*);
203    GC3Dboolean isTexture(WebGLTexture*);
204
205    void lineWidth(GC3Dfloat);
206    void linkProgram(WebGLProgram*);
207    void pixelStorei(GC3Denum pname, GC3Dint param);
208    void polygonOffset(GC3Dfloat factor, GC3Dfloat units);
209    void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels);
210    void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height);
211    void sampleCoverage(GC3Dfloat value, GC3Dboolean invert);
212    void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
213    void shaderSource(WebGLShader*, const String&);
214    void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask);
215    void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask);
216    void stencilMask(GC3Duint);
217    void stencilMaskSeparate(GC3Denum face, GC3Duint mask);
218    void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
219    void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass);
220
221    void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
222        GC3Dsizei width, GC3Dsizei height, GC3Dint border,
223        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionState&);
224    void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
225        GC3Denum format, GC3Denum type, ImageData*, ExceptionState&);
226    void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
227        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&);
228    void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
229        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&);
230    void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
231        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&);
232
233    void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param);
234    void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param);
235
236    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
237        GC3Dsizei width, GC3Dsizei height,
238        GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionState&);
239    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
240        GC3Denum format, GC3Denum type, ImageData*, ExceptionState&);
241    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
242        GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&);
243    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
244        GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&);
245    void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
246        GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&);
247
248    void uniform1f(const WebGLUniformLocation*, GC3Dfloat x);
249    void uniform1fv(const WebGLUniformLocation*, Float32Array* v);
250    void uniform1fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei);
251    void uniform1i(const WebGLUniformLocation*, GC3Dint x);
252    void uniform1iv(const WebGLUniformLocation*, Int32Array* v);
253    void uniform1iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei);
254    void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y);
255    void uniform2fv(const WebGLUniformLocation*, Float32Array* v);
256    void uniform2fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei);
257    void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y);
258    void uniform2iv(const WebGLUniformLocation*, Int32Array* v);
259    void uniform2iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei);
260    void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
261    void uniform3fv(const WebGLUniformLocation*, Float32Array* v);
262    void uniform3fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei);
263    void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z);
264    void uniform3iv(const WebGLUniformLocation*, Int32Array* v);
265    void uniform3iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei);
266    void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
267    void uniform4fv(const WebGLUniformLocation*, Float32Array* v);
268    void uniform4fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei);
269    void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w);
270    void uniform4iv(const WebGLUniformLocation*, Int32Array* v);
271    void uniform4iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei);
272    void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value);
273    void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei);
274    void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value);
275    void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei);
276    void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value);
277    void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei);
278
279    void useProgram(WebGLProgram*);
280    void validateProgram(WebGLProgram*);
281
282    void vertexAttrib1f(GC3Duint index, GC3Dfloat x);
283    void vertexAttrib1fv(GC3Duint index, Float32Array* values);
284    void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei);
285    void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y);
286    void vertexAttrib2fv(GC3Duint index, Float32Array* values);
287    void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei);
288    void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z);
289    void vertexAttrib3fv(GC3Duint index, Float32Array* values);
290    void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei);
291    void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w);
292    void vertexAttrib4fv(GC3Duint index, Float32Array* values);
293    void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei);
294    void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized,
295        GC3Dsizei stride, long long offset);
296
297    void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor);
298
299    void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height);
300
301    // WEBKIT_lose_context support
302    enum LostContextMode {
303        // Lost context occurred at the graphics system level.
304        RealLostContext,
305
306        // Lost context provoked by WEBKIT_lose_context.
307        SyntheticLostContext,
308
309        // A synthetic lost context that should attempt to recover automatically
310        AutoRecoverSyntheticLostContext
311    };
312    void forceLostContext(LostContextMode);
313    void forceRestoreContext();
314    void loseContextImpl(LostContextMode);
315
316    GraphicsContext3D* graphicsContext3D() const { return m_context.get(); }
317    WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); }
318    virtual blink::WebLayer* platformLayer() const;
319
320    void reshape(int width, int height);
321
322    void markLayerComposited();
323    virtual void paintRenderingResultsToCanvas();
324    virtual PassRefPtr<ImageData> paintRenderingResultsToImageData();
325
326    void removeSharedObject(WebGLSharedObject*);
327    void removeContextObject(WebGLContextObject*);
328
329    unsigned maxVertexAttribs() const { return m_maxVertexAttribs; }
330
331    // ActiveDOMObject notifications
332    virtual bool hasPendingActivity() const;
333    virtual void stop();
334
335  private:
336    friend class WebGLDrawBuffers;
337    friend class WebGLFramebuffer;
338    friend class WebGLObject;
339    friend class OESVertexArrayObject;
340    friend class WebGLDebugShaders;
341    friend class WebGLCompressedTextureATC;
342    friend class WebGLCompressedTexturePVRTC;
343    friend class WebGLCompressedTextureS3TC;
344    friend class WebGLRenderingContextErrorMessageCallback;
345    friend class WebGLVertexArrayObjectOES;
346
347    WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes, GraphicsContext3D::Attributes);
348    void initializeNewContext();
349    void setupFlags();
350
351    void addSharedObject(WebGLSharedObject*);
352    void addContextObject(WebGLContextObject*);
353    void detachAndRemoveAllObjects();
354
355    void destroyGraphicsContext3D();
356    void markContextChanged();
357
358    // Query if the GL implementation is NPOT strict.
359    bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; }
360    // Query if depth_stencil buffer is supported.
361    bool isDepthStencilSupported() { return m_isDepthStencilSupported; }
362
363    // Helper to return the size in bytes of OpenGL data types
364    // like GL_FLOAT, GL_INT, etc.
365    unsigned int sizeInBytes(GC3Denum type);
366
367    // Check if each enabled vertex attribute is bound to a buffer.
368    bool validateRenderingState();
369
370    bool validateWebGLObject(const char*, WebGLObject*);
371
372    // Adds a compressed texture format.
373    void addCompressedTextureFormat(GC3Denum);
374    void removeAllCompressedTextureFormats();
375
376    PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height);
377
378    PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy);
379
380    WebGLRenderbuffer* ensureEmulatedStencilBuffer(GC3Denum target, WebGLRenderbuffer*);
381
382    RefPtr<GraphicsContext3D> m_context;
383    RefPtr<WebGLContextGroup> m_contextGroup;
384
385    // Structure for rendering to a DrawingBuffer, instead of directly
386    // to the back-buffer of m_context.
387    RefPtr<DrawingBuffer> m_drawingBuffer;
388
389    // Dispatches a context lost event once it is determined that one is needed.
390    // This is used both for synthetic and real context losses. For real ones, it's
391    // likely that there's no JavaScript on the stack, but that might be dependent
392    // on how exactly the platform discovers that the context was lost. For better
393    // portability we always defer the dispatch of the event.
394    Timer<WebGLRenderingContext> m_dispatchContextLostEventTimer;
395    bool m_restoreAllowed;
396    Timer<WebGLRenderingContext> m_restoreTimer;
397
398    bool m_needsUpdate;
399    bool m_markedCanvasDirty;
400    HashSet<WebGLContextObject*> m_contextObjects;
401
402    // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER
403    RefPtr<WebGLBuffer> m_boundArrayBuffer;
404
405    RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject;
406    RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject;
407    void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject)
408    {
409        if (arrayObject)
410            m_boundVertexArrayObject = arrayObject;
411        else
412            m_boundVertexArrayObject = m_defaultVertexArrayObject;
413    }
414
415    class VertexAttribValue {
416    public:
417        VertexAttribValue()
418        {
419            initValue();
420        }
421
422        void initValue()
423        {
424            value[0] = 0.0f;
425            value[1] = 0.0f;
426            value[2] = 0.0f;
427            value[3] = 1.0f;
428        }
429
430        GC3Dfloat value[4];
431    };
432    Vector<VertexAttribValue> m_vertexAttribValue;
433    unsigned m_maxVertexAttribs;
434    RefPtr<WebGLBuffer> m_vertexAttrib0Buffer;
435    long m_vertexAttrib0BufferSize;
436    GC3Dfloat m_vertexAttrib0BufferValue[4];
437    bool m_forceAttrib0BufferRefill;
438    bool m_vertexAttrib0UsedBefore;
439
440    RefPtr<WebGLProgram> m_currentProgram;
441    RefPtr<WebGLFramebuffer> m_framebufferBinding;
442    RefPtr<WebGLRenderbuffer> m_renderbufferBinding;
443    class TextureUnitState {
444    public:
445        RefPtr<WebGLTexture> m_texture2DBinding;
446        RefPtr<WebGLTexture> m_textureCubeMapBinding;
447    };
448    Vector<TextureUnitState> m_textureUnits;
449    unsigned long m_activeTextureUnit;
450
451    RefPtr<WebGLTexture> m_blackTexture2D;
452    RefPtr<WebGLTexture> m_blackTextureCubeMap;
453
454    Vector<GC3Denum> m_compressedTextureFormats;
455
456    // Fixed-size cache of reusable image buffers for video texImage2D calls.
457    class LRUImageBufferCache {
458    public:
459        LRUImageBufferCache(int capacity);
460        // The pointer returned is owned by the image buffer map.
461        ImageBuffer* imageBuffer(const IntSize& size);
462    private:
463        void bubbleToFront(int idx);
464        OwnPtr<OwnPtr<ImageBuffer>[]> m_buffers;
465        int m_capacity;
466    };
467    LRUImageBufferCache m_generatedImageCache;
468
469    GC3Dint m_maxTextureSize;
470    GC3Dint m_maxCubeMapTextureSize;
471    GC3Dint m_maxRenderbufferSize;
472    GC3Dint m_maxViewportDims[2];
473    GC3Dint m_maxTextureLevel;
474    GC3Dint m_maxCubeMapTextureLevel;
475
476    GC3Dint m_maxDrawBuffers;
477    GC3Dint m_maxColorAttachments;
478    GC3Denum m_backDrawBuffer;
479    bool m_drawBuffersWebGLRequirementsChecked;
480    bool m_drawBuffersSupported;
481
482    GC3Dint m_packAlignment;
483    GC3Dint m_unpackAlignment;
484    bool m_unpackFlipY;
485    bool m_unpackPremultiplyAlpha;
486    GC3Denum m_unpackColorspaceConversion;
487    bool m_contextLost;
488    LostContextMode m_contextLostMode;
489    GraphicsContext3D::Attributes m_attributes;
490    GraphicsContext3D::Attributes m_requestedAttributes;
491
492    bool m_layerCleared;
493    GC3Dfloat m_clearColor[4];
494    bool m_scissorEnabled;
495    GC3Dfloat m_clearDepth;
496    GC3Dint m_clearStencil;
497    GC3Dboolean m_colorMask[4];
498    GC3Dboolean m_depthMask;
499
500    bool m_stencilEnabled;
501    GC3Duint m_stencilMask, m_stencilMaskBack;
502    GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value.
503    GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack;
504
505    bool m_isGLES2NPOTStrict;
506    bool m_isDepthStencilSupported;
507
508    bool m_synthesizedErrorsToConsole;
509    int m_numGLErrorsToConsoleAllowed;
510
511    bool m_multisamplingAllowed;
512    bool m_multisamplingObserverRegistered;
513
514    GC3Duint m_onePlusMaxEnabledAttribIndex;
515    unsigned long m_onePlusMaxNonDefaultTextureUnit;
516
517    // Enabled extension objects.
518    RefPtr<ANGLEInstancedArrays> m_angleInstancedArrays;
519    RefPtr<EXTFragDepth> m_extFragDepth;
520    RefPtr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic;
521    RefPtr<OESTextureFloat> m_oesTextureFloat;
522    RefPtr<OESTextureFloatLinear> m_oesTextureFloatLinear;
523    RefPtr<OESTextureHalfFloat> m_oesTextureHalfFloat;
524    RefPtr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear;
525    RefPtr<OESStandardDerivatives> m_oesStandardDerivatives;
526    RefPtr<OESVertexArrayObject> m_oesVertexArrayObject;
527    RefPtr<OESElementIndexUint> m_oesElementIndexUint;
528    RefPtr<WebGLLoseContext> m_webglLoseContext;
529    RefPtr<WebGLDebugRendererInfo> m_webglDebugRendererInfo;
530    RefPtr<WebGLDebugShaders> m_webglDebugShaders;
531    RefPtr<WebGLDrawBuffers> m_webglDrawBuffers;
532    RefPtr<WebGLCompressedTextureATC> m_webglCompressedTextureATC;
533    RefPtr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC;
534    RefPtr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC;
535    RefPtr<WebGLDepthTexture> m_webglDepthTexture;
536
537    enum ExtensionFlags {
538        ApprovedExtension   = 0x00,
539        DraftExtension      = 0x01,
540        PrivilegedExtension = 0x02,
541        PrefixedExtension   = 0x04,
542        WebGLDebugRendererInfoExtension = 0x08,
543    };
544
545    class ExtensionTracker {
546    public:
547        ExtensionTracker(ExtensionFlags flags, const char* const* prefixes)
548            : m_privileged(flags & PrivilegedExtension)
549            , m_draft(flags & DraftExtension)
550            , m_prefixed(flags & PrefixedExtension)
551            , m_webglDebugRendererInfo(flags & WebGLDebugRendererInfoExtension)
552            , m_prefixes(prefixes)
553        {
554        }
555
556        virtual ~ExtensionTracker()
557        {
558        }
559
560        bool prefixed() const
561        {
562            return m_prefixed;
563        }
564
565        bool privileged() const
566        {
567            return m_privileged;
568        }
569
570        bool draft() const
571        {
572            return m_draft;
573        }
574
575        bool webglDebugRendererInfo() const
576        {
577            return m_webglDebugRendererInfo;
578        }
579
580        bool matchesNameWithPrefixes(const String&) const;
581
582        virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext*) const = 0;
583        virtual bool supported(WebGLRenderingContext*) const = 0;
584        virtual const char* extensionName() const = 0;
585        virtual void loseExtension() = 0;
586
587    private:
588        bool m_privileged;
589        bool m_draft;
590        bool m_prefixed;
591        bool m_webglDebugRendererInfo;
592        const char* const* m_prefixes;
593    };
594
595    template <typename T>
596    class TypedExtensionTracker : public ExtensionTracker {
597    public:
598        TypedExtensionTracker(RefPtr<T>& extensionField, ExtensionFlags flags, const char* const* prefixes)
599            : ExtensionTracker(flags, prefixes)
600            , m_extensionField(extensionField)
601        {
602        }
603
604        ~TypedExtensionTracker()
605        {
606            if (m_extensionField) {
607                m_extensionField->lose(true);
608                m_extensionField = 0;
609            }
610        }
611
612        virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext* context) const
613        {
614            if (!m_extensionField)
615                m_extensionField = T::create(context);
616
617            return m_extensionField;
618        }
619
620        virtual bool supported(WebGLRenderingContext* context) const
621        {
622            return T::supported(context);
623        }
624
625        virtual const char* extensionName() const
626        {
627            return T::extensionName();
628        }
629
630        virtual void loseExtension()
631        {
632            if (m_extensionField) {
633                m_extensionField->lose(false);
634                if (m_extensionField->isLost())
635                    m_extensionField = 0;
636            }
637        }
638
639    private:
640        RefPtr<T>& m_extensionField;
641    };
642
643    Vector<ExtensionTracker*> m_extensions;
644
645    template <typename T>
646    void registerExtension(RefPtr<T>& extensionPtr, ExtensionFlags flags = ApprovedExtension, const char* const* prefixes = 0)
647    {
648        m_extensions.append(new TypedExtensionTracker<T>(extensionPtr, flags, prefixes));
649    }
650
651    // Errors raised by synthesizeGLError() while the context is lost.
652    Vector<GC3Denum> lost_context_errors_;
653
654    // Helpers for getParameter and others
655    WebGLGetInfo getBooleanParameter(GC3Denum);
656    WebGLGetInfo getBooleanArrayParameter(GC3Denum);
657    WebGLGetInfo getFloatParameter(GC3Denum);
658    WebGLGetInfo getIntParameter(GC3Denum);
659    WebGLGetInfo getUnsignedIntParameter(GC3Denum);
660    WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum);
661    WebGLGetInfo getWebGLIntArrayParameter(GC3Denum);
662
663    // Clear the backbuffer if it was composited since the last operation.
664    // clearMask is set to the bitfield of any clear that would happen anyway at this time
665    // and the function returns true if that clear is now unnecessary.
666    bool clearIfComposited(GC3Dbitfield clearMask = 0);
667
668    // Helper to restore state that clearing the framebuffer may destroy.
669    void restoreStateAfterClear();
670
671    void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState&);
672    void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&);
673    void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState&);
674    void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&);
675
676    void handleTextureCompleteness(const char*, bool);
677    void createFallbackBlackTextures1x1();
678
679    // Helper function for copyTex{Sub}Image, check whether the internalformat
680    // and the color buffer format of the current bound framebuffer combination
681    // is valid.
682    bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
683                                                        GC3Denum colorBufferFormat);
684
685    // Helper function to get the bound framebuffer's color buffer format.
686    GC3Denum boundFramebufferColorFormat();
687
688    // Helper function to get the bound framebuffer's width.
689    int boundFramebufferWidth();
690
691    // Helper function to get the bound framebuffer's height.
692    int boundFramebufferHeight();
693
694    // Helper function to verify limits on the length of uniform and attribute locations.
695    bool validateLocationLength(const char* functionName, const String&);
696
697    // Helper function to check if size is non-negative.
698    // Generate GL error and return false for negative inputs; otherwise, return true.
699    bool validateSize(const char* functionName, GC3Dint x, GC3Dint y);
700
701    // Helper function to check if all characters in the string belong to the
702    // ASCII subset as defined in GLSL ES 1.0 spec section 3.1.
703    bool validateString(const char* functionName, const String&);
704
705    // Helper function to check target and texture bound to the target.
706    // Generate GL errors and return 0 if target is invalid or texture bound is
707    // null.  Otherwise, return the texture bound to the target.
708    WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap);
709
710    // Helper function to check input format/type for functions {copy}Tex{Sub}Image.
711    // Generates GL error and returns false if parameters are invalid.
712    bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level);
713
714    // Helper function to check input level for functions {copy}Tex{Sub}Image.
715    // Generates GL error and returns false if level is invalid.
716    bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level);
717
718    enum TexFuncValidationFunctionType {
719        NotTexSubImage2D,
720        TexSubImage2D,
721    };
722
723    enum TexFuncValidationSourceType {
724        SourceArrayBufferView,
725        SourceImageData,
726        SourceHTMLImageElement,
727        SourceHTMLCanvasElement,
728        SourceHTMLVideoElement,
729    };
730
731    // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid.
732    // Otherwise, it would return quickly without doing other work.
733    bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
734        GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset);
735
736    // Helper function to check input width and height for functions {copy, compressed}Tex{Sub}Image.
737    // Generates GL error and returns false if width or height is invalid.
738    bool validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType,
739        GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height);
740
741    // Helper function to check input parameters for functions {copy}Tex{Sub}Image.
742    // Generates GL error and returns false if parameters are invalid.
743    bool validateTexFuncParameters(const char* functionName,
744                                   TexFuncValidationFunctionType,
745                                   GC3Denum target, GC3Dint level,
746                                   GC3Denum internalformat,
747                                   GC3Dsizei width, GC3Dsizei height, GC3Dint border,
748                                   GC3Denum format, GC3Denum type);
749
750    enum NullDisposition {
751        NullAllowed,
752        NullNotAllowed
753    };
754
755    // Helper function to validate that the given ArrayBufferView
756    // is of the correct type and contains enough data for the texImage call.
757    // Generates GL error and returns false if parameters are invalid.
758    bool validateTexFuncData(const char* functionName, GC3Dint level,
759                             GC3Dsizei width, GC3Dsizei height,
760                             GC3Denum format, GC3Denum type,
761                             ArrayBufferView* pixels,
762                             NullDisposition);
763
764    // Helper function to validate a given texture format is settable as in
765    // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and
766    // copyTexSubImage2D.
767    // Generates GL error and returns false if the format is not settable.
768    bool validateSettableTexFormat(const char* functionName, GC3Denum format);
769
770    // Helper function to validate compressed texture data is correct size
771    // for the given format and dimensions.
772    bool validateCompressedTexFuncData(const char* functionName,
773                                       GC3Dsizei width, GC3Dsizei height,
774                                       GC3Denum format, ArrayBufferView* pixels);
775
776    // Helper function for validating compressed texture formats.
777    bool validateCompressedTexFormat(GC3Denum format);
778
779    // Helper function to validate compressed texture dimensions are valid for
780    // the given format.
781    bool validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format);
782
783    // Helper function to validate compressed texture dimensions are valid for
784    // the given format.
785    bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
786                                            GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*);
787
788    // Helper function to validate mode for draw{Arrays/Elements}.
789    bool validateDrawMode(const char* functionName, GC3Denum);
790
791    // Helper function to validate if front/back stencilMask and stencilFunc settings are the same.
792    bool validateStencilSettings(const char* functionName);
793
794    // Helper function to validate stencil or depth func.
795    bool validateStencilOrDepthFunc(const char* functionName, GC3Denum);
796
797    // Helper function for texParameterf and texParameteri.
798    void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat);
799
800    // Helper function to print GL errors to console.
801    void printGLErrorToConsole(const String&);
802
803    // Helper function to print warnings to console. Currently
804    // used only to warn about use of obsolete functions.
805    void printWarningToConsole(const String&);
806
807    // Helper function to validate input parameters for framebuffer functions.
808    // Generate GL error if parameters are illegal.
809    bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment);
810
811    // Helper function to validate blend equation mode.
812    bool validateBlendEquation(const char* functionName, GC3Denum);
813
814    // Helper function to validate blend func factors.
815    bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst);
816
817    // Helper function to validate a GL capability.
818    bool validateCapability(const char* functionName, GC3Denum);
819
820    // Helper function to validate input parameters for uniform functions.
821    bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod);
822    bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod);
823    bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod);
824    bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod);
825    bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod);
826
827    // Helper function to validate parameters for bufferData.
828    // Return the current bound buffer to target, or 0 if parameters are invalid.
829    WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage);
830
831    // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin.
832    bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionState&);
833
834    // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin.
835    bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionState&);
836
837    // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin.
838    bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionState&);
839
840    // Helper function to validate drawArrays(Instanced) calls
841    bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count);
842
843    // Helper function to validate drawElements(Instanced) calls
844    bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset);
845
846    // Helper function to validate draw*Instanced calls
847    bool validateDrawInstanced(const char* functionName, GC3Dsizei primcount);
848
849    // Helper functions for vertexAttribNf{v}.
850    void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat);
851    void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize);
852    void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize);
853
854    // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions.
855    // Return false if caller should return without further processing.
856    bool deleteObject(WebGLObject*);
857
858    // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram.
859    // If the object has already been deleted, set deleted to true upon return.
860    // Return false if caller should return without further processing.
861    bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted);
862
863    void dispatchContextLostEvent(Timer<WebGLRenderingContext>*);
864    // Helper for restoration after context lost.
865    void maybeRestoreContext(Timer<WebGLRenderingContext>*);
866
867    // Determine if we are running privileged code in the browser, for example,
868    // a Safari or Chrome extension.
869    bool allowPrivilegedExtensions() const;
870
871    // Determine if WEBGL_debug_renderer_info extension is enabled. For the
872    // moment it can be enabled either through a chromium finch experiment
873    // or for privileged code in the browser.
874    bool allowWebGLDebugRendererInfo() const;
875
876    enum ConsoleDisplayPreference {
877        DisplayInConsole,
878        DontDisplayInConsole
879    };
880
881    // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message
882    // to the JavaScript console.
883    void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole);
884    void emitGLWarning(const char* function, const char* reason);
885
886    String ensureNotNull(const String&) const;
887
888    // Enable or disable stencil test based on user setting and
889    // whether the current FBO has a stencil buffer.
890    void applyStencilTest();
891
892    // Helper for enabling or disabling a capability.
893    void enableOrDisable(GC3Denum capability, bool enable);
894
895    // Clamp the width and height to GL_MAX_VIEWPORT_DIMS.
896    IntSize clampedCanvasSize();
897
898    // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0.
899    // Later, return the cached value.
900    GC3Dint maxDrawBuffers();
901    GC3Dint maxColorAttachments();
902
903    void setBackDrawBuffer(GC3Denum);
904
905    void restoreCurrentFramebuffer();
906    void restoreCurrentTexture2D();
907
908    virtual void multisamplingChanged(bool);
909
910    void findNewMaxEnabledAttribIndex();
911    void findNewMaxNonDefaultTextureUnit();
912
913    friend class WebGLStateRestorer;
914    friend class WebGLRenderingContextEvictionManager;
915
916    static Vector<WebGLRenderingContext*>& activeContexts();
917    static Vector<WebGLRenderingContext*>& forciblyEvictedContexts();
918
919    static void activateContext(WebGLRenderingContext*);
920    static void deactivateContext(WebGLRenderingContext*, bool addToInactiveList);
921    static void willDestroyContext(WebGLRenderingContext*);
922    static void forciblyLoseOldestContext(const String& reason);
923    // Return the least recently used context's position in the active context vector.
924    // If the vector is empty, return the maximum allowed active context number.
925    static size_t oldestContextIndex();
926    static IntSize oldestContextSize();
927};
928
929DEFINE_TYPE_CASTS(WebGLRenderingContext, CanvasRenderingContext, context, context->is3d(), context.is3d());
930
931} // namespace WebCore
932
933#endif
934