Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: Source/core/html/canvas/WebGLRenderingContext.cpp

Issue 24096029: Moved the majority of WebGL functionality into WebGLRenderingContextBase (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Apple Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 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 * 7 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 8 * 1. Redistributions of source code must retain the above copyright
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9 * notice, this list of conditions and the following disclaimer.
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 10 * 2. Redistributions in binary form must reproduce the above copyright
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 11 * notice, this list of conditions and the following disclaimer in the
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 12 * documentation and/or other materials provided with the distribution.
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 13 *
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #include "config.h" 26 #include "config.h"
27 #include "core/html/canvas/WebGLRenderingContext.h" 27 #include "core/html/canvas/WebGLRenderingContext.h"
28 28
29 #include "RuntimeEnabledFeatures.h"
30 #include "bindings/v8/ExceptionMessages.h"
31 #include "bindings/v8/ExceptionState.h"
32 #include "core/dom/ExceptionCode.h"
33 #include "core/fetch/ImageResource.h"
34 #include "core/html/HTMLCanvasElement.h"
35 #include "core/html/HTMLImageElement.h"
36 #include "core/html/HTMLVideoElement.h"
37 #include "core/html/ImageData.h"
38 #include "core/html/canvas/ANGLEInstancedArrays.h" 29 #include "core/html/canvas/ANGLEInstancedArrays.h"
39 #include "core/html/canvas/EXTFragDepth.h" 30 #include "core/html/canvas/EXTFragDepth.h"
40 #include "core/html/canvas/EXTTextureFilterAnisotropic.h" 31 #include "core/html/canvas/EXTTextureFilterAnisotropic.h"
41 #include "core/html/canvas/OESElementIndexUint.h" 32 #include "core/html/canvas/OESElementIndexUint.h"
42 #include "core/html/canvas/OESStandardDerivatives.h" 33 #include "core/html/canvas/OESStandardDerivatives.h"
43 #include "core/html/canvas/OESTextureFloat.h" 34 #include "core/html/canvas/OESTextureFloat.h"
44 #include "core/html/canvas/OESTextureFloatLinear.h" 35 #include "core/html/canvas/OESTextureFloatLinear.h"
45 #include "core/html/canvas/OESTextureHalfFloat.h" 36 #include "core/html/canvas/OESTextureHalfFloat.h"
46 #include "core/html/canvas/OESTextureHalfFloatLinear.h" 37 #include "core/html/canvas/OESTextureHalfFloatLinear.h"
47 #include "core/html/canvas/OESVertexArrayObject.h" 38 #include "core/html/canvas/OESVertexArrayObject.h"
48 #include "core/html/canvas/WebGLActiveInfo.h"
49 #include "core/html/canvas/WebGLBuffer.h"
50 #include "core/html/canvas/WebGLCompressedTextureATC.h" 39 #include "core/html/canvas/WebGLCompressedTextureATC.h"
51 #include "core/html/canvas/WebGLCompressedTexturePVRTC.h" 40 #include "core/html/canvas/WebGLCompressedTexturePVRTC.h"
52 #include "core/html/canvas/WebGLCompressedTextureS3TC.h" 41 #include "core/html/canvas/WebGLCompressedTextureS3TC.h"
53 #include "core/html/canvas/WebGLContextAttributes.h" 42 #include "core/html/canvas/WebGLContextAttributes.h"
54 #include "core/html/canvas/WebGLContextEvent.h" 43 #include "core/html/canvas/WebGLContextEvent.h"
55 #include "core/html/canvas/WebGLContextGroup.h"
56 #include "core/html/canvas/WebGLDebugRendererInfo.h" 44 #include "core/html/canvas/WebGLDebugRendererInfo.h"
57 #include "core/html/canvas/WebGLDebugShaders.h" 45 #include "core/html/canvas/WebGLDebugShaders.h"
58 #include "core/html/canvas/WebGLDepthTexture.h" 46 #include "core/html/canvas/WebGLDepthTexture.h"
59 #include "core/html/canvas/WebGLDrawBuffers.h" 47 #include "core/html/canvas/WebGLDrawBuffers.h"
60 #include "core/html/canvas/WebGLFramebuffer.h"
61 #include "core/html/canvas/WebGLLoseContext.h" 48 #include "core/html/canvas/WebGLLoseContext.h"
62 #include "core/html/canvas/WebGLProgram.h"
63 #include "core/html/canvas/WebGLRenderbuffer.h"
64 #include "core/html/canvas/WebGLShader.h"
65 #include "core/html/canvas/WebGLShaderPrecisionFormat.h"
66 #include "core/html/canvas/WebGLTexture.h"
67 #include "core/html/canvas/WebGLUniformLocation.h"
68 #include "core/inspector/InspectorInstrumentation.h"
69 #include "core/loader/FrameLoader.h" 49 #include "core/loader/FrameLoader.h"
70 #include "core/loader/FrameLoaderClient.h" 50 #include "core/loader/FrameLoaderClient.h"
71 #include "core/page/Frame.h" 51 #include "core/page/Frame.h"
72 #include "core/page/Page.h"
73 #include "core/page/Settings.h" 52 #include "core/page/Settings.h"
74 #include "core/platform/NotImplemented.h"
75 #include "core/platform/graphics/Extensions3D.h"
76 #include "core/platform/graphics/ImageBuffer.h"
77 #include "core/platform/graphics/IntSize.h"
78 #include "core/platform/graphics/gpu/DrawingBuffer.h" 53 #include "core/platform/graphics/gpu/DrawingBuffer.h"
79 #include "core/rendering/RenderBox.h"
80
81 #include "wtf/OwnArrayPtr.h"
82 #include "wtf/PassOwnArrayPtr.h"
83 #include "wtf/Uint32Array.h"
84 #include "wtf/text/StringBuilder.h"
85 54
86 namespace WebCore { 55 namespace WebCore {
87 56
88 const double secondsBetweenRestoreAttempts = 1.0;
89 const int maxGLErrorsAllowedToConsole = 256;
90 const int maxGLActiveContexts = 16;
91
92 Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts()
93 {
94 DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ());
95 return activeContexts;
96 }
97
98 Vector<WebGLRenderingContext*>& WebGLRenderingContext::forciblyEvictedContexts()
99 {
100 DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, forciblyEvictedContexts, ());
101 return forciblyEvictedContexts;
102 }
103
104 void WebGLRenderingContext::forciblyLoseOldestContext(const String& reason)
105 {
106 if (activeContexts().size()) {
107 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
108 activeContexts().remove(0);
109
110 oldestActiveContext->printWarningToConsole(reason);
111 InspectorInstrumentation::didFireWebGLWarning(oldestActiveContext->canva s());
112
113 // This will call deactivateContext once the context has actually been l ost.
114 oldestActiveContext->forceLostContext(WebGLRenderingContext::SyntheticLo stContext);
115 }
116 }
117
118 IntSize WebGLRenderingContext::oldestContextSize()
119 {
120 IntSize size;
121
122 if (activeContexts().size()) {
123 WebGLRenderingContext* oldestActiveContext = activeContexts().first();
124 size.setWidth(oldestActiveContext->drawingBufferWidth());
125 size.setHeight(oldestActiveContext->drawingBufferHeight());
126 }
127
128 return size;
129 }
130
131 void WebGLRenderingContext::activateContext(WebGLRenderingContext* context)
132 {
133 if (!activeContexts().contains(context))
134 activeContexts().append(context);
135
136 if (activeContexts().size() > maxGLActiveContexts)
137 forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Olde st context will be lost.");
138 }
139
140 void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bo ol addToEvictedList)
141 {
142 size_t position = activeContexts().find(context);
143 if (position != WTF::notFound)
144 activeContexts().remove(position);
145
146 if (addToEvictedList && !forciblyEvictedContexts().contains(context))
147 forciblyEvictedContexts().append(context);
148 }
149
150 void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context)
151 {
152 size_t position = forciblyEvictedContexts().find(context);
153 if (position != WTF::notFound)
154 forciblyEvictedContexts().remove(position);
155
156 deactivateContext(context, false);
157
158 // Try to re-enable the oldest inactive contexts.
159 while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContex ts().size()) {
160 WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first( );
161 if (!evictedContext->m_restoreAllowed) {
162 forciblyEvictedContexts().remove(0);
163 continue;
164 }
165
166 IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evicte dContext->clampedCanvasSize());
167
168 // If there's room in the pixel budget for this context, restore it.
169 if (!desiredSize.isEmpty()) {
170 forciblyEvictedContexts().remove(0);
171 evictedContext->forceRestoreContext();
172 activeContexts().append(evictedContext);
173 }
174 break;
175 }
176 }
177
178 class WebGLRenderingContextEvictionManager : public ContextEvictionManager {
179 public:
180 void forciblyLoseOldestContext(const String& reason) {
181 WebGLRenderingContext::forciblyLoseOldestContext(reason);
182 };
183 IntSize oldestContextSize() {
184 return WebGLRenderingContext::oldestContextSize();
185 };
186 };
187
188 namespace {
189
190 class ScopedDrawingBufferBinder {
191 public:
192 ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer * framebufferBinding)
193 : m_drawingBuffer(drawingBuffer)
194 , m_framebufferBinding(framebufferBinding)
195 {
196 // Commit DrawingBuffer if needed (e.g., for multisampling)
197 if (!m_framebufferBinding && m_drawingBuffer)
198 m_drawingBuffer->commit();
199 }
200
201 ~ScopedDrawingBufferBinder()
202 {
203 // Restore DrawingBuffer if needed
204 if (!m_framebufferBinding && m_drawingBuffer)
205 m_drawingBuffer->bind();
206 }
207
208 private:
209 DrawingBuffer* m_drawingBuffer;
210 WebGLFramebuffer* m_framebufferBinding;
211 };
212
213 Platform3DObject objectOrZero(WebGLObject* object)
214 {
215 return object ? object->object() : 0;
216 }
217
218 void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange)
219 {
220 ASSERT(clippedStart && clippedRange);
221 if (start < 0) {
222 range += start;
223 start = 0;
224 }
225 GC3Dint end = start + range;
226 if (end > sourceRange)
227 range -= end - sourceRange;
228 *clippedStart = start;
229 *clippedRange = range;
230 }
231
232 // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same.
233 bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height,
234 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight,
235 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, G C3Dsizei*clippedHeight)
236 {
237 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight);
238 clip1D(x, width, sourceWidth, clippedX, clippedWidth);
239 clip1D(y, height, sourceHeight, clippedY, clippedHeight);
240 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *c lippedHeight != height);
241 }
242
243 GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max)
244 {
245 if (value < min)
246 value = min;
247 if (value > max)
248 value = max;
249 return value;
250 }
251
252 // Return true if a character belongs to the ASCII subset as defined in
253 // GLSL ES 1.0 spec section 3.1.
254 bool validateCharacter(unsigned char c)
255 {
256 // Printing characters are valid except " $ ` @ \ ' DEL.
257 if (c >= 32 && c <= 126
258 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
259 return true;
260 // Horizontal tab, line feed, vertical tab, form feed, carriage return
261 // are also valid.
262 if (c >= 9 && c <= 13)
263 return true;
264 return false;
265 }
266
267 bool isPrefixReserved(const String& name)
268 {
269 if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWi th("_webgl_"))
270 return true;
271 return false;
272 }
273
274 // Strips comments from shader text. This allows non-ASCII characters
275 // to be used in comments without potentially breaking OpenGL
276 // implementations not expecting characters outside the GLSL ES set.
277 class StripComments {
278 public:
279 StripComments(const String& str)
280 : m_parseState(BeginningOfLine)
281 , m_sourceString(str)
282 , m_length(str.length())
283 , m_position(0)
284 {
285 parse();
286 }
287
288 String result()
289 {
290 return m_builder.toString();
291 }
292
293 private:
294 bool hasMoreCharacters() const
295 {
296 return (m_position < m_length);
297 }
298
299 void parse()
300 {
301 while (hasMoreCharacters()) {
302 process(current());
303 // process() might advance the position.
304 if (hasMoreCharacters())
305 advance();
306 }
307 }
308
309 void process(UChar);
310
311 bool peek(UChar& character) const
312 {
313 if (m_position + 1 >= m_length)
314 return false;
315 character = m_sourceString[m_position + 1];
316 return true;
317 }
318
319 UChar current()
320 {
321 ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length);
322 return m_sourceString[m_position];
323 }
324
325 void advance()
326 {
327 ++m_position;
328 }
329
330 static bool isNewline(UChar character)
331 {
332 // Don't attempt to canonicalize newline related characters.
333 return (character == '\n' || character == '\r');
334 }
335
336 void emit(UChar character)
337 {
338 m_builder.append(character);
339 }
340
341 enum ParseState {
342 // Have not seen an ASCII non-whitespace character yet on
343 // this line. Possible that we might see a preprocessor
344 // directive.
345 BeginningOfLine,
346
347 // Have seen at least one ASCII non-whitespace character
348 // on this line.
349 MiddleOfLine,
350
351 // Handling a preprocessor directive. Passes through all
352 // characters up to the end of the line. Disables comment
353 // processing.
354 InPreprocessorDirective,
355
356 // Handling a single-line comment. The comment text is
357 // replaced with a single space.
358 InSingleLineComment,
359
360 // Handling a multi-line comment. Newlines are passed
361 // through to preserve line numbers.
362 InMultiLineComment
363 };
364
365 ParseState m_parseState;
366 String m_sourceString;
367 unsigned m_length;
368 unsigned m_position;
369 StringBuilder m_builder;
370 };
371
372 void StripComments::process(UChar c)
373 {
374 if (isNewline(c)) {
375 // No matter what state we are in, pass through newlines
376 // so we preserve line numbers.
377 emit(c);
378
379 if (m_parseState != InMultiLineComment)
380 m_parseState = BeginningOfLine;
381
382 return;
383 }
384
385 UChar temp = 0;
386 switch (m_parseState) {
387 case BeginningOfLine:
388 if (WTF::isASCIISpace(c)) {
389 emit(c);
390 break;
391 }
392
393 if (c == '#') {
394 m_parseState = InPreprocessorDirective;
395 emit(c);
396 break;
397 }
398
399 // Transition to normal state and re-handle character.
400 m_parseState = MiddleOfLine;
401 process(c);
402 break;
403
404 case MiddleOfLine:
405 if (c == '/' && peek(temp)) {
406 if (temp == '/') {
407 m_parseState = InSingleLineComment;
408 emit(' ');
409 advance();
410 break;
411 }
412
413 if (temp == '*') {
414 m_parseState = InMultiLineComment;
415 // Emit the comment start in case the user has
416 // an unclosed comment and we want to later
417 // signal an error.
418 emit('/');
419 emit('*');
420 advance();
421 break;
422 }
423 }
424
425 emit(c);
426 break;
427
428 case InPreprocessorDirective:
429 // No matter what the character is, just pass it
430 // through. Do not parse comments in this state. This
431 // might not be the right thing to do long term, but it
432 // should handle the #error preprocessor directive.
433 emit(c);
434 break;
435
436 case InSingleLineComment:
437 // The newline code at the top of this function takes care
438 // of resetting our state when we get out of the
439 // single-line comment. Swallow all other characters.
440 break;
441
442 case InMultiLineComment:
443 if (c == '*' && peek(temp) && temp == '/') {
444 emit('*');
445 emit('/');
446 m_parseState = MiddleOfLine;
447 advance();
448 break;
449 }
450
451 // Swallow all other characters. Unclear whether we may
452 // want or need to just emit a space per character to try
453 // to preserve column numbers for debugging purposes.
454 break;
455 }
456 }
457
458 GraphicsContext3D::Attributes adjustAttributes(const GraphicsContext3D::Attr ibutes& attributes, Settings* settings)
459 {
460 GraphicsContext3D::Attributes adjustedAttributes = attributes;
461 if (adjustedAttributes.antialias) {
462 if (settings && !settings->openGLMultisamplingEnabled())
463 adjustedAttributes.antialias = false;
464 }
465
466 return adjustedAttributes;
467 }
468 } // namespace anonymous
469
470 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostC allback {
471 WTF_MAKE_FAST_ALLOCATED;
472 public:
473 explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_co ntext(cb) { }
474 virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingCon text::RealLostContext); }
475 virtual ~WebGLRenderingContextLostCallback() {}
476 private:
477 WebGLRenderingContext* m_context;
478 };
479
480 class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::Erro rMessageCallback {
481 WTF_MAKE_FAST_ALLOCATED;
482 public:
483 explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb ) : m_context(cb) { }
484 virtual void onErrorMessage(const String& message, GC3Dint)
485 {
486 if (m_context->m_synthesizedErrorsToConsole)
487 m_context->printGLErrorToConsole(message);
488 InspectorInstrumentation::didFireWebGLErrorOrWarning(m_context->canvas() , message);
489 }
490 virtual ~WebGLRenderingContextErrorMessageCallback() { }
491 private:
492 WebGLRenderingContext* m_context;
493 };
494
495 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen t* canvas, WebGLContextAttributes* attrs) 57 PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen t* canvas, WebGLContextAttributes* attrs)
bajones 2013/09/20 19:24:25 I'd like to abstract this function some more, beca
496 { 58 {
497 Document& document = canvas->document(); 59 Document& document = canvas->document();
498 Frame* frame = document.frame(); 60 Frame* frame = document.frame();
499 if (!frame) 61 if (!frame)
500 return nullptr; 62 return nullptr;
501 Settings* settings = frame->settings(); 63 Settings* settings = frame->settings();
502 64
503 // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in 65 // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in
504 // particular, if WebGL contexts were lost one or more times via the GL_ARB_ robustness extension. 66 // particular, if WebGL contexts were lost one or more times via the GL_ARB_ robustness extension.
505 if (!frame->loader()->client()->allowWebGL(settings && settings->webGLEnable d())) { 67 if (!frame->loader()->client()->allowWebGL(settings && settings->webGLEnable d())) {
506 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL co ntext.")); 68 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL co ntext."));
507 return nullptr; 69 return nullptr;
508 } 70 }
509 71
510 GraphicsContext3D::Attributes requestedAttributes = attrs ? attrs->attribute s() : GraphicsContext3D::Attributes(); 72 GraphicsContext3D::Attributes requestedAttributes = attrs ? attrs->attribute s() : GraphicsContext3D::Attributes();
511 requestedAttributes.noExtensions = true; 73 requestedAttributes.noExtensions = true;
512 requestedAttributes.shareResources = true; 74 requestedAttributes.shareResources = true;
513 requestedAttributes.preferDiscreteGPU = true; 75 requestedAttributes.preferDiscreteGPU = true;
514 requestedAttributes.topDocumentURL = document.topDocument()->url(); 76 requestedAttributes.topDocumentURL = document.topDocument()->url();
515 77
516 GraphicsContext3D::Attributes attributes = adjustAttributes(requestedAttribu tes, settings); 78 GraphicsContext3D::Attributes attributes = WebGLRenderingContext::adjustAttr ibutes(requestedAttributes, settings);
517 79
518 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes)); 80 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes));
519 81
520 if (!context || !context->makeContextCurrent()) { 82 if (!context || !context->makeContextCurrent()) {
521 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Could not create a WebGL context.")); 83 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Could not create a WebGL context."));
522 return nullptr; 84 return nullptr;
523 } 85 }
524 86
525 Extensions3D* extensions = context->getExtensions(); 87 Extensions3D* extensions = context->getExtensions();
526 if (extensions->supports("GL_EXT_debug_marker")) 88 if (extensions->supports("GL_EXT_debug_marker"))
527 extensions->pushGroupMarkerEXT("WebGLRenderingContext"); 89 extensions->pushGroupMarkerEXT("WebGLRenderingContext");
528 90
529 OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRendering Context(canvas, context, attributes, requestedAttributes)); 91 OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRendering Context(canvas, context, attributes, requestedAttributes));
92 renderingContext->registerContextExtensions();
530 renderingContext->suspendIfNeeded(); 93 renderingContext->suspendIfNeeded();
531 94
532 if (renderingContext->m_drawingBuffer->isZeroSized()) { 95 if (renderingContext->m_drawingBuffer->isZeroSized()) {
533 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Could not create a WebGL context.")); 96 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontex tcreationerrorEvent, false, true, "Could not create a WebGL context."));
534 return nullptr; 97 return nullptr;
535 } 98 }
536 99
537 return renderingContext.release(); 100 return renderingContext.release();
538 } 101 }
539 102
540 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa ssRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, G raphicsContext3D::Attributes requestedAttributes) 103 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa ssRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, G raphicsContext3D::Attributes requestedAttributes)
541 : CanvasRenderingContext(passedCanvas) 104 : WebGLRenderingContextBase("WebGLRenderingContext", passedCanvas, context, attributes, requestedAttributes)
542 , ActiveDOMObject(&passedCanvas->document())
543 , m_context(context)
544 , m_drawingBuffer(0)
545 , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchCont extLostEvent)
546 , m_restoreAllowed(false)
547 , m_restoreTimer(this, &WebGLRenderingContext::maybeRestoreContext)
548 , m_videoCache(4)
549 , m_contextLost(false)
550 , m_contextLostMode(SyntheticLostContext)
551 , m_attributes(attributes)
552 , m_requestedAttributes(requestedAttributes)
553 , m_synthesizedErrorsToConsole(true)
554 , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
555 , m_multisamplingAllowed(false)
556 , m_multisamplingObserverRegistered(false)
557 , m_onePlusMaxEnabledAttribIndex(0)
558 , m_onePlusMaxNonDefaultTextureUnit(0)
559 { 105 {
560 ASSERT(m_context);
561 ScriptWrappable::init(this); 106 ScriptWrappable::init(this);
107 }
562 108
563 m_contextGroup = WebGLContextGroup::create(); 109 WebGLRenderingContext::~WebGLRenderingContext()
564 m_contextGroup->addContext(this); 110 {
111 }
565 112
566 m_maxViewportDims[0] = m_maxViewportDims[1] = 0; 113 void WebGLRenderingContext::registerContextExtensions()
bajones 2013/09/20 19:24:25 Moving out of base ensures that the WebGL2 context
567 m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDi ms); 114 {
568
569 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
570
571 // Create the DrawingBuffer and initialize the platform layer.
572 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
573 m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize() , preserve, contextEvictionManager.release());
574
575 if (!m_drawingBuffer->isZeroSized()) {
576 m_drawingBuffer->bind();
577 setupFlags();
578 initializeNewContext();
579 }
580
581 // Register extensions. 115 // Register extensions.
582 static const char* webkitPrefix[] = { "WEBKIT_", 0, }; 116 static const char* webkitPrefix[] = { "WEBKIT_", 0, };
583 static const char* bothPrefixes[] = { "", "WEBKIT_", 0, }; 117 static const char* bothPrefixes[] = { "", "WEBKIT_", 0, };
584 118
585 registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays); 119 registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays);
586 registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic , PrefixedExtension, webkitPrefix); 120 registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic , PrefixedExtension, webkitPrefix);
587 registerExtension<OESElementIndexUint>(m_oesElementIndexUint); 121 registerExtension<OESElementIndexUint>(m_oesElementIndexUint);
588 registerExtension<OESStandardDerivatives>(m_oesStandardDerivatives); 122 registerExtension<OESStandardDerivatives>(m_oesStandardDerivatives);
589 registerExtension<OESTextureFloat>(m_oesTextureFloat); 123 registerExtension<OESTextureFloat>(m_oesTextureFloat);
590 registerExtension<OESTextureFloatLinear>(m_oesTextureFloatLinear); 124 registerExtension<OESTextureFloatLinear>(m_oesTextureFloatLinear);
591 registerExtension<OESTextureHalfFloat>(m_oesTextureHalfFloat); 125 registerExtension<OESTextureHalfFloat>(m_oesTextureHalfFloat);
592 registerExtension<OESTextureHalfFloatLinear>(m_oesTextureHalfFloatLinear); 126 registerExtension<OESTextureHalfFloatLinear>(m_oesTextureHalfFloatLinear);
593 registerExtension<OESVertexArrayObject>(m_oesVertexArrayObject); 127 registerExtension<OESVertexArrayObject>(m_oesVertexArrayObject);
594 registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, Pr efixedExtension, webkitPrefix); 128 registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, Pr efixedExtension, webkitPrefix);
595 registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC , PrefixedExtension, webkitPrefix); 129 registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC , PrefixedExtension, webkitPrefix);
596 registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, PrefixedExtension, bothPrefixes); 130 registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, PrefixedExtension, bothPrefixes);
597 registerExtension<WebGLDepthTexture>(m_webglDepthTexture, PrefixedExtension, bothPrefixes); 131 registerExtension<WebGLDepthTexture>(m_webglDepthTexture, PrefixedExtension, bothPrefixes);
598 registerExtension<WebGLLoseContext>(m_webglLoseContext, ApprovedExtension, b othPrefixes); 132 registerExtension<WebGLLoseContext>(m_webglLoseContext, ApprovedExtension, b othPrefixes);
599 133
600 // Register draft extensions. 134 // Register draft extensions.
601 registerExtension<EXTFragDepth>(m_extFragDepth, DraftExtension); 135 registerExtension<EXTFragDepth>(m_extFragDepth, DraftExtension);
602 registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers, DraftExtension); 136 registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers, DraftExtension);
603 137
604 // Register privileged extensions. 138 // Register privileged extensions.
605 registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo, Privileg edExtension); 139 registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo, Privileg edExtension);
606 registerExtension<WebGLDebugShaders>(m_webglDebugShaders, PrivilegedExtensio n); 140 registerExtension<WebGLDebugShaders>(m_webglDebugShaders, PrivilegedExtensio n);
607 } 141 }
608 142
609 void WebGLRenderingContext::initializeNewContext()
610 {
611 ASSERT(!isContextLost());
612 m_needsUpdate = true;
613 m_markedCanvasDirty = false;
614 m_activeTextureUnit = 0;
615 m_packAlignment = 4;
616 m_unpackAlignment = 4;
617 m_unpackFlipY = false;
618 m_unpackPremultiplyAlpha = false;
619 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL;
620 m_boundArrayBuffer = 0;
621 m_currentProgram = 0;
622 m_framebufferBinding = 0;
623 m_renderbufferBinding = 0;
624 m_depthMask = true;
625 m_stencilEnabled = false;
626 m_stencilMask = 0xFFFFFFFF;
627 m_stencilMaskBack = 0xFFFFFFFF;
628 m_stencilFuncRef = 0;
629 m_stencilFuncRefBack = 0;
630 m_stencilFuncMask = 0xFFFFFFFF;
631 m_stencilFuncMaskBack = 0xFFFFFFFF;
632 m_layerCleared = false;
633 m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole;
634
635 m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0;
636 m_scissorEnabled = false;
637 m_clearDepth = 1;
638 m_clearStencil = 0;
639 m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true;
640
641 GC3Dint numCombinedTextureImageUnits = 0;
642 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits);
643 m_textureUnits.clear();
644 m_textureUnits.resize(numCombinedTextureImageUnits);
645
646 GC3Dint numVertexAttribs = 0;
647 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttr ibs);
648 m_maxVertexAttribs = numVertexAttribs;
649
650 m_maxTextureSize = 0;
651 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSiz e);
652 m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxT extureSize);
653 m_maxCubeMapTextureSize = 0;
654 m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxC ubeMapTextureSize);
655 m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextu reSize, m_maxCubeMapTextureSize);
656 m_maxRenderbufferSize = 0;
657 m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRende rbufferSize);
658
659 // These two values from EXT_draw_buffers are lazily queried.
660 m_maxDrawBuffers = 0;
661 m_maxColorAttachments = 0;
662
663 m_backDrawBuffer = GraphicsContext3D::BACK;
664
665 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVe rtexArrayObjectOES::VaoTypeDefault);
666 addContextObject(m_defaultVertexArrayObject.get());
667 m_boundVertexArrayObject = m_defaultVertexArrayObject;
668
669 m_vertexAttribValue.resize(m_maxVertexAttribs);
670
671 createFallbackBlackTextures1x1();
672
673 IntSize canvasSize = clampedCanvasSize();
674 m_drawingBuffer->reset(canvasSize);
675
676 m_context->viewport(0, 0, canvasSize.width(), canvasSize.height());
677 m_context->scissor(0, 0, canvasSize.width(), canvasSize.height());
678
679 m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCall back(this)));
680 m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMe ssageCallback(this)));
681
682 activateContext(this);
683 }
684
685 void WebGLRenderingContext::setupFlags()
686 {
687 ASSERT(m_context);
688 if (Page* p = canvas()->document().page()) {
689 m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled ();
690
691 if (!m_multisamplingObserverRegistered && m_requestedAttributes.antialia s) {
692 m_multisamplingAllowed = m_drawingBuffer->multisample();
693 p->addMultisamplingChangedObserver(this);
694 m_multisamplingObserverRegistered = true;
695 }
696 }
697
698 m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture _npot");
699 m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_pa cked_depth_stencil");
700 }
701
702 bool WebGLRenderingContext::allowPrivilegedExtensions() const
703 {
704 if (Page* p = canvas()->document().page())
705 return p->settings().privilegedWebGLExtensionsEnabled();
706 return false;
707 }
708
709 void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format)
710 {
711 if (!m_compressedTextureFormats.contains(format))
712 m_compressedTextureFormats.append(format);
713 }
714
715 void WebGLRenderingContext::removeAllCompressedTextureFormats()
716 {
717 m_compressedTextureFormats.clear();
718 }
719
720 WebGLRenderingContext::~WebGLRenderingContext()
721 {
722 // Remove all references to WebGLObjects so if they are the last reference
723 // they will be freed before the last context is removed from the context gr oup.
724 m_boundArrayBuffer = 0;
725 m_defaultVertexArrayObject = 0;
726 m_boundVertexArrayObject = 0;
727 m_vertexAttrib0Buffer = 0;
728 m_currentProgram = 0;
729 m_framebufferBinding = 0;
730 m_renderbufferBinding = 0;
731
732 for (size_t i = 0; i < m_textureUnits.size(); ++i) {
733 m_textureUnits[i].m_texture2DBinding = 0;
734 m_textureUnits[i].m_textureCubeMapBinding = 0;
735 }
736
737 m_blackTexture2D = 0;
738 m_blackTextureCubeMap = 0;
739
740 detachAndRemoveAllObjects();
741
742 // release all extensions
743 for (size_t i = 0; i < m_extensions.size(); ++i)
744 delete m_extensions[i];
745
746 // Context must be removed from the group prior to the destruction of the
747 // GraphicsContext3D, otherwise shared objects may not be properly deleted.
748 m_contextGroup->removeContext(this);
749
750 destroyGraphicsContext3D();
751
752 if (m_multisamplingObserverRegistered) {
753 Page* page = canvas()->document().page();
754 if (page)
755 page->removeMultisamplingChangedObserver(this);
756 }
757
758 willDestroyContext(this);
759 }
760
761 void WebGLRenderingContext::destroyGraphicsContext3D()
762 {
763 m_contextLost = true;
764
765 // The drawing buffer holds a context reference. It must also be destroyed
766 // in order for the context to be released.
767 m_drawingBuffer->releaseResources();
768
769 if (m_context) {
770 m_context->setContextLostCallback(nullptr);
771 m_context->setErrorMessageCallback(nullptr);
772 m_context.clear();
773 }
774 }
775
776 void WebGLRenderingContext::markContextChanged()
777 {
778 if (m_framebufferBinding || isContextLost())
779 return;
780
781 m_context->markContextChanged();
782 m_drawingBuffer->markContentsChanged();
783
784 m_layerCleared = false;
785 RenderBox* renderBox = canvas()->renderBox();
786 if (renderBox && renderBox->hasAcceleratedCompositing()) {
787 m_markedCanvasDirty = true;
788 canvas()->clearCopiedImage();
789 renderBox->contentChanged(CanvasChanged);
790 } else {
791 if (!m_markedCanvasDirty) {
792 m_markedCanvasDirty = true;
793 canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize()));
794 }
795 }
796 }
797
798 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
799 {
800 if (isContextLost())
801 return false;
802
803 if (!m_context->layerComposited() || m_layerCleared
804 || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding))
805 return false;
806
807 RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
808
809 // Determine if it's possible to combine the clear the user asked for and th is clear.
810 bool combinedClear = mask && !m_scissorEnabled;
811
812 m_context->disable(GraphicsContext3D::SCISSOR_TEST);
813 if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT))
814 m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0,
815 m_colorMask[1] ? m_clearColor[1] : 0,
816 m_colorMask[2] ? m_clearColor[2] : 0,
817 m_colorMask[3] ? m_clearColor[3] : 0);
818 else
819 m_context->clearColor(0, 0, 0, 0);
820 m_context->colorMask(true, true, true, true);
821 GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
822 if (contextAttributes->depth()) {
823 if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_ BUFFER_BIT))
824 m_context->clearDepth(1.0f);
825 clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
826 m_context->depthMask(true);
827 }
828 if (contextAttributes->stencil()) {
829 if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT))
830 m_context->clearStencil(m_clearStencil & m_stencilMask);
831 else
832 m_context->clearStencil(0);
833 clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
834 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF);
835 }
836
837 m_drawingBuffer->clearFramebuffers(clearMask);
838
839 restoreStateAfterClear();
840 if (m_framebufferBinding)
841 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero( m_framebufferBinding.get()));
842 m_layerCleared = true;
843
844 return combinedClear;
845 }
846
847 void WebGLRenderingContext::restoreStateAfterClear()
848 {
849 if (isContextLost())
850 return;
851
852 // Restore the state that the context set.
853 if (m_scissorEnabled)
854 m_context->enable(GraphicsContext3D::SCISSOR_TEST);
855 m_context->clearColor(m_clearColor[0], m_clearColor[1],
856 m_clearColor[2], m_clearColor[3]);
857 m_context->colorMask(m_colorMask[0], m_colorMask[1],
858 m_colorMask[2], m_colorMask[3]);
859 m_context->clearDepth(m_clearDepth);
860 m_context->clearStencil(m_clearStencil);
861 m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask);
862 m_context->depthMask(m_depthMask);
863 }
864
865 void WebGLRenderingContext::markLayerComposited()
866 {
867 if (!isContextLost())
868 m_context->markLayerComposited();
869 }
870
871 void WebGLRenderingContext::paintRenderingResultsToCanvas()
872 {
873 if (isContextLost()) {
874 canvas()->clearPresentationCopy();
875 return;
876 }
877
878 if (canvas()->document().printing())
879 canvas()->clearPresentationCopy();
880
881 // Until the canvas is written to by the application, the clear that
882 // happened after it was composited should be ignored by the compositor.
883 if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) {
884 m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer());
885
886 canvas()->makePresentationCopy();
887 } else
888 canvas()->clearPresentationCopy();
889 clearIfComposited();
890
891 if (!m_markedCanvasDirty && !m_layerCleared)
892 return;
893
894 canvas()->clearCopiedImage();
895 m_markedCanvasDirty = false;
896
897 m_drawingBuffer->commit();
898 m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer .get());
899
900 if (m_framebufferBinding)
901 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero( m_framebufferBinding.get()));
902 else
903 m_drawingBuffer->bind();
904 }
905
906 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
907 {
908 if (isContextLost())
909 return 0;
910
911 clearIfComposited();
912 m_drawingBuffer->commit();
913 RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_ drawingBuffer.get());
914
915 if (m_framebufferBinding)
916 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero( m_framebufferBinding.get()));
917 else
918 m_drawingBuffer->bind();
919
920 return imageData;
921 }
922
923 void WebGLRenderingContext::reshape(int width, int height)
924 {
925 if (isContextLost())
926 return;
927
928 // This is an approximation because at WebGLRenderingContext level we don't
929 // know if the underlying FBO uses textures or renderbuffers.
930 GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize);
931 // Limit drawing buffer size to 4k to avoid memory exhaustion.
932 const int sizeUpperLimit = 4096;
933 maxSize = std::min(maxSize, sizeUpperLimit);
934 GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]);
935 GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]);
936 width = clamp(width, 1, maxWidth);
937 height = clamp(height, 1, maxHeight);
938
939 if (m_needsUpdate) {
940 RenderBox* renderBox = canvas()->renderBox();
941 if (renderBox && renderBox->hasAcceleratedCompositing())
942 renderBox->contentChanged(CanvasChanged);
943 m_needsUpdate = false;
944 }
945
946 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
947 // clear (and this matches what reshape will do).
948 m_drawingBuffer->reset(IntSize(width, height));
949 restoreStateAfterClear();
950
951 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_texture Units[m_activeTextureUnit].m_texture2DBinding.get()));
952 m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_ renderbufferBinding.get()));
953 if (m_framebufferBinding)
954 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_ framebufferBinding.get()));
955 }
956
957 int WebGLRenderingContext::drawingBufferWidth() const
958 {
959 return m_drawingBuffer->size().width();
960 }
961
962 int WebGLRenderingContext::drawingBufferHeight() const
963 {
964 return m_drawingBuffer->size().height();
965 }
966
967 unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type)
968 {
969 switch (type) {
970 case GraphicsContext3D::BYTE:
971 return sizeof(GC3Dbyte);
972 case GraphicsContext3D::UNSIGNED_BYTE:
973 return sizeof(GC3Dubyte);
974 case GraphicsContext3D::SHORT:
975 return sizeof(GC3Dshort);
976 case GraphicsContext3D::UNSIGNED_SHORT:
977 return sizeof(GC3Dushort);
978 case GraphicsContext3D::INT:
979 return sizeof(GC3Dint);
980 case GraphicsContext3D::UNSIGNED_INT:
981 return sizeof(GC3Duint);
982 case GraphicsContext3D::FLOAT:
983 return sizeof(GC3Dfloat);
984 }
985 ASSERT_NOT_REACHED();
986 return 0;
987 }
988
989 void WebGLRenderingContext::activeTexture(GC3Denum texture)
990 {
991 if (isContextLost())
992 return;
993 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) {
994 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "tex ture unit out of range");
995 return;
996 }
997 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0;
998 m_context->activeTexture(texture);
999
1000 m_drawingBuffer->setActiveTextureUnit(texture);
1001
1002 }
1003
1004 void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* sha der)
1005 {
1006 if (isContextLost() || !validateWebGLObject("attachShader", program) || !val idateWebGLObject("attachShader", shader))
1007 return;
1008 if (!program->attachShader(shader)) {
1009 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader");
1010 return;
1011 }
1012 m_context->attachShader(objectOrZero(program), objectOrZero(shader));
1013 shader->onAttached();
1014 }
1015
1016 void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint i ndex, const String& name)
1017 {
1018 if (isContextLost() || !validateWebGLObject("bindAttribLocation", program))
1019 return;
1020 if (!validateLocationLength("bindAttribLocation", name))
1021 return;
1022 if (!validateString("bindAttribLocation", name))
1023 return;
1024 if (isPrefixReserved(name)) {
1025 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocat ion", "reserved prefix");
1026 return;
1027 }
1028 if (index >= m_maxVertexAttribs) {
1029 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation" , "index out of range");
1030 return;
1031 }
1032 m_context->bindAttribLocation(objectOrZero(program), index, name);
1033 }
1034
1035 bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGL Object* object, bool& deleted)
1036 {
1037 deleted = false;
1038 if (isContextLost())
1039 return false;
1040 if (object) {
1041 if (!object->validate(contextGroup(), this)) {
1042 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "object not from this context");
1043 return false;
1044 }
1045 deleted = !object->object();
1046 }
1047 return true;
1048 }
1049
1050 void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer)
1051 {
1052 bool deleted;
1053 if (!checkObjectToBeBound("bindBuffer", buffer, deleted))
1054 return;
1055 if (deleted)
1056 buffer = 0;
1057 if (buffer && buffer->getTarget() && buffer->getTarget() != target) {
1058 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "b uffers can not be used with multiple targets");
1059 return;
1060 }
1061 if (target == GraphicsContext3D::ARRAY_BUFFER)
1062 m_boundArrayBuffer = buffer;
1063 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
1064 m_boundVertexArrayObject->setElementArrayBuffer(buffer);
1065 else {
1066 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invali d target");
1067 return;
1068 }
1069
1070 m_context->bindBuffer(target, objectOrZero(buffer));
1071 if (buffer)
1072 buffer->setTarget(target);
1073 }
1074
1075 void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* b uffer)
1076 {
1077 bool deleted;
1078 if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted))
1079 return;
1080 if (deleted)
1081 buffer = 0;
1082 if (target != GraphicsContext3D::FRAMEBUFFER) {
1083 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "i nvalid target");
1084 return;
1085 }
1086 m_framebufferBinding = buffer;
1087 m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get ()));
1088 if (!m_framebufferBinding) {
1089 // Instead of binding fb 0, bind the drawing buffer.
1090 m_drawingBuffer->bind();
1091 } else
1092 m_context->bindFramebuffer(target, objectOrZero(buffer));
1093 if (buffer)
1094 buffer->setHasEverBeenBound();
1095 applyStencilTest();
1096 }
1097
1098 void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer)
1099 {
1100 bool deleted;
1101 if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted))
1102 return;
1103 if (deleted)
1104 renderBuffer = 0;
1105 if (target != GraphicsContext3D::RENDERBUFFER) {
1106 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", " invalid target");
1107 return;
1108 }
1109 m_renderbufferBinding = renderBuffer;
1110 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer));
1111 if (renderBuffer)
1112 renderBuffer->setHasEverBeenBound();
1113 }
1114
1115 void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture)
1116 {
1117 bool deleted;
1118 if (!checkObjectToBeBound("bindTexture", texture, deleted))
1119 return;
1120 if (deleted)
1121 texture = 0;
1122 if (texture && texture->getTarget() && texture->getTarget() != target) {
1123 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", " textures can not be used with multiple targets");
1124 return;
1125 }
1126 GC3Dint maxLevel = 0;
1127 if (target == GraphicsContext3D::TEXTURE_2D) {
1128 m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
1129 maxLevel = m_maxTextureLevel;
1130
1131 if (!m_activeTextureUnit)
1132 m_drawingBuffer->setTexture2DBinding(objectOrZero(texture));
1133
1134 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
1135 m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
1136 maxLevel = m_maxCubeMapTextureLevel;
1137 } else {
1138 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "inval id target");
1139 return;
1140 }
1141
1142 m_context->bindTexture(target, objectOrZero(texture));
1143 if (texture) {
1144 texture->setTarget(target, maxLevel);
1145 m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePl usMaxNonDefaultTextureUnit);
1146 } else {
1147 // If the disabled index is the current maximum, trace backwards to find the new max enabled texture index
1148 if (m_onePlusMaxNonDefaultTextureUnit == m_activeTextureUnit + 1) {
1149 findNewMaxNonDefaultTextureUnit();
1150 }
1151 }
1152
1153 // Note: previously we used to automatically set the TEXTURE_WRAP_R
1154 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL
1155 // ES 2.0 doesn't expose this flag (a bug in the specification) and
1156 // otherwise the application has no control over the seams in this
1157 // dimension. However, it appears that supporting this properly on all
1158 // platforms is fairly involved (will require a HashMap from texture ID
1159 // in all ports), and we have not had any complaints, so the logic has
1160 // been removed.
1161
1162 }
1163
1164 void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha)
1165 {
1166 if (isContextLost())
1167 return;
1168 m_context->blendColor(red, green, blue, alpha);
1169 }
1170
1171 void WebGLRenderingContext::blendEquation(GC3Denum mode)
1172 {
1173 if (isContextLost() || !validateBlendEquation("blendEquation", mode))
1174 return;
1175 m_context->blendEquation(mode);
1176 }
1177
1178 void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum mod eAlpha)
1179 {
1180 if (isContextLost() || !validateBlendEquation("blendEquationSeparate", modeR GB) || !validateBlendEquation("blendEquationSeparate", modeAlpha))
1181 return;
1182 m_context->blendEquationSeparate(modeRGB, modeAlpha);
1183 }
1184
1185
1186 void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
1187 {
1188 if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfact or))
1189 return;
1190 m_context->blendFunc(sfactor, dfactor);
1191 }
1192
1193 void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
1194 {
1195 // Note: Alpha does not have the same restrictions as RGB.
1196 if (isContextLost() || !validateBlendFuncFactors("blendFuncSeparate", srcRGB , dstRGB))
1197 return;
1198 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
1199 }
1200
1201 void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage)
1202 {
1203 if (isContextLost())
1204 return;
1205 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usa ge);
1206 if (!buffer)
1207 return;
1208 if (size < 0) {
1209 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0");
1210 return;
1211 }
1212 if (!size) {
1213 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0");
1214 return;
1215 }
1216
1217 m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage);
1218 }
1219
1220 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3De num usage)
1221 {
1222 if (isContextLost())
1223 return;
1224 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usa ge);
1225 if (!buffer)
1226 return;
1227 if (!data) {
1228 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no da ta");
1229 return;
1230 }
1231 m_context->bufferData(target, data->byteLength(), data->data(), usage);
1232 }
1233
1234 void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, G C3Denum usage)
1235 {
1236 if (isContextLost())
1237 return;
1238 WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usa ge);
1239 if (!buffer)
1240 return;
1241 if (!data) {
1242 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no da ta");
1243 return;
1244 }
1245
1246 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage );
1247 }
1248
1249 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, Arr ayBuffer* data)
1250 {
1251 if (isContextLost())
1252 return;
1253 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1254 if (!buffer)
1255 return;
1256 if (offset < 0) {
1257 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "of fset < 0");
1258 return;
1259 }
1260 if (!data)
1261 return;
1262
1263 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byte Length(), data->data());
1264 }
1265
1266 void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, Arr ayBufferView* data)
1267 {
1268 if (isContextLost())
1269 return;
1270 WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
1271 if (!buffer)
1272 return;
1273 if (offset < 0) {
1274 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "of fset < 0");
1275 return;
1276 }
1277 if (!data)
1278 return;
1279
1280 m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byte Length(), data->baseAddress());
1281 }
1282
1283 GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target)
1284 {
1285 if (isContextLost())
1286 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED;
1287 if (target != GraphicsContext3D::FRAMEBUFFER) {
1288 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStat us", "invalid target");
1289 return 0;
1290 }
1291 if (!m_framebufferBinding || !m_framebufferBinding->object())
1292 return GraphicsContext3D::FRAMEBUFFER_COMPLETE;
1293 const char* reason = "framebuffer incomplete";
1294 GC3Denum result = m_framebufferBinding->checkStatus(&reason);
1295 if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1296 emitGLWarning("checkFramebufferStatus", reason);
1297 return result;
1298 }
1299 result = m_context->checkFramebufferStatus(target);
1300 return result;
1301 }
1302
1303 void WebGLRenderingContext::clear(GC3Dbitfield mask)
1304 {
1305 if (isContextLost())
1306 return;
1307 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_ BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1308 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid ma sk");
1309 return;
1310 }
1311 const char* reason = "framebuffer incomplete";
1312 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
1313 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "cle ar", reason);
1314 return;
1315 }
1316 if (!clearIfComposited(mask))
1317 m_context->clear(mask);
1318 markContextChanged();
1319 }
1320
1321 void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC 3Dfloat a)
1322 {
1323 if (isContextLost())
1324 return;
1325 if (std::isnan(r))
1326 r = 0;
1327 if (std::isnan(g))
1328 g = 0;
1329 if (std::isnan(b))
1330 b = 0;
1331 if (std::isnan(a))
1332 a = 1;
1333 m_clearColor[0] = r;
1334 m_clearColor[1] = g;
1335 m_clearColor[2] = b;
1336 m_clearColor[3] = a;
1337 m_context->clearColor(r, g, b, a);
1338 }
1339
1340 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
1341 {
1342 if (isContextLost())
1343 return;
1344 m_clearDepth = depth;
1345 m_context->clearDepth(depth);
1346 }
1347
1348 void WebGLRenderingContext::clearStencil(GC3Dint s)
1349 {
1350 if (isContextLost())
1351 return;
1352 m_clearStencil = s;
1353 m_context->clearStencil(s);
1354 }
1355
1356 void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dbo olean blue, GC3Dboolean alpha)
1357 {
1358 if (isContextLost())
1359 return;
1360 m_colorMask[0] = red;
1361 m_colorMask[1] = green;
1362 m_colorMask[2] = blue;
1363 m_colorMask[3] = alpha;
1364 m_context->colorMask(red, green, blue, alpha);
1365 }
1366
1367 void WebGLRenderingContext::compileShader(WebGLShader* shader)
1368 {
1369 if (isContextLost() || !validateWebGLObject("compileShader", shader))
1370 return;
1371 m_context->compileShader(objectOrZero(shader));
1372 }
1373
1374 void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width,
1375 GC3Dsizei height, GC3Dint borde r, ArrayBufferView* data)
1376 {
1377 if (isContextLost())
1378 return;
1379 if (!validateTexFuncLevel("compressedTexImage2D", target, level))
1380 return;
1381
1382 if (!validateCompressedTexFormat(internalformat)) {
1383 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D ", "invalid internalformat");
1384 return;
1385 }
1386 if (border) {
1387 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2 D", "border not 0");
1388 return;
1389 }
1390 if (!validateCompressedTexDimensions("compressedTexImage2D", NotTexSubImage2 D, target, level, width, height, internalformat))
1391 return;
1392 if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, in ternalformat, data))
1393 return;
1394
1395 WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, t rue);
1396 if (!tex)
1397 return;
1398 if (!isGLES2NPOTStrict()) {
1399 if (level && WebGLTexture::isNPOT(width, height)) {
1400 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexIm age2D", "level > 0 not power of 2");
1401 return;
1402 }
1403 }
1404 graphicsContext3D()->compressedTexImage2D(target, level, internalformat, wid th, height,
1405 border, data->byteLength(), data-> baseAddress());
1406 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsCont ext3D::UNSIGNED_BYTE);
1407 }
1408
1409 void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint lev el, GC3Dint xoffset, GC3Dint yoffset,
1410 GC3Dsizei width, GC3Dsizei h eight, GC3Denum format, ArrayBufferView* data)
1411 {
1412 if (isContextLost())
1413 return;
1414 if (!validateTexFuncLevel("compressedTexSubImage2D", target, level))
1415 return;
1416 if (!validateCompressedTexFormat(format)) {
1417 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImag e2D", "invalid format");
1418 return;
1419 }
1420 if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data))
1421 return;
1422
1423 WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target , true);
1424 if (!tex)
1425 return;
1426
1427 if (format != tex->getInternalFormat(target, level)) {
1428 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSu bImage2D", "format does not match texture format");
1429 return;
1430 }
1431
1432 if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, l evel, xoffset, yoffset, width, height, format, tex))
1433 return;
1434
1435 graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset ,
1436 width, height, format, data->by teLength(), data->baseAddress());
1437 }
1438
1439 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format)
1440 {
1441 if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DE PTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
1442 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "f ormat can not be set, only rendered to");
1443 return false;
1444 }
1445 return true;
1446 }
1447
1448 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3De num internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3 Dint border)
1449 {
1450 if (isContextLost())
1451 return;
1452 if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, l evel, internalformat, width, height, border, internalformat, GraphicsContext3D:: UNSIGNED_BYTE))
1453 return;
1454 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
1455 return;
1456 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
1457 if (!tex)
1458 return;
1459 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBound FramebufferColorFormat())) {
1460 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D" , "framebuffer is incompatible format");
1461 return;
1462 }
1463 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
1464 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "l evel > 0 not power of 2");
1465 return;
1466 }
1467 const char* reason = "framebuffer incomplete";
1468 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
1469 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "cop yTexImage2D", reason);
1470 return;
1471 }
1472 clearIfComposited();
1473 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding .get());
1474 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height , border);
1475 // FIXME: if the framebuffer is not complete, none of the below should be ex ecuted.
1476 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsCont ext3D::UNSIGNED_BYTE);
1477 }
1478
1479 void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC 3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1480 {
1481 if (isContextLost())
1482 return;
1483 if (!validateTexFuncLevel("copyTexSubImage2D", target, level))
1484 return;
1485 WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true );
1486 if (!tex)
1487 return;
1488 if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("c opyTexSubImage2D", width, height))
1489 return;
1490 // Before checking if it is in the range, check if overflow happens first.
1491 if (xoffset + width < 0 || yoffset + height < 0) {
1492 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions");
1493 return;
1494 }
1495 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex ->getHeight(target, level)) {
1496 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range");
1497 return;
1498 }
1499 GC3Denum internalformat = tex->getInternalFormat(target, level);
1500 if (!validateSettableTexFormat("copyTexSubImage2D", internalformat))
1501 return;
1502 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBound FramebufferColorFormat())) {
1503 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage 2D", "framebuffer is incompatible format");
1504 return;
1505 }
1506 const char* reason = "framebuffer incomplete";
1507 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
1508 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "cop yTexSubImage2D", reason);
1509 return;
1510 }
1511 clearIfComposited();
1512 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding .get());
1513 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, h eight);
1514 }
1515
1516 PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer()
1517 {
1518 if (isContextLost())
1519 return 0;
1520 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this);
1521 addSharedObject(o.get());
1522 return o;
1523 }
1524
1525 PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer()
1526 {
1527 if (isContextLost())
1528 return 0;
1529 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this);
1530 addContextObject(o.get());
1531 return o;
1532 }
1533
1534 PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture()
1535 {
1536 if (isContextLost())
1537 return 0;
1538 RefPtr<WebGLTexture> o = WebGLTexture::create(this);
1539 addSharedObject(o.get());
1540 return o;
1541 }
1542
1543 PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram()
1544 {
1545 if (isContextLost())
1546 return 0;
1547 RefPtr<WebGLProgram> o = WebGLProgram::create(this);
1548 addSharedObject(o.get());
1549 return o;
1550 }
1551
1552 PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer()
1553 {
1554 if (isContextLost())
1555 return 0;
1556 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this);
1557 addSharedObject(o.get());
1558 return o;
1559 }
1560
1561 WebGLRenderbuffer* WebGLRenderingContext::ensureEmulatedStencilBuffer(GC3Denum t arget, WebGLRenderbuffer* renderbuffer)
1562 {
1563 if (isContextLost())
1564 return 0;
1565 if (!renderbuffer->emulatedStencilBuffer()) {
1566 renderbuffer->setEmulatedStencilBuffer(createRenderbuffer());
1567 m_context->bindRenderbuffer(target, objectOrZero(renderbuffer->emulatedS tencilBuffer()));
1568 m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.g et()));
1569 }
1570 return renderbuffer->emulatedStencilBuffer();
1571 }
1572
1573 PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type)
1574 {
1575 if (isContextLost())
1576 return 0;
1577 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::F RAGMENT_SHADER) {
1578 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "inva lid shader type");
1579 return 0;
1580 }
1581
1582 RefPtr<WebGLShader> o = WebGLShader::create(this, type);
1583 addSharedObject(o.get());
1584 return o;
1585 }
1586
1587 void WebGLRenderingContext::cullFace(GC3Denum mode)
1588 {
1589 if (isContextLost())
1590 return;
1591 switch (mode) {
1592 case GraphicsContext3D::FRONT_AND_BACK:
1593 case GraphicsContext3D::FRONT:
1594 case GraphicsContext3D::BACK:
1595 break;
1596 default:
1597 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "cullFace", "invalid mode");
1598 return;
1599 }
1600 m_context->cullFace(mode);
1601 }
1602
1603 bool WebGLRenderingContext::deleteObject(WebGLObject* object)
1604 {
1605 if (isContextLost() || !object)
1606 return false;
1607 if (!object->validate(contextGroup(), this)) {
1608 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "objec t does not belong to this context");
1609 return false;
1610 }
1611 if (object->object())
1612 // We need to pass in context here because we want
1613 // things in this context unbound.
1614 object->deleteObject(graphicsContext3D());
1615 return true;
1616 }
1617
1618 void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer)
1619 {
1620 if (!deleteObject(buffer))
1621 return;
1622 if (m_boundArrayBuffer == buffer)
1623 m_boundArrayBuffer = 0;
1624
1625 m_boundVertexArrayObject->unbindBuffer(buffer);
1626 }
1627
1628 void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer)
1629 {
1630 if (!deleteObject(framebuffer))
1631 return;
1632 if (framebuffer == m_framebufferBinding) {
1633 m_framebufferBinding = 0;
1634 m_drawingBuffer->setFramebufferBinding(0);
1635 // Have to call bindFramebuffer here to bind back to internal fbo.
1636 m_drawingBuffer->bind();
1637 }
1638 }
1639
1640 void WebGLRenderingContext::deleteProgram(WebGLProgram* program)
1641 {
1642 deleteObject(program);
1643 // We don't reset m_currentProgram to 0 here because the deletion of the
1644 // current program is delayed.
1645 }
1646
1647 void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer)
1648 {
1649 if (!deleteObject(renderbuffer))
1650 return;
1651 if (renderbuffer == m_renderbufferBinding)
1652 m_renderbufferBinding = 0;
1653 if (m_framebufferBinding)
1654 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer) ;
1655 }
1656
1657 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
1658 {
1659 deleteObject(shader);
1660 }
1661
1662 void WebGLRenderingContext::deleteTexture(WebGLTexture* texture)
1663 {
1664 if (!deleteObject(texture))
1665 return;
1666
1667 int maxBoundTextureIndex = -1;
1668 for (size_t i = 0; i < m_onePlusMaxNonDefaultTextureUnit; ++i) {
1669 if (texture == m_textureUnits[i].m_texture2DBinding) {
1670 m_textureUnits[i].m_texture2DBinding = 0;
1671 maxBoundTextureIndex = i;
1672 if (!i)
1673 m_drawingBuffer->setTexture2DBinding(0);
1674 }
1675 if (texture == m_textureUnits[i].m_textureCubeMapBinding) {
1676 m_textureUnits[i].m_textureCubeMapBinding = 0;
1677 maxBoundTextureIndex = i;
1678 }
1679 }
1680 if (m_framebufferBinding)
1681 m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture);
1682
1683 // If the deleted was bound to the the current maximum index, trace backward s to find the new max texture index
1684 if (m_onePlusMaxNonDefaultTextureUnit == maxBoundTextureIndex + 1) {
1685 findNewMaxNonDefaultTextureUnit();
1686 }
1687 }
1688
1689 void WebGLRenderingContext::depthFunc(GC3Denum func)
1690 {
1691 if (isContextLost())
1692 return;
1693 if (!validateStencilOrDepthFunc("depthFunc", func))
1694 return;
1695 m_context->depthFunc(func);
1696 }
1697
1698 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
1699 {
1700 if (isContextLost())
1701 return;
1702 m_depthMask = flag;
1703 m_context->depthMask(flag);
1704 }
1705
1706 void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar)
1707 {
1708 if (isContextLost())
1709 return;
1710 if (zNear > zFar) {
1711 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "z Near > zFar");
1712 return;
1713 }
1714 m_context->depthRange(zNear, zFar);
1715 }
1716
1717 void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* sha der)
1718 {
1719 if (isContextLost() || !validateWebGLObject("detachShader", program) || !val idateWebGLObject("detachShader", shader))
1720 return;
1721 if (!program->detachShader(shader)) {
1722 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached");
1723 return;
1724 }
1725 m_context->detachShader(objectOrZero(program), objectOrZero(shader));
1726 shader->onDetached(graphicsContext3D());
1727 }
1728
1729 void WebGLRenderingContext::disable(GC3Denum cap)
1730 {
1731 if (isContextLost() || !validateCapability("disable", cap))
1732 return;
1733 if (cap == GraphicsContext3D::STENCIL_TEST) {
1734 m_stencilEnabled = false;
1735 applyStencilTest();
1736 return;
1737 }
1738 if (cap == GraphicsContext3D::SCISSOR_TEST) {
1739 m_scissorEnabled = false;
1740 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1741 }
1742 m_context->disable(cap);
1743 }
1744
1745 void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index)
1746 {
1747 if (isContextLost())
1748 return;
1749 if (index >= m_maxVertexAttribs) {
1750 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttrib Array", "index out of range");
1751 return;
1752 }
1753
1754 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObje ct->getVertexAttribState(index);
1755 state.enabled = false;
1756
1757 // If the disabled index is the current maximum, trace backwards to find the new max enabled attrib index
1758 if (m_onePlusMaxEnabledAttribIndex == index + 1) {
1759 findNewMaxEnabledAttribIndex();
1760 }
1761
1762 m_context->disableVertexAttribArray(index);
1763 }
1764
1765 bool WebGLRenderingContext::validateRenderingState()
1766 {
1767 if (!m_currentProgram)
1768 return false;
1769
1770 // Look in each enabled vertex attrib and check if they've been bound to a b uffer.
1771 for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) {
1772 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVerte xArrayObject->getVertexAttribState(i);
1773 if (state.enabled
1774 && (!state.bufferBinding || !state.bufferBinding->object()))
1775 return false;
1776 }
1777
1778 return true;
1779 }
1780
1781 bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLO bject* object)
1782 {
1783 if (!object || !object->object()) {
1784 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ob ject or object deleted");
1785 return false;
1786 }
1787 if (!object->validate(contextGroup(), this)) {
1788 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "o bject does not belong to this context");
1789 return false;
1790 }
1791 return true;
1792 }
1793
1794 void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei c ount)
1795 {
1796 if (!validateDrawArrays("drawArrays", mode, first, count))
1797 return;
1798
1799 clearIfComposited();
1800
1801 handleTextureCompleteness("drawArrays", true);
1802 m_context->drawArrays(mode, first, count);
1803 handleTextureCompleteness("drawArrays", false);
1804 markContextChanged();
1805 }
1806
1807 void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denu m type, long long offset)
1808 {
1809 if (!validateDrawElements("drawElements", mode, count, type, offset))
1810 return;
1811
1812 clearIfComposited();
1813
1814 handleTextureCompleteness("drawElements", true);
1815 m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset));
1816 handleTextureCompleteness("drawElements", false);
1817 markContextChanged();
1818 }
1819
1820 void WebGLRenderingContext::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint firs t, GC3Dsizei count, GC3Dsizei primcount)
1821 {
1822 if (!validateDrawArrays("drawArraysInstancedANGLE", mode, first, count))
1823 return;
1824
1825 if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount))
1826 return;
1827
1828 clearIfComposited();
1829
1830 handleTextureCompleteness("drawArraysInstancedANGLE", true);
1831 m_context->getExtensions()->drawArraysInstancedANGLE(mode, first, count, pri mcount);
1832 handleTextureCompleteness("drawArraysInstancedANGLE", false);
1833 markContextChanged();
1834 }
1835
1836 void WebGLRenderingContext::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount)
1837 {
1838 if (!validateDrawElements("drawElementsInstancedANGLE", mode, count, type, o ffset))
1839 return;
1840
1841 if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount))
1842 return;
1843
1844 clearIfComposited();
1845
1846 handleTextureCompleteness("drawElementsInstancedANGLE", true);
1847 m_context->getExtensions()->drawElementsInstancedANGLE(mode, count, type, st atic_cast<GC3Dintptr>(offset), primcount);
1848 handleTextureCompleteness("drawElementsInstancedANGLE", false);
1849 markContextChanged();
1850 }
1851
1852 void WebGLRenderingContext::enable(GC3Denum cap)
1853 {
1854 if (isContextLost() || !validateCapability("enable", cap))
1855 return;
1856 if (cap == GraphicsContext3D::STENCIL_TEST) {
1857 m_stencilEnabled = true;
1858 applyStencilTest();
1859 return;
1860 }
1861 if (cap == GraphicsContext3D::SCISSOR_TEST) {
1862 m_scissorEnabled = true;
1863 m_drawingBuffer->setScissorEnabled(m_scissorEnabled);
1864 }
1865 m_context->enable(cap);
1866 }
1867
1868 void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index)
1869 {
1870 if (isContextLost())
1871 return;
1872 if (index >= m_maxVertexAttribs) {
1873 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribA rray", "index out of range");
1874 return;
1875 }
1876
1877 WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObje ct->getVertexAttribState(index);
1878 state.enabled = true;
1879
1880 m_onePlusMaxEnabledAttribIndex = max(index + 1, m_onePlusMaxEnabledAttribInd ex);
1881
1882 m_context->enableVertexAttribArray(index);
1883 }
1884
1885 void WebGLRenderingContext::finish()
1886 {
1887 if (isContextLost())
1888 return;
1889 m_context->flush(); // Intentionally a flush, not a finish.
1890 }
1891
1892 void WebGLRenderingContext::flush()
1893 {
1894 if (isContextLost())
1895 return;
1896 m_context->flush();
1897 }
1898
1899 void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum at tachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer)
1900 {
1901 if (isContextLost() || !validateFramebufferFuncParameters("framebufferRender buffer", target, attachment))
1902 return;
1903 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) {
1904 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuf fer", "invalid target");
1905 return;
1906 }
1907 if (buffer && !buffer->validate(contextGroup(), this)) {
1908 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRend erbuffer", "no buffer or buffer not from this context");
1909 return;
1910 }
1911 // Don't allow the default framebuffer to be mutated; all current
1912 // implementations use an FBO internally in place of the default
1913 // FBO.
1914 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1915 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRend erbuffer", "no framebuffer bound");
1916 return;
1917 }
1918 Platform3DObject bufferObject = objectOrZero(buffer);
1919 switch (attachment) {
1920 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1921 if (isDepthStencilSupported() || !buffer) {
1922 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ ATTACHMENT, renderbuffertarget, bufferObject);
1923 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCI L_ATTACHMENT, renderbuffertarget, bufferObject);
1924 } else {
1925 WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuff er(renderbuffertarget, buffer);
1926 if (!emulatedStencilBuffer) {
1927 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "framebuffer Renderbuffer", "out of memory");
1928 return;
1929 }
1930 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ ATTACHMENT, renderbuffertarget, bufferObject);
1931 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCI L_ATTACHMENT, renderbuffertarget, objectOrZero(emulatedStencilBuffer));
1932 }
1933 break;
1934 default:
1935 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarge t, bufferObject);
1936 }
1937 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer);
1938 applyStencilTest();
1939 }
1940
1941 void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attac hment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level)
1942 {
1943 if (isContextLost() || !validateFramebufferFuncParameters("framebufferTextur e2D", target, attachment))
1944 return;
1945 if (level) {
1946 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2 D", "level not 0");
1947 return;
1948 }
1949 if (texture && !texture->validate(contextGroup(), this)) {
1950 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferText ure2D", "no texture or texture not from this context");
1951 return;
1952 }
1953 // Don't allow the default framebuffer to be mutated; all current
1954 // implementations use an FBO internally in place of the default
1955 // FBO.
1956 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
1957 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferText ure2D", "no framebuffer bound");
1958 return;
1959 }
1960 Platform3DObject textureObject = objectOrZero(texture);
1961 switch (attachment) {
1962 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
1963 m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHM ENT, textarget, textureObject, level);
1964 m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTAC HMENT, textarget, textureObject, level);
1965 break;
1966 case GraphicsContext3D::DEPTH_ATTACHMENT:
1967 m_context->framebufferTexture2D(target, attachment, textarget, textureOb ject, level);
1968 break;
1969 case GraphicsContext3D::STENCIL_ATTACHMENT:
1970 m_context->framebufferTexture2D(target, attachment, textarget, textureOb ject, level);
1971 break;
1972 default:
1973 m_context->framebufferTexture2D(target, attachment, textarget, textureOb ject, level);
1974 }
1975 m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget , texture, level);
1976 applyStencilTest();
1977 }
1978
1979 void WebGLRenderingContext::frontFace(GC3Denum mode)
1980 {
1981 if (isContextLost())
1982 return;
1983 switch (mode) {
1984 case GraphicsContext3D::CW:
1985 case GraphicsContext3D::CCW:
1986 break;
1987 default:
1988 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "frontFace", "invalid mode");
1989 return;
1990 }
1991 m_context->frontFace(mode);
1992 }
1993
1994 void WebGLRenderingContext::generateMipmap(GC3Denum target)
1995 {
1996 if (isContextLost())
1997 return;
1998 WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false);
1999 if (!tex)
2000 return;
2001 if (!tex->canGenerateMipmaps()) {
2002 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap" , "level 0 not power of 2 or not all the same size");
2003 return;
2004 }
2005 if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(targ et, 0)))
2006 return;
2007
2008 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LIN EAR
2009 // on Mac. Remove the hack once this driver bug is fixed.
2010 #if OS(MACOSX)
2011 bool needToResetMinFilter = false;
2012 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) {
2013 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR);
2014 needToResetMinFilter = true;
2015 }
2016 #endif
2017 m_context->generateMipmap(target);
2018 #if OS(MACOSX)
2019 if (needToResetMinFilter)
2020 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter());
2021 #endif
2022 tex->generateMipmapLevelInfo();
2023 }
2024
2025 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index)
2026 {
2027 if (isContextLost() || !validateWebGLObject("getActiveAttrib", program))
2028 return 0;
2029 ActiveInfo info;
2030 if (!m_context->getActiveAttrib(objectOrZero(program), index, info))
2031 return 0;
2032 return WebGLActiveInfo::create(info.name, info.type, info.size);
2033 }
2034
2035 PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram * program, GC3Duint index)
2036 {
2037 if (isContextLost() || !validateWebGLObject("getActiveUniform", program))
2038 return 0;
2039 ActiveInfo info;
2040 if (!m_context->getActiveUniform(objectOrZero(program), index, info))
2041 return 0;
2042 return WebGLActiveInfo::create(info.name, info.type, info.size);
2043 }
2044
2045 bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<Ref Ptr<WebGLShader> >& shaderObjects)
2046 {
2047 shaderObjects.clear();
2048 if (isContextLost() || !validateWebGLObject("getAttachedShaders", program))
2049 return false;
2050
2051 const GC3Denum shaderType[] = {
2052 GraphicsContext3D::VERTEX_SHADER,
2053 GraphicsContext3D::FRAGMENT_SHADER
2054 };
2055 for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) {
2056 WebGLShader* shader = program->getAttachedShader(shaderType[i]);
2057 if (shader)
2058 shaderObjects.append(shader);
2059 }
2060 return true;
2061 }
2062
2063 GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const St ring& name)
2064 {
2065 if (isContextLost() || !validateWebGLObject("getAttribLocation", program))
2066 return -1;
2067 if (!validateLocationLength("getAttribLocation", name))
2068 return -1;
2069 if (!validateString("getAttribLocation", name))
2070 return -1;
2071 if (isPrefixReserved(name))
2072 return -1;
2073 if (!program->getLinkStatus()) {
2074 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocati on", "program not linked");
2075 return 0;
2076 }
2077 return m_context->getAttribLocation(objectOrZero(program), name);
2078 }
2079
2080 WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname)
2081 {
2082 if (isContextLost())
2083 return WebGLGetInfo();
2084 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D ::ELEMENT_ARRAY_BUFFER) {
2085 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target");
2086 return WebGLGetInfo();
2087 }
2088
2089 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::B UFFER_USAGE) {
2090 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name");
2091 return WebGLGetInfo();
2092 }
2093
2094 GC3Dint value = 0;
2095 m_context->getBufferParameteriv(target, pname, &value);
2096 if (pname == GraphicsContext3D::BUFFER_SIZE)
2097 return WebGLGetInfo(value);
2098 return WebGLGetInfo(static_cast<unsigned int>(value));
2099 }
2100
2101 PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
2102 {
2103 if (isContextLost())
2104 return 0;
2105 // We always need to return a new WebGLContextAttributes object to
2106 // prevent the user from mutating any cached version.
2107
2108 // Also, we need to enforce requested values of "false" for depth
2109 // and stencil, regardless of the properties of the underlying
2110 // GraphicsContext3D or DrawingBuffer.
2111 RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m _context->getContextAttributes());
2112 if (!m_attributes.depth)
2113 attributes->setDepth(false);
2114 if (!m_attributes.stencil)
2115 attributes->setStencil(false);
2116 // The DrawingBuffer obtains its parameters from GraphicsContext3D::getConte xtAttributes(),
2117 // but it makes its own determination of whether multisampling is supported.
2118 attributes->setAntialias(m_drawingBuffer->multisample());
2119 return attributes.release();
2120 }
2121
2122 GC3Denum WebGLRenderingContext::getError()
2123 {
2124 if (lost_context_errors_.size()) {
2125 GC3Denum err = lost_context_errors_.first();
2126 lost_context_errors_.remove(0);
2127 return err;
2128 }
2129
2130 if (isContextLost())
2131 return GraphicsContext3D::NO_ERROR;
2132
2133 return m_context->getError();
2134 }
2135
2136 bool WebGLRenderingContext::ExtensionTracker::matchesNameWithPrefixes(const Stri ng& name) const
2137 {
2138 static const char* unprefixed[] = { "", 0, };
2139
2140 const char** prefixes = m_prefixes ? m_prefixes : unprefixed;
2141 for (; *prefixes; ++prefixes) {
2142 String prefixedName = String(*prefixes) + getExtensionName();
2143 if (equalIgnoringCase(prefixedName, name)) {
2144 return true;
2145 }
2146 }
2147 return false;
2148 }
2149
2150 PassRefPtr<WebGLExtension> WebGLRenderingContext::getExtension(const String& nam e)
2151 {
2152 if (isContextLost())
2153 return 0;
2154
2155 for (size_t i = 0; i < m_extensions.size(); ++i) {
2156 ExtensionTracker* tracker = m_extensions[i];
2157 if (tracker->matchesNameWithPrefixes(name)) {
2158 if (tracker->getPrivileged() && !allowPrivilegedExtensions())
2159 return 0;
2160 if (tracker->getDraft() && !RuntimeEnabledFeatures::webGLDraftExtens ionsEnabled())
2161 return 0;
2162 if (!tracker->supported(this))
2163 return 0;
2164 return tracker->getExtension(this);
2165 }
2166 }
2167
2168 return 0;
2169 }
2170
2171 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum t arget, GC3Denum attachment, GC3Denum pname)
2172 {
2173 if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAtt achmentParameter", target, attachment))
2174 return WebGLGetInfo();
2175
2176 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
2177 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferA ttachmentParameter", "no framebuffer bound");
2178 return WebGLGetInfo();
2179 }
2180
2181 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attach ment);
2182 if (!object) {
2183 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
2184 return WebGLGetInfo(GraphicsContext3D::NONE);
2185 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
2186 // specifies INVALID_OPERATION.
2187 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttach mentParameter", "invalid parameter name");
2188 return WebGLGetInfo();
2189 }
2190
2191 ASSERT(object->isTexture() || object->isRenderbuffer());
2192 if (object->isTexture()) {
2193 switch (pname) {
2194 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2195 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
2196 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2197 return WebGLGetInfo(PassRefPtr<WebGLTexture>(static_cast<WebGLTextur e*>(object)));
2198 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
2199 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
2200 {
2201 GC3Dint value = 0;
2202 m_context->getFramebufferAttachmentParameteriv(target, attachmen t, pname, &value);
2203 return WebGLGetInfo(value);
2204 }
2205 default:
2206 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAt tachmentParameter", "invalid parameter name for texture attachment");
2207 return WebGLGetInfo();
2208 }
2209 } else {
2210 switch (pname) {
2211 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
2212 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
2213 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
2214 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(static_cast<WebGLR enderbuffer*>(object)));
2215 default:
2216 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAt tachmentParameter", "invalid parameter name for renderbuffer attachment");
2217 return WebGLGetInfo();
2218 }
2219 }
2220 }
2221
2222 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname)
2223 {
2224 if (isContextLost())
2225 return WebGLGetInfo();
2226 const int intZero = 0;
2227 switch (pname) {
2228 case GraphicsContext3D::ACTIVE_TEXTURE:
2229 return getUnsignedIntParameter(pname);
2230 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
2231 return getWebGLFloatArrayParameter(pname);
2232 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
2233 return getWebGLFloatArrayParameter(pname);
2234 case GraphicsContext3D::ALPHA_BITS:
2235 return getIntParameter(pname);
2236 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
2237 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
2238 case GraphicsContext3D::BLEND:
2239 return getBooleanParameter(pname);
2240 case GraphicsContext3D::BLEND_COLOR:
2241 return getWebGLFloatArrayParameter(pname);
2242 case GraphicsContext3D::BLEND_DST_ALPHA:
2243 return getUnsignedIntParameter(pname);
2244 case GraphicsContext3D::BLEND_DST_RGB:
2245 return getUnsignedIntParameter(pname);
2246 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
2247 return getUnsignedIntParameter(pname);
2248 case GraphicsContext3D::BLEND_EQUATION_RGB:
2249 return getUnsignedIntParameter(pname);
2250 case GraphicsContext3D::BLEND_SRC_ALPHA:
2251 return getUnsignedIntParameter(pname);
2252 case GraphicsContext3D::BLEND_SRC_RGB:
2253 return getUnsignedIntParameter(pname);
2254 case GraphicsContext3D::BLUE_BITS:
2255 return getIntParameter(pname);
2256 case GraphicsContext3D::COLOR_CLEAR_VALUE:
2257 return getWebGLFloatArrayParameter(pname);
2258 case GraphicsContext3D::COLOR_WRITEMASK:
2259 return getBooleanArrayParameter(pname);
2260 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
2261 return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data( ), m_compressedTextureFormats.size()));
2262 case GraphicsContext3D::CULL_FACE:
2263 return getBooleanParameter(pname);
2264 case GraphicsContext3D::CULL_FACE_MODE:
2265 return getUnsignedIntParameter(pname);
2266 case GraphicsContext3D::CURRENT_PROGRAM:
2267 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
2268 case GraphicsContext3D::DEPTH_BITS:
2269 if (!m_framebufferBinding && !m_attributes.depth)
2270 return WebGLGetInfo(intZero);
2271 return getIntParameter(pname);
2272 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
2273 return getFloatParameter(pname);
2274 case GraphicsContext3D::DEPTH_FUNC:
2275 return getUnsignedIntParameter(pname);
2276 case GraphicsContext3D::DEPTH_RANGE:
2277 return getWebGLFloatArrayParameter(pname);
2278 case GraphicsContext3D::DEPTH_TEST:
2279 return getBooleanParameter(pname);
2280 case GraphicsContext3D::DEPTH_WRITEMASK:
2281 return getBooleanParameter(pname);
2282 case GraphicsContext3D::DITHER:
2283 return getBooleanParameter(pname);
2284 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
2285 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->ge tElementArrayBuffer()));
2286 case GraphicsContext3D::FRAMEBUFFER_BINDING:
2287 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
2288 case GraphicsContext3D::FRONT_FACE:
2289 return getUnsignedIntParameter(pname);
2290 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2291 return getUnsignedIntParameter(pname);
2292 case GraphicsContext3D::GREEN_BITS:
2293 return getIntParameter(pname);
2294 case GraphicsContext3D::LINE_WIDTH:
2295 return getFloatParameter(pname);
2296 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
2297 return getIntParameter(pname);
2298 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
2299 return getIntParameter(pname);
2300 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
2301 return getIntParameter(pname);
2302 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
2303 return getIntParameter(pname);
2304 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
2305 return getIntParameter(pname);
2306 case GraphicsContext3D::MAX_TEXTURE_SIZE:
2307 return getIntParameter(pname);
2308 case GraphicsContext3D::MAX_VARYING_VECTORS:
2309 return getIntParameter(pname);
2310 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
2311 return getIntParameter(pname);
2312 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
2313 return getIntParameter(pname);
2314 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
2315 return getIntParameter(pname);
2316 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
2317 return getWebGLIntArrayParameter(pname);
2318 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
2319 // FIXME: should we always return 0 for this?
2320 return getIntParameter(pname);
2321 case GraphicsContext3D::PACK_ALIGNMENT:
2322 return getIntParameter(pname);
2323 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
2324 return getFloatParameter(pname);
2325 case GraphicsContext3D::POLYGON_OFFSET_FILL:
2326 return getBooleanParameter(pname);
2327 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
2328 return getFloatParameter(pname);
2329 case GraphicsContext3D::RED_BITS:
2330 return getIntParameter(pname);
2331 case GraphicsContext3D::RENDERBUFFER_BINDING:
2332 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding) );
2333 case GraphicsContext3D::RENDERER:
2334 return WebGLGetInfo(String("WebKit WebGL"));
2335 case GraphicsContext3D::SAMPLE_BUFFERS:
2336 return getIntParameter(pname);
2337 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
2338 return getBooleanParameter(pname);
2339 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
2340 return getFloatParameter(pname);
2341 case GraphicsContext3D::SAMPLES:
2342 return getIntParameter(pname);
2343 case GraphicsContext3D::SCISSOR_BOX:
2344 return getWebGLIntArrayParameter(pname);
2345 case GraphicsContext3D::SCISSOR_TEST:
2346 return getBooleanParameter(pname);
2347 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
2348 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(Graphic sContext3D::SHADING_LANGUAGE_VERSION) + ")");
2349 case GraphicsContext3D::STENCIL_BACK_FAIL:
2350 return getUnsignedIntParameter(pname);
2351 case GraphicsContext3D::STENCIL_BACK_FUNC:
2352 return getUnsignedIntParameter(pname);
2353 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
2354 return getUnsignedIntParameter(pname);
2355 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
2356 return getUnsignedIntParameter(pname);
2357 case GraphicsContext3D::STENCIL_BACK_REF:
2358 return getIntParameter(pname);
2359 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
2360 return getUnsignedIntParameter(pname);
2361 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
2362 return getUnsignedIntParameter(pname);
2363 case GraphicsContext3D::STENCIL_BITS:
2364 if (!m_framebufferBinding && !m_attributes.stencil)
2365 return WebGLGetInfo(intZero);
2366 return getIntParameter(pname);
2367 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
2368 return getIntParameter(pname);
2369 case GraphicsContext3D::STENCIL_FAIL:
2370 return getUnsignedIntParameter(pname);
2371 case GraphicsContext3D::STENCIL_FUNC:
2372 return getUnsignedIntParameter(pname);
2373 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
2374 return getUnsignedIntParameter(pname);
2375 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
2376 return getUnsignedIntParameter(pname);
2377 case GraphicsContext3D::STENCIL_REF:
2378 return getIntParameter(pname);
2379 case GraphicsContext3D::STENCIL_TEST:
2380 return getBooleanParameter(pname);
2381 case GraphicsContext3D::STENCIL_VALUE_MASK:
2382 return getUnsignedIntParameter(pname);
2383 case GraphicsContext3D::STENCIL_WRITEMASK:
2384 return getUnsignedIntParameter(pname);
2385 case GraphicsContext3D::SUBPIXEL_BITS:
2386 return getIntParameter(pname);
2387 case GraphicsContext3D::TEXTURE_BINDING_2D:
2388 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeText ureUnit].m_texture2DBinding));
2389 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
2390 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeText ureUnit].m_textureCubeMapBinding));
2391 case GraphicsContext3D::UNPACK_ALIGNMENT:
2392 return getIntParameter(pname);
2393 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2394 return WebGLGetInfo(m_unpackFlipY);
2395 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2396 return WebGLGetInfo(m_unpackPremultiplyAlpha);
2397 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2398 return WebGLGetInfo(m_unpackColorspaceConversion);
2399 case GraphicsContext3D::VENDOR:
2400 return WebGLGetInfo(String("WebKit"));
2401 case GraphicsContext3D::VERSION:
2402 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext 3D::VERSION) + ")");
2403 case GraphicsContext3D::VIEWPORT:
2404 return getWebGLIntArrayParameter(pname);
2405 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_deri vatives
2406 if (m_oesStandardDerivatives)
2407 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVAT IVE_HINT_OES);
2408 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, OES_standard_derivatives not enabled");
2409 return WebGLGetInfo();
2410 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
2411 if (m_webglDebugRendererInfo)
2412 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER ));
2413 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, WEBGL_debug_renderer_info not enabled");
2414 return WebGLGetInfo();
2415 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
2416 if (m_webglDebugRendererInfo)
2417 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR)) ;
2418 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, WEBGL_debug_renderer_info not enabled");
2419 return WebGLGetInfo();
2420 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
2421 if (m_oesVertexArrayObject) {
2422 if (!m_boundVertexArrayObject->isDefaultObject())
2423 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boun dVertexArrayObject));
2424 return WebGLGetInfo();
2425 }
2426 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, OES_vertex_array_object not enabled");
2427 return WebGLGetInfo();
2428 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_ani sotropic
2429 if (m_extTextureFilterAnisotropic)
2430 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTR OPY_EXT);
2431 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, EXT_texture_filter_anisotropic not enabled");
2432 return WebGLGetInfo();
2433 case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
2434 if (m_webglDrawBuffers)
2435 return WebGLGetInfo(getMaxColorAttachments());
2436 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, WEBGL_draw_buffers not enabled");
2437 return WebGLGetInfo();
2438 case Extensions3D::MAX_DRAW_BUFFERS_EXT:
2439 if (m_webglDrawBuffers)
2440 return WebGLGetInfo(getMaxDrawBuffers());
2441 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name, WEBGL_draw_buffers not enabled");
2442 return WebGLGetInfo();
2443 default:
2444 if (m_webglDrawBuffers
2445 && pname >= Extensions3D::DRAW_BUFFER0_EXT
2446 && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + ge tMaxDrawBuffers())) {
2447 GC3Dint value = GraphicsContext3D::NONE;
2448 if (m_framebufferBinding)
2449 value = m_framebufferBinding->getDrawBuffer(pname);
2450 else // emulated backbuffer
2451 value = m_backDrawBuffer;
2452 return WebGLGetInfo(value);
2453 }
2454 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "inva lid parameter name");
2455 return WebGLGetInfo();
2456 }
2457 }
2458
2459 WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, G C3Denum pname)
2460 {
2461 if (isContextLost() || !validateWebGLObject("getProgramParameter", program))
2462 return WebGLGetInfo();
2463
2464 GC3Dint value = 0;
2465 switch (pname) {
2466 case GraphicsContext3D::DELETE_STATUS:
2467 return WebGLGetInfo(program->isDeleted());
2468 case GraphicsContext3D::VALIDATE_STATUS:
2469 m_context->getProgramiv(objectOrZero(program), pname, &value);
2470 return WebGLGetInfo(static_cast<bool>(value));
2471 case GraphicsContext3D::LINK_STATUS:
2472 return WebGLGetInfo(program->getLinkStatus());
2473 case GraphicsContext3D::ATTACHED_SHADERS:
2474 case GraphicsContext3D::ACTIVE_ATTRIBUTES:
2475 case GraphicsContext3D::ACTIVE_UNIFORMS:
2476 m_context->getProgramiv(objectOrZero(program), pname, &value);
2477 return WebGLGetInfo(value);
2478 default:
2479 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter" , "invalid parameter name");
2480 return WebGLGetInfo();
2481 }
2482 }
2483
2484 String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program)
2485 {
2486 if (isContextLost())
2487 return String();
2488 if (!validateWebGLObject("getProgramInfoLog", program))
2489 return "";
2490 return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program)));
2491 }
2492
2493 WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC 3Denum pname)
2494 {
2495 if (isContextLost())
2496 return WebGLGetInfo();
2497 if (target != GraphicsContext3D::RENDERBUFFER) {
2498 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParam eter", "invalid target");
2499 return WebGLGetInfo();
2500 }
2501 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
2502 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbuffer Parameter", "no renderbuffer bound");
2503 return WebGLGetInfo();
2504 }
2505
2506 GC3Dint value = 0;
2507 switch (pname) {
2508 case GraphicsContext3D::RENDERBUFFER_WIDTH:
2509 case GraphicsContext3D::RENDERBUFFER_HEIGHT:
2510 case GraphicsContext3D::RENDERBUFFER_RED_SIZE:
2511 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE:
2512 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE:
2513 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE:
2514 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE:
2515 m_context->getRenderbufferParameteriv(target, pname, &value);
2516 return WebGLGetInfo(value);
2517 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE:
2518 if (m_renderbufferBinding->emulatedStencilBuffer()) {
2519 m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBindi ng->emulatedStencilBuffer()));
2520 m_context->getRenderbufferParameteriv(target, pname, &value);
2521 m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBindi ng.get()));
2522 } else {
2523 m_context->getRenderbufferParameteriv(target, pname, &value);
2524 }
2525 return WebGLGetInfo(value);
2526 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT:
2527 return WebGLGetInfo(m_renderbufferBinding->getInternalFormat());
2528 default:
2529 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParam eter", "invalid parameter name");
2530 return WebGLGetInfo();
2531 }
2532 }
2533
2534 WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3D enum pname)
2535 {
2536 if (isContextLost() || !validateWebGLObject("getShaderParameter", shader))
2537 return WebGLGetInfo();
2538 GC3Dint value = 0;
2539 switch (pname) {
2540 case GraphicsContext3D::DELETE_STATUS:
2541 return WebGLGetInfo(shader->isDeleted());
2542 case GraphicsContext3D::COMPILE_STATUS:
2543 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2544 return WebGLGetInfo(static_cast<bool>(value));
2545 case GraphicsContext3D::SHADER_TYPE:
2546 m_context->getShaderiv(objectOrZero(shader), pname, &value);
2547 return WebGLGetInfo(static_cast<unsigned int>(value));
2548 default:
2549 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name");
2550 return WebGLGetInfo();
2551 }
2552 }
2553
2554 String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader)
2555 {
2556 if (isContextLost())
2557 return String();
2558 if (!validateWebGLObject("getShaderInfoLog", shader))
2559 return "";
2560 return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader)));
2561 }
2562
2563 PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecision Format(GC3Denum shaderType, GC3Denum precisionType)
2564 {
2565 if (isContextLost())
2566 return 0;
2567 switch (shaderType) {
2568 case GraphicsContext3D::VERTEX_SHADER:
2569 case GraphicsContext3D::FRAGMENT_SHADER:
2570 break;
2571 default:
2572 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFo rmat", "invalid shader type");
2573 return 0;
2574 }
2575 switch (precisionType) {
2576 case GraphicsContext3D::LOW_FLOAT:
2577 case GraphicsContext3D::MEDIUM_FLOAT:
2578 case GraphicsContext3D::HIGH_FLOAT:
2579 case GraphicsContext3D::LOW_INT:
2580 case GraphicsContext3D::MEDIUM_INT:
2581 case GraphicsContext3D::HIGH_INT:
2582 break;
2583 default:
2584 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFo rmat", "invalid precision type");
2585 return 0;
2586 }
2587
2588 GC3Dint range[2] = {0, 0};
2589 GC3Dint precision = 0;
2590 m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &preci sion);
2591 return WebGLShaderPrecisionFormat::create(range[0], range[1], precision);
2592 }
2593
2594 String WebGLRenderingContext::getShaderSource(WebGLShader* shader)
2595 {
2596 if (isContextLost())
2597 return String();
2598 if (!validateWebGLObject("getShaderSource", shader))
2599 return "";
2600 return ensureNotNull(shader->getSource());
2601 }
2602
2603 Vector<String> WebGLRenderingContext::getSupportedExtensions()
2604 {
2605 Vector<String> result;
2606 if (isContextLost())
2607 return result;
2608
2609 for (size_t i = 0; i < m_extensions.size(); ++i) {
2610 ExtensionTracker* tracker = m_extensions[i];
2611 if (tracker->getPrivileged() && !allowPrivilegedExtensions())
2612 continue;
2613 if (tracker->getDraft() && !RuntimeEnabledFeatures::webGLDraftExtensions Enabled())
2614 continue;
2615 if (tracker->supported(this))
2616 result.append(String(tracker->getPrefixed() ? "WEBKIT_" : "") + tra cker->getExtensionName());
2617 }
2618
2619 return result;
2620 }
2621
2622 WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pn ame)
2623 {
2624 if (isContextLost())
2625 return WebGLGetInfo();
2626 WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false) ;
2627 if (!tex)
2628 return WebGLGetInfo();
2629 GC3Dint value = 0;
2630 switch (pname) {
2631 case GraphicsContext3D::TEXTURE_MAG_FILTER:
2632 case GraphicsContext3D::TEXTURE_MIN_FILTER:
2633 case GraphicsContext3D::TEXTURE_WRAP_S:
2634 case GraphicsContext3D::TEXTURE_WRAP_T:
2635 m_context->getTexParameteriv(target, pname, &value);
2636 return WebGLGetInfo(static_cast<unsigned int>(value));
2637 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotr opic
2638 if (m_extTextureFilterAnisotropic) {
2639 m_context->getTexParameteriv(target, pname, &value);
2640 return WebGLGetInfo(static_cast<unsigned int>(value));
2641 }
2642 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "i nvalid parameter name, EXT_texture_filter_anisotropic not enabled");
2643 return WebGLGetInfo();
2644 default:
2645 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "i nvalid parameter name");
2646 return WebGLGetInfo();
2647 }
2648 }
2649
2650 WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebG LUniformLocation* uniformLocation)
2651 {
2652 if (isContextLost() || !validateWebGLObject("getUniform", program))
2653 return WebGLGetInfo();
2654 if (!uniformLocation || uniformLocation->program() != program) {
2655 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "n o uniformlocation or not valid for this program");
2656 return WebGLGetInfo();
2657 }
2658 GC3Dint location = uniformLocation->location();
2659
2660 // FIXME: make this more efficient using WebGLUniformLocation and caching ty pes in it
2661 GC3Dint activeUniforms = 0;
2662 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNI FORMS, &activeUniforms);
2663 for (GC3Dint i = 0; i < activeUniforms; i++) {
2664 ActiveInfo info;
2665 if (!m_context->getActiveUniform(objectOrZero(program), i, info))
2666 return WebGLGetInfo();
2667 // Strip "[0]" from the name if it's an array.
2668 if (info.size > 1 && info.name.endsWith("[0]"))
2669 info.name = info.name.left(info.name.length() - 3);
2670 // If it's an array, we need to iterate through each element, appending "[index]" to the name.
2671 for (GC3Dint index = 0; index < info.size; ++index) {
2672 String name = info.name;
2673 if (info.size > 1 && index >= 1) {
2674 name.append('[');
2675 name.append(String::number(index));
2676 name.append(']');
2677 }
2678 // Now need to look this up by name again to find its location
2679 GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), n ame);
2680 if (loc == location) {
2681 // Found it. Use the type in the ActiveInfo to determine the ret urn type.
2682 GC3Denum baseType;
2683 unsigned int length;
2684 switch (info.type) {
2685 case GraphicsContext3D::BOOL:
2686 baseType = GraphicsContext3D::BOOL;
2687 length = 1;
2688 break;
2689 case GraphicsContext3D::BOOL_VEC2:
2690 baseType = GraphicsContext3D::BOOL;
2691 length = 2;
2692 break;
2693 case GraphicsContext3D::BOOL_VEC3:
2694 baseType = GraphicsContext3D::BOOL;
2695 length = 3;
2696 break;
2697 case GraphicsContext3D::BOOL_VEC4:
2698 baseType = GraphicsContext3D::BOOL;
2699 length = 4;
2700 break;
2701 case GraphicsContext3D::INT:
2702 baseType = GraphicsContext3D::INT;
2703 length = 1;
2704 break;
2705 case GraphicsContext3D::INT_VEC2:
2706 baseType = GraphicsContext3D::INT;
2707 length = 2;
2708 break;
2709 case GraphicsContext3D::INT_VEC3:
2710 baseType = GraphicsContext3D::INT;
2711 length = 3;
2712 break;
2713 case GraphicsContext3D::INT_VEC4:
2714 baseType = GraphicsContext3D::INT;
2715 length = 4;
2716 break;
2717 case GraphicsContext3D::FLOAT:
2718 baseType = GraphicsContext3D::FLOAT;
2719 length = 1;
2720 break;
2721 case GraphicsContext3D::FLOAT_VEC2:
2722 baseType = GraphicsContext3D::FLOAT;
2723 length = 2;
2724 break;
2725 case GraphicsContext3D::FLOAT_VEC3:
2726 baseType = GraphicsContext3D::FLOAT;
2727 length = 3;
2728 break;
2729 case GraphicsContext3D::FLOAT_VEC4:
2730 baseType = GraphicsContext3D::FLOAT;
2731 length = 4;
2732 break;
2733 case GraphicsContext3D::FLOAT_MAT2:
2734 baseType = GraphicsContext3D::FLOAT;
2735 length = 4;
2736 break;
2737 case GraphicsContext3D::FLOAT_MAT3:
2738 baseType = GraphicsContext3D::FLOAT;
2739 length = 9;
2740 break;
2741 case GraphicsContext3D::FLOAT_MAT4:
2742 baseType = GraphicsContext3D::FLOAT;
2743 length = 16;
2744 break;
2745 case GraphicsContext3D::SAMPLER_2D:
2746 case GraphicsContext3D::SAMPLER_CUBE:
2747 baseType = GraphicsContext3D::INT;
2748 length = 1;
2749 break;
2750 default:
2751 // Can't handle this type
2752 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUnif orm", "unhandled type");
2753 return WebGLGetInfo();
2754 }
2755 switch (baseType) {
2756 case GraphicsContext3D::FLOAT: {
2757 GC3Dfloat value[16] = {0};
2758 m_context->getUniformfv(objectOrZero(program), location, val ue);
2759 if (length == 1)
2760 return WebGLGetInfo(value[0]);
2761 return WebGLGetInfo(Float32Array::create(value, length));
2762 }
2763 case GraphicsContext3D::INT: {
2764 GC3Dint value[4] = {0};
2765 m_context->getUniformiv(objectOrZero(program), location, val ue);
2766 if (length == 1)
2767 return WebGLGetInfo(value[0]);
2768 return WebGLGetInfo(Int32Array::create(value, length));
2769 }
2770 case GraphicsContext3D::BOOL: {
2771 GC3Dint value[4] = {0};
2772 m_context->getUniformiv(objectOrZero(program), location, val ue);
2773 if (length > 1) {
2774 bool boolValue[16] = {0};
2775 for (unsigned j = 0; j < length; j++)
2776 boolValue[j] = static_cast<bool>(value[j]);
2777 return WebGLGetInfo(boolValue, length);
2778 }
2779 return WebGLGetInfo(static_cast<bool>(value[0]));
2780 }
2781 default:
2782 notImplemented();
2783 }
2784 }
2785 }
2786 }
2787 // If we get here, something went wrong in our unfortunately complex logic a bove
2788 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown e rror");
2789 return WebGLGetInfo();
2790 }
2791
2792 PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGL Program* program, const String& name)
2793 {
2794 if (isContextLost() || !validateWebGLObject("getUniformLocation", program))
2795 return 0;
2796 if (!validateLocationLength("getUniformLocation", name))
2797 return 0;
2798 if (!validateString("getUniformLocation", name))
2799 return 0;
2800 if (isPrefixReserved(name))
2801 return 0;
2802 if (!program->getLinkStatus()) {
2803 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocat ion", "program not linked");
2804 return 0;
2805 }
2806 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program ), name);
2807 if (uniformLocation == -1)
2808 return 0;
2809 return WebGLUniformLocation::create(program, uniformLocation);
2810 }
2811
2812 WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pna me)
2813 {
2814 if (isContextLost())
2815 return WebGLGetInfo();
2816 if (index >= m_maxVertexAttribs) {
2817 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", " index out of range");
2818 return WebGLGetInfo();
2819 }
2820 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArr ayObject->getVertexAttribState(index);
2821
2822 if (m_angleInstancedArrays && pname == Extensions3D::VERTEX_ATTRIB_ARRAY_DIV ISOR_ANGLE)
2823 return WebGLGetInfo(state.divisor);
2824
2825 switch (pname) {
2826 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
2827 if (!state.bufferBinding || !state.bufferBinding->object())
2828 return WebGLGetInfo();
2829 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding));
2830 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED:
2831 return WebGLGetInfo(state.enabled);
2832 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED:
2833 return WebGLGetInfo(state.normalized);
2834 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE:
2835 return WebGLGetInfo(state.size);
2836 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE:
2837 return WebGLGetInfo(state.originalStride);
2838 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE:
2839 return WebGLGetInfo(state.type);
2840 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB:
2841 return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].valu e, 4));
2842 default:
2843 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "i nvalid parameter name");
2844 return WebGLGetInfo();
2845 }
2846 }
2847
2848 long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
2849 {
2850 if (isContextLost())
2851 return 0;
2852 if (pname != GraphicsContext3D::VERTEX_ATTRIB_ARRAY_POINTER) {
2853 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttribOffse t", "invalid parameter name");
2854 return 0;
2855 }
2856 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname);
2857 return static_cast<long long>(result);
2858 }
2859
2860 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
2861 {
2862 if (isContextLost())
2863 return;
2864 bool isValid = false;
2865 switch (target) {
2866 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
2867 isValid = true;
2868 break;
2869 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_deri vatives
2870 if (m_oesStandardDerivatives)
2871 isValid = true;
2872 break;
2873 }
2874 if (!isValid) {
2875 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid targ et");
2876 return;
2877 }
2878 m_context->hint(target, mode);
2879 }
2880
2881 GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer)
2882 {
2883 if (!buffer || isContextLost())
2884 return 0;
2885
2886 if (!buffer->hasEverBeenBound())
2887 return 0;
2888
2889 return m_context->isBuffer(buffer->object());
2890 }
2891
2892 bool WebGLRenderingContext::isContextLost()
2893 {
2894 return m_contextLost;
2895 }
2896
2897 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
2898 {
2899 if (isContextLost() || !validateCapability("isEnabled", cap))
2900 return 0;
2901 if (cap == GraphicsContext3D::STENCIL_TEST)
2902 return m_stencilEnabled;
2903 return m_context->isEnabled(cap);
2904 }
2905
2906 GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer)
2907 {
2908 if (!framebuffer || isContextLost())
2909 return 0;
2910
2911 if (!framebuffer->hasEverBeenBound())
2912 return 0;
2913
2914 return m_context->isFramebuffer(framebuffer->object());
2915 }
2916
2917 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
2918 {
2919 if (!program || isContextLost())
2920 return 0;
2921
2922 return m_context->isProgram(program->object());
2923 }
2924
2925 GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffe r)
2926 {
2927 if (!renderbuffer || isContextLost())
2928 return 0;
2929
2930 if (!renderbuffer->hasEverBeenBound())
2931 return 0;
2932
2933 return m_context->isRenderbuffer(renderbuffer->object());
2934 }
2935
2936 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
2937 {
2938 if (!shader || isContextLost())
2939 return 0;
2940
2941 return m_context->isShader(shader->object());
2942 }
2943
2944 GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture)
2945 {
2946 if (!texture || isContextLost())
2947 return 0;
2948
2949 if (!texture->hasEverBeenBound())
2950 return 0;
2951
2952 return m_context->isTexture(texture->object());
2953 }
2954
2955 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
2956 {
2957 if (isContextLost())
2958 return;
2959 m_context->lineWidth(width);
2960 }
2961
2962 void WebGLRenderingContext::linkProgram(WebGLProgram* program)
2963 {
2964 if (isContextLost() || !validateWebGLObject("linkProgram", program))
2965 return;
2966
2967 m_context->linkProgram(objectOrZero(program));
2968 program->increaseLinkCount();
2969 }
2970
2971 void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param)
2972 {
2973 if (isContextLost())
2974 return;
2975 switch (pname) {
2976 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
2977 m_unpackFlipY = param;
2978 break;
2979 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
2980 m_unpackPremultiplyAlpha = param;
2981 break;
2982 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
2983 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == Graphi csContext3D::NONE)
2984 m_unpackColorspaceConversion = static_cast<GC3Denum>(param);
2985 else {
2986 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", " invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL");
2987 return;
2988 }
2989 break;
2990 case GraphicsContext3D::PACK_ALIGNMENT:
2991 case GraphicsContext3D::UNPACK_ALIGNMENT:
2992 if (param == 1 || param == 2 || param == 4 || param == 8) {
2993 if (pname == GraphicsContext3D::PACK_ALIGNMENT)
2994 m_packAlignment = param;
2995 else // GraphicsContext3D::UNPACK_ALIGNMENT:
2996 m_unpackAlignment = param;
2997 m_context->pixelStorei(pname, param);
2998 } else {
2999 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", " invalid parameter for alignment");
3000 return;
3001 }
3002 break;
3003 default:
3004 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "inval id parameter name");
3005 return;
3006 }
3007 }
3008
3009 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
3010 {
3011 if (isContextLost())
3012 return;
3013 m_context->polygonOffset(factor, units);
3014 }
3015
3016 void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC 3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels)
3017 {
3018 if (isContextLost())
3019 return;
3020 // Due to WebGL's same-origin restrictions, it is not possible to
3021 // taint the origin using the WebGL API.
3022 ASSERT(canvas()->originClean());
3023 // Validate input parameters.
3024 if (!pixels) {
3025 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no de stination ArrayBufferView");
3026 return;
3027 }
3028 switch (format) {
3029 case GraphicsContext3D::ALPHA:
3030 case GraphicsContext3D::RGB:
3031 case GraphicsContext3D::RGBA:
3032 break;
3033 default:
3034 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invali d format");
3035 return;
3036 }
3037 switch (type) {
3038 case GraphicsContext3D::UNSIGNED_BYTE:
3039 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
3040 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
3041 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
3042 break;
3043 default:
3044 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invali d type");
3045 return;
3046 }
3047 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED _BYTE) {
3048 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "f ormat not RGBA or type not UNSIGNED_BYTE");
3049 return;
3050 }
3051 // Validate array type against pixel type.
3052 if (pixels->getType() != ArrayBufferView::TypeUint8) {
3053 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "A rrayBufferView not Uint8Array");
3054 return;
3055 }
3056 const char* reason = "framebuffer incomplete";
3057 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
3058 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "rea dPixels", reason);
3059 return;
3060 }
3061 // Calculate array size, taking into consideration of PACK_ALIGNMENT.
3062 unsigned int totalBytesRequired = 0;
3063 unsigned int padding = 0;
3064 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, hei ght, m_packAlignment, &totalBytesRequired, &padding);
3065 if (error != GraphicsContext3D::NO_ERROR) {
3066 synthesizeGLError(error, "readPixels", "invalid dimensions");
3067 return;
3068 }
3069 if (pixels->byteLength() < totalBytesRequired) {
3070 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "A rrayBufferView not large enough for dimensions");
3071 return;
3072 }
3073
3074 clearIfComposited();
3075 void* data = pixels->baseAddress();
3076
3077 {
3078 ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBin ding.get());
3079 m_context->readPixels(x, y, width, height, format, type, data);
3080 }
3081
3082 #if OS(MACOSX)
3083 // FIXME: remove this section when GL driver bug on Mac is fixed, i.e.,
3084 // when alpha is off, readPixels should set alpha to 255 instead of 0.
3085 if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) {
3086 unsigned char* pixels = reinterpret_cast<unsigned char*>(data);
3087 for (GC3Dsizei iy = 0; iy < height; ++iy) {
3088 for (GC3Dsizei ix = 0; ix < width; ++ix) {
3089 pixels[3] = 255;
3090 pixels += 4;
3091 }
3092 pixels += padding;
3093 }
3094 }
3095 #endif
3096 }
3097
3098 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum intern alformat, GC3Dsizei width, GC3Dsizei height)
3099 {
3100 if (isContextLost())
3101 return;
3102 if (target != GraphicsContext3D::RENDERBUFFER) {
3103 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage" , "invalid target");
3104 return;
3105 }
3106 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
3107 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferSto rage", "no bound renderbuffer");
3108 return;
3109 }
3110 if (!validateSize("renderbufferStorage", width, height))
3111 return;
3112 switch (internalformat) {
3113 case GraphicsContext3D::DEPTH_COMPONENT16:
3114 case GraphicsContext3D::RGBA4:
3115 case GraphicsContext3D::RGB5_A1:
3116 case GraphicsContext3D::RGB565:
3117 case GraphicsContext3D::STENCIL_INDEX8:
3118 m_context->renderbufferStorage(target, internalformat, width, height);
3119 m_renderbufferBinding->setInternalFormat(internalformat);
3120 m_renderbufferBinding->setSize(width, height);
3121 m_renderbufferBinding->deleteEmulatedStencilBuffer(m_context.get());
3122 break;
3123 case GraphicsContext3D::DEPTH_STENCIL:
3124 if (isDepthStencilSupported()) {
3125 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL 8, width, height);
3126 } else {
3127 WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuff er(target, m_renderbufferBinding.get());
3128 if (!emulatedStencilBuffer) {
3129 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "renderbuffe rStorage", "out of memory");
3130 return;
3131 }
3132 m_context->renderbufferStorage(target, GraphicsContext3D::DEPTH_COMP ONENT16, width, height);
3133 m_context->bindRenderbuffer(target, objectOrZero(emulatedStencilBuff er));
3134 m_context->renderbufferStorage(target, GraphicsContext3D::STENCIL_IN DEX8, width, height);
3135 m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBindi ng.get()));
3136 emulatedStencilBuffer->setSize(width, height);
3137 emulatedStencilBuffer->setInternalFormat(GraphicsContext3D::STENCIL_ INDEX8);
3138 }
3139 m_renderbufferBinding->setSize(width, height);
3140 m_renderbufferBinding->setInternalFormat(internalformat);
3141 break;
3142 default:
3143 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage" , "invalid internalformat");
3144 return;
3145 }
3146 applyStencilTest();
3147 }
3148
3149 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
3150 {
3151 if (isContextLost())
3152 return;
3153 m_context->sampleCoverage(value, invert);
3154 }
3155
3156 void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Ds izei height)
3157 {
3158 if (isContextLost())
3159 return;
3160 if (!validateSize("scissor", width, height))
3161 return;
3162 m_context->scissor(x, y, width, height);
3163 }
3164
3165 void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& stri ng)
3166 {
3167 if (isContextLost() || !validateWebGLObject("shaderSource", shader))
3168 return;
3169 String stringWithoutComments = StripComments(string).result();
3170 if (!validateString("shaderSource", stringWithoutComments))
3171 return;
3172 shader->setSource(string);
3173 m_context->shaderSource(objectOrZero(shader), stringWithoutComments);
3174 }
3175
3176 void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mas k)
3177 {
3178 if (isContextLost())
3179 return;
3180 if (!validateStencilOrDepthFunc("stencilFunc", func))
3181 return;
3182 m_stencilFuncRef = ref;
3183 m_stencilFuncRefBack = ref;
3184 m_stencilFuncMask = mask;
3185 m_stencilFuncMaskBack = mask;
3186 m_context->stencilFunc(func, ref, mask);
3187 }
3188
3189 void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC 3Dint ref, GC3Duint mask)
3190 {
3191 if (isContextLost())
3192 return;
3193 if (!validateStencilOrDepthFunc("stencilFuncSeparate", func))
3194 return;
3195 switch (face) {
3196 case GraphicsContext3D::FRONT_AND_BACK:
3197 m_stencilFuncRef = ref;
3198 m_stencilFuncRefBack = ref;
3199 m_stencilFuncMask = mask;
3200 m_stencilFuncMaskBack = mask;
3201 break;
3202 case GraphicsContext3D::FRONT:
3203 m_stencilFuncRef = ref;
3204 m_stencilFuncMask = mask;
3205 break;
3206 case GraphicsContext3D::BACK:
3207 m_stencilFuncRefBack = ref;
3208 m_stencilFuncMaskBack = mask;
3209 break;
3210 default:
3211 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate" , "invalid face");
3212 return;
3213 }
3214 m_context->stencilFuncSeparate(face, func, ref, mask);
3215 }
3216
3217 void WebGLRenderingContext::stencilMask(GC3Duint mask)
3218 {
3219 if (isContextLost())
3220 return;
3221 m_stencilMask = mask;
3222 m_stencilMaskBack = mask;
3223 m_context->stencilMask(mask);
3224 }
3225
3226 void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
3227 {
3228 if (isContextLost())
3229 return;
3230 switch (face) {
3231 case GraphicsContext3D::FRONT_AND_BACK:
3232 m_stencilMask = mask;
3233 m_stencilMaskBack = mask;
3234 break;
3235 case GraphicsContext3D::FRONT:
3236 m_stencilMask = mask;
3237 break;
3238 case GraphicsContext3D::BACK:
3239 m_stencilMaskBack = mask;
3240 break;
3241 default:
3242 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate" , "invalid face");
3243 return;
3244 }
3245 m_context->stencilMaskSeparate(face, mask);
3246 }
3247
3248 void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zp ass)
3249 {
3250 if (isContextLost())
3251 return;
3252 m_context->stencilOp(fail, zfail, zpass);
3253 }
3254
3255 void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3D enum zfail, GC3Denum zpass)
3256 {
3257 if (isContextLost())
3258 return;
3259 m_context->stencilOpSeparate(face, fail, zfail, zpass);
3260 }
3261
3262 void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3De num internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState& es)
3263 {
3264 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
3265 // FIXME: Handle errors.
3266 WebGLTexture* tex = validateTextureBinding("texImage2D", target, true);
3267 ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, lev el, internalformat, width, height, border, format, type));
3268 ASSERT(tex);
3269 ASSERT(!level || !WebGLTexture::isNPOT(width, height));
3270 ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat));
3271 m_context->texImage2D(target, level, internalformat, width, height,
3272 border, format, type, pixels);
3273 tex->setLevelInfo(target, level, internalformat, width, height, type);
3274 }
3275
3276 void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3De num internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContex t3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionS tate& es)
3277 {
3278 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
3279 Vector<uint8_t> data;
3280 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultip lyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
3281 if (!imageExtractor.extractSucceeded()) {
3282 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad i mage data");
3283 return;
3284 }
3285 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceF ormat();
3286 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
3287 const void* imagePixelData = imageExtractor.imagePixelData();
3288
3289 bool needConversion = true;
3290 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == Graphics Context3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == Gr aphicsContext3D::AlphaDoNothing && !flipY)
3291 needConversion = false;
3292 else {
3293 if (!m_context->packImageData(image, imagePixelData, format, type, flipY , alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHe ight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
3294 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "p ackImage error");
3295 return;
3296 }
3297 }
3298
3299 if (m_unpackAlignment != 1)
3300 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3301 texImage2DBase(target, level, internalformat, image->width(), image->height( ), 0, format, type, needConversion ? data.data() : imagePixelData, es);
3302 if (m_unpackAlignment != 1)
3303 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3304 }
3305
3306 bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncVal idationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Den um target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei he ight, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint y offset)
3307 {
3308 if (!validateTexFuncParameters(functionName, functionType, target, level, in ternalformat, width, height, border, format, type))
3309 return false;
3310
3311 WebGLTexture* texture = validateTextureBinding(functionName, target, true);
3312 if (!texture)
3313 return false;
3314
3315 if (functionType == NotTexSubImage2D) {
3316 if (level && WebGLTexture::isNPOT(width, height)) {
3317 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "l evel > 0 not power of 2");
3318 return false;
3319 }
3320 // For SourceArrayBufferView, function validateTexFuncData() would handl e whether to validate the SettableTexFormat
3321 // by checking if the ArrayBufferView is null or not.
3322 if (sourceType != SourceArrayBufferView) {
3323 if (!validateSettableTexFormat(functionName, format))
3324 return false;
3325 }
3326 } else {
3327 if (!validateSettableTexFormat(functionName, format))
3328 return false;
3329 if (!validateSize(functionName, xoffset, yoffset))
3330 return false;
3331 // Before checking if it is in the range, check if overflow happens firs t.
3332 if (xoffset + width < 0 || yoffset + height < 0) {
3333 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "b ad dimensions");
3334 return false;
3335 }
3336 if (xoffset + width > texture->getWidth(target, level) || yoffset + heig ht > texture->getHeight(target, level)) {
3337 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "d imensions out of range");
3338 return false;
3339 }
3340 if (texture->getInternalFormat(target, level) != format || texture->getT ype(target, level) != type) {
3341 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "type and format do not match texture");
3342 return false;
3343 }
3344 }
3345
3346 return true;
3347 }
3348
3349 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3350 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
3351 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionState& es)
3352 {
3353 if (isContextLost() || !validateTexFuncData("texImage2D", level, width, heig ht, format, type, pixels, NullAllowed)
3354 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferVie w, target, level, internalformat, width, height, border, format, type, 0, 0))
3355 return;
3356 void* data = pixels ? pixels->baseAddress() : 0;
3357 Vector<uint8_t> tempData;
3358 bool changeUnpackAlignment = false;
3359 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3360 if (!m_context->extractTextureData(width, height, format, type,
3361 m_unpackAlignment,
3362 m_unpackFlipY, m_unpackPremultiplyAlp ha,
3363 data,
3364 tempData))
3365 return;
3366 data = tempData.data();
3367 changeUnpackAlignment = true;
3368 }
3369 if (changeUnpackAlignment)
3370 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3371 texImage2DBase(target, level, internalformat, width, height, border, format, type, data, es);
3372 if (changeUnpackAlignment)
3373 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3374 }
3375
3376 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3377 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& es)
3378 {
3379 if (isContextLost() || !pixels || !validateTexFunc("texImage2D", NotTexSubIm age2D, SourceImageData, target, level, internalformat, pixels->width(), pixels-> height(), 0, format, type, 0, 0))
3380 return;
3381 Vector<uint8_t> data;
3382 bool needConversion = true;
3383 // The data from ImageData is always of format RGBA8.
3384 // No conversion is needed if destination format is RGBA and type is USIGNED _BYTE and no Flip or Premultiply operation is required.
3385 if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext 3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE)
3386 needConversion = false;
3387 else {
3388 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_ unpackPremultiplyAlpha, data)) {
3389 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "b ad image data");
3390 return;
3391 }
3392 }
3393 if (m_unpackAlignment != 1)
3394 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3395 texImage2DBase(target, level, internalformat, pixels->width(), pixels->heigh t(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), es) ;
3396 if (m_unpackAlignment != 1)
3397 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3398 }
3399
3400 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3401 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& es)
3402 {
3403 if (isContextLost() || !validateHTMLImageElement("texImage2D", image, es))
3404 return;
3405 Image* imageForRender = image->cachedImage()->imageForRenderer(image->render er());
3406 if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, Sour ceHTMLImageElement, target, level, internalformat, imageForRender->width(), imag eForRender->height(), 0, format, type, 0, 0))
3407 return;
3408
3409 texImage2DImpl(target, level, internalformat, format, type, imageForRender, GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, es);
3410 }
3411
3412 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3413 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& e s)
3414 {
3415 if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, es) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, tar get, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0))
3416 return;
3417
3418 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
3419 // If possible, copy from the canvas element directly to the texture
3420 // via the GPU, without a read-back to system memory.
3421 if (GraphicsContext3D::TEXTURE_2D == target && texture) {
3422 ImageBuffer* buffer = canvas->buffer();
3423 if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->o bject(), internalformat, type, level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
3424 texture->setLevelInfo(target, level, internalformat, canvas->width() , canvas->height(), type);
3425 return;
3426 }
3427 }
3428
3429 RefPtr<ImageData> imageData = canvas->getImageData();
3430 if (imageData)
3431 texImage2D(target, level, internalformat, format, type, imageData.get(), es);
3432 else
3433 texImage2DImpl(target, level, internalformat, format, type, canvas->copi edImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyA lpha, es);
3434 }
3435
3436 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* vid eo, BackingStoreCopy backingStoreCopy)
3437 {
3438 IntSize size(video->videoWidth(), video->videoHeight());
3439 ImageBuffer* buf = m_videoCache.imageBuffer(size);
3440 if (!buf) {
3441 synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out o f memory");
3442 return 0;
3443 }
3444 IntRect destRect(0, 0, size.width(), size.height());
3445 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
3446 video->paintCurrentFrameInContext(buf->context(), destRect);
3447 return buf->copyImage(backingStoreCopy);
3448 }
3449
3450 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
3451 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionState& es)
3452 {
3453 if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, es)
3454 || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoEleme nt, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0))
3455 return;
3456
3457 // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible.
3458 // Otherwise, it will fall back to the normal SW path.
3459 WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
3460 if (GraphicsContext3D::TEXTURE_2D == target && texture) {
3461 if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->o bject(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
3462 texture->setLevelInfo(target, level, internalformat, video->videoWid th(), video->videoHeight(), type);
3463 return;
3464 }
3465 }
3466
3467 // Normal pure SW path.
3468 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMod e());
3469 if (!image)
3470 return;
3471 texImage2DImpl(target, level, internalformat, format, type, image.get(), Gra phicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, es);
3472 }
3473
3474 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfl oat paramf, GC3Dint parami, bool isFloat)
3475 {
3476 if (isContextLost())
3477 return;
3478 WebGLTexture* tex = validateTextureBinding("texParameter", target, false);
3479 if (!tex)
3480 return;
3481 switch (pname) {
3482 case GraphicsContext3D::TEXTURE_MIN_FILTER:
3483 case GraphicsContext3D::TEXTURE_MAG_FILTER:
3484 break;
3485 case GraphicsContext3D::TEXTURE_WRAP_S:
3486 case GraphicsContext3D::TEXTURE_WRAP_T:
3487 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
3488 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
3489 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", " invalid parameter");
3490 return;
3491 }
3492 break;
3493 case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotr opic
3494 if (!m_extTextureFilterAnisotropic) {
3495 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", " invalid parameter, EXT_texture_filter_anisotropic not enabled");
3496 return;
3497 }
3498 break;
3499 default:
3500 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "inva lid parameter name");
3501 return;
3502 }
3503 if (isFloat) {
3504 tex->setParameterf(pname, paramf);
3505 m_context->texParameterf(target, pname, paramf);
3506 } else {
3507 tex->setParameteri(pname, parami);
3508 m_context->texParameteri(target, pname, parami);
3509 }
3510 }
3511
3512 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Df loat param)
3513 {
3514 texParameter(target, pname, param, 0, true);
3515 }
3516
3517 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Di nt param)
3518 {
3519 texParameter(target, pname, 0, param, false);
3520 }
3521
3522 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC 3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum form at, GC3Denum type, const void* pixels, ExceptionState& es)
3523 {
3524 // FIXME: Handle errors.
3525 ASSERT(!isContextLost());
3526 ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, lev el, format, width, height, 0, format, type));
3527 ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
3528 ASSERT(validateSettableTexFormat("texSubImage2D", format));
3529 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
3530 if (!tex) {
3531 ASSERT_NOT_REACHED();
3532 return;
3533 }
3534 ASSERT((xoffset + width) >= 0);
3535 ASSERT((yoffset + height) >= 0);
3536 ASSERT(tex->getWidth(target, level) >= (xoffset + width));
3537 ASSERT(tex->getHeight(target, level) >= (yoffset + height));
3538 ASSERT(tex->getInternalFormat(target, level) == format);
3539 ASSERT(tex->getType(target, level) == type);
3540 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, for mat, type, pixels);
3541 }
3542
3543 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC 3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, Gr aphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha , ExceptionState& es)
3544 {
3545 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
3546 Vector<uint8_t> data;
3547 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultip lyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
3548 if (!imageExtractor.extractSucceeded()) {
3549 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "ba d image");
3550 return;
3551 }
3552 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceF ormat();
3553 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
3554 const void* imagePixelData = imageExtractor.imagePixelData();
3555
3556 bool needConversion = true;
3557 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == Graphics Context3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == Gr aphicsContext3D::AlphaDoNothing && !flipY)
3558 needConversion = false;
3559 else {
3560 if (!m_context->packImageData(image, imagePixelData, format, type, flipY , alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHe ight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
3561 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "b ad image data");
3562 return;
3563 }
3564 }
3565
3566 if (m_unpackAlignment != 1)
3567 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3568 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->he ight(), format, type, needConversion ? data.data() : imagePixelData, es);
3569 if (m_unpackAlignment != 1)
3570 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3571 }
3572
3573 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din t xoffset, GC3Dint yoffset,
3574 GC3Dsizei width, GC3Dsizei height,
3575 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionState& es)
3576 {
3577 if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, h eight, format, type, pixels, NullNotAllowed)
3578 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferVie w, target, level, format, width, height, 0, format, type, xoffset, yoffset))
3579 return;
3580 void* data = pixels->baseAddress();
3581 Vector<uint8_t> tempData;
3582 bool changeUnpackAlignment = false;
3583 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
3584 if (!m_context->extractTextureData(width, height, format, type,
3585 m_unpackAlignment,
3586 m_unpackFlipY, m_unpackPremultiplyAlp ha,
3587 data,
3588 tempData))
3589 return;
3590 data = tempData.data();
3591 changeUnpackAlignment = true;
3592 }
3593 if (changeUnpackAlignment)
3594 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3595 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, ty pe, data, es);
3596 if (changeUnpackAlignment)
3597 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3598 }
3599
3600 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din t xoffset, GC3Dint yoffset,
3601 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& es)
3602 {
3603 if (isContextLost() || !pixels || !validateTexFunc("texSubImage2D", TexSubIm age2D, SourceImageData, target, level, format, pixels->width(), pixels->height( ), 0, format, type, xoffset, yoffset))
3604 return;
3605
3606 Vector<uint8_t> data;
3607 bool needConversion = true;
3608 // The data from ImageData is always of format RGBA8.
3609 // No conversion is needed if destination format is RGBA and type is USIGNED _BYTE and no Flip or Premultiply operation is required.
3610 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED _BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
3611 needConversion = false;
3612 else {
3613 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_ unpackPremultiplyAlpha, data)) {
3614 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
3615 return;
3616 }
3617 }
3618 if (m_unpackAlignment != 1)
3619 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
3620 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels-> height(), format, type, needConversion ? data.data() : pixels->data()->data(), e s);
3621 if (m_unpackAlignment != 1)
3622 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlig nment);
3623 }
3624
3625 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din t xoffset, GC3Dint yoffset,
3626 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& es)
3627 {
3628 if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, es) )
3629 return;
3630 Image* imageForRender = image->cachedImage()->imageForRenderer(image->render er());
3631 if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, Sour ceHTMLImageElement, target, level, format, imageForRender->width(), imageForRend er->height(), 0, format, type, xoffset, yoffset))
3632 return;
3633
3634 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRen der, GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, e s);
3635 }
3636
3637 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din t xoffset, GC3Dint yoffset,
3638 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& e s)
3639 {
3640 if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, e s)
3641 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElem ent, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
3642 return;
3643
3644 RefPtr<ImageData> imageData = canvas->getImageData();
3645 if (imageData)
3646 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.g et(), es);
3647 else
3648 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas- >copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremult iplyAlpha, es);
3649 }
3650
3651 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Din t xoffset, GC3Dint yoffset,
3652 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionState& es)
3653 {
3654 if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, es)
3655 || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoEleme nt, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
3656 return;
3657
3658 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMod e());
3659 if (!image)
3660 return;
3661 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get() , GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, es);
3662 }
3663
3664 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3D float x)
3665 {
3666 if (isContextLost() || !location)
3667 return;
3668
3669 if (location->program() != m_currentProgram) {
3670 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "lo cation not for current program");
3671 return;
3672 }
3673
3674 m_context->uniform1f(location->location(), x);
3675 }
3676
3677 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Flo at32Array* v)
3678 {
3679 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1))
3680 return;
3681
3682 m_context->uniform1fv(location->location(), v->length(), v->data());
3683 }
3684
3685 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3 Dfloat* v, GC3Dsizei size)
3686 {
3687 if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1))
3688 return;
3689
3690 m_context->uniform1fv(location->location(), size, v);
3691 }
3692
3693 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3D int x)
3694 {
3695 if (isContextLost() || !location)
3696 return;
3697
3698 if (location->program() != m_currentProgram) {
3699 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "lo cation not for current program");
3700 return;
3701 }
3702
3703 m_context->uniform1i(location->location(), x);
3704 }
3705
3706 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int 32Array* v)
3707 {
3708 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1))
3709 return;
3710
3711 m_context->uniform1iv(location->location(), v->length(), v->data());
3712 }
3713
3714 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3 Dint* v, GC3Dsizei size)
3715 {
3716 if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1))
3717 return;
3718
3719 m_context->uniform1iv(location->location(), size, v);
3720 }
3721
3722 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3D float x, GC3Dfloat y)
3723 {
3724 if (isContextLost() || !location)
3725 return;
3726
3727 if (location->program() != m_currentProgram) {
3728 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "lo cation not for current program");
3729 return;
3730 }
3731
3732 m_context->uniform2f(location->location(), x, y);
3733 }
3734
3735 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Flo at32Array* v)
3736 {
3737 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2))
3738 return;
3739
3740 m_context->uniform2fv(location->location(), v->length() / 2, v->data());
3741 }
3742
3743 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3 Dfloat* v, GC3Dsizei size)
3744 {
3745 if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2))
3746 return;
3747
3748 m_context->uniform2fv(location->location(), size / 2, v);
3749 }
3750
3751 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3D int x, GC3Dint y)
3752 {
3753 if (isContextLost() || !location)
3754 return;
3755
3756 if (location->program() != m_currentProgram) {
3757 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "lo cation not for current program");
3758 return;
3759 }
3760
3761 m_context->uniform2i(location->location(), x, y);
3762 }
3763
3764 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int 32Array* v)
3765 {
3766 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2))
3767 return;
3768
3769 m_context->uniform2iv(location->location(), v->length() / 2, v->data());
3770 }
3771
3772 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3 Dint* v, GC3Dsizei size)
3773 {
3774 if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2))
3775 return;
3776
3777 m_context->uniform2iv(location->location(), size / 2, v);
3778 }
3779
3780 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3D float x, GC3Dfloat y, GC3Dfloat z)
3781 {
3782 if (isContextLost() || !location)
3783 return;
3784
3785 if (location->program() != m_currentProgram) {
3786 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "lo cation not for current program");
3787 return;
3788 }
3789
3790 m_context->uniform3f(location->location(), x, y, z);
3791 }
3792
3793 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Flo at32Array* v)
3794 {
3795 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3))
3796 return;
3797
3798 m_context->uniform3fv(location->location(), v->length() / 3, v->data());
3799 }
3800
3801 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3 Dfloat* v, GC3Dsizei size)
3802 {
3803 if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3))
3804 return;
3805
3806 m_context->uniform3fv(location->location(), size / 3, v);
3807 }
3808
3809 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3D int x, GC3Dint y, GC3Dint z)
3810 {
3811 if (isContextLost() || !location)
3812 return;
3813
3814 if (location->program() != m_currentProgram) {
3815 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "lo cation not for current program");
3816 return;
3817 }
3818
3819 m_context->uniform3i(location->location(), x, y, z);
3820 }
3821
3822 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int 32Array* v)
3823 {
3824 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3))
3825 return;
3826
3827 m_context->uniform3iv(location->location(), v->length() / 3, v->data());
3828 }
3829
3830 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3 Dint* v, GC3Dsizei size)
3831 {
3832 if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3))
3833 return;
3834
3835 m_context->uniform3iv(location->location(), size / 3, v);
3836 }
3837
3838 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3D float x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w)
3839 {
3840 if (isContextLost() || !location)
3841 return;
3842
3843 if (location->program() != m_currentProgram) {
3844 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "lo cation not for current program");
3845 return;
3846 }
3847
3848 m_context->uniform4f(location->location(), x, y, z, w);
3849 }
3850
3851 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Flo at32Array* v)
3852 {
3853 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4))
3854 return;
3855
3856 m_context->uniform4fv(location->location(), v->length() / 4, v->data());
3857 }
3858
3859 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3 Dfloat* v, GC3Dsizei size)
3860 {
3861 if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4))
3862 return;
3863
3864 m_context->uniform4fv(location->location(), size / 4, v);
3865 }
3866
3867 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3D int x, GC3Dint y, GC3Dint z, GC3Dint w)
3868 {
3869 if (isContextLost() || !location)
3870 return;
3871
3872 if (location->program() != m_currentProgram) {
3873 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "lo cation not for current program");
3874 return;
3875 }
3876
3877 m_context->uniform4i(location->location(), x, y, z, w);
3878 }
3879
3880 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int 32Array* v)
3881 {
3882 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4))
3883 return;
3884
3885 m_context->uniform4iv(location->location(), v->length() / 4, v->data());
3886 }
3887
3888 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3 Dint* v, GC3Dsizei size)
3889 {
3890 if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4))
3891 return;
3892
3893 m_context->uniform4iv(location->location(), size / 4, v);
3894 }
3895
3896 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, Float32Array* v)
3897 {
3898 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4))
3899 return;
3900 m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose , v->data());
3901 }
3902
3903 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size)
3904 {
3905 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4))
3906 return;
3907 m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v);
3908 }
3909
3910 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, Float32Array* v)
3911 {
3912 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9))
3913 return;
3914 m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose , v->data());
3915 }
3916
3917 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size)
3918 {
3919 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9))
3920 return;
3921 m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v);
3922 }
3923
3924 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, Float32Array* v)
3925 {
3926 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16))
3927 return;
3928 m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpos e, v->data());
3929 }
3930
3931 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* locatio n, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size)
3932 {
3933 if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16))
3934 return;
3935 m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v);
3936 }
3937
3938 void WebGLRenderingContext::useProgram(WebGLProgram* program)
3939 {
3940 bool deleted;
3941 if (!checkObjectToBeBound("useProgram", program, deleted))
3942 return;
3943 if (deleted)
3944 program = 0;
3945 if (program && !program->getLinkStatus()) {
3946 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "p rogram not valid");
3947 return;
3948 }
3949 if (m_currentProgram != program) {
3950 if (m_currentProgram)
3951 m_currentProgram->onDetached(graphicsContext3D());
3952 m_currentProgram = program;
3953 m_context->useProgram(objectOrZero(program));
3954 if (program)
3955 program->onAttached();
3956 }
3957 }
3958
3959 void WebGLRenderingContext::validateProgram(WebGLProgram* program)
3960 {
3961 if (isContextLost() || !validateWebGLObject("validateProgram", program))
3962 return;
3963 m_context->validateProgram(objectOrZero(program));
3964 }
3965
3966 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
3967 {
3968 vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f);
3969 }
3970
3971 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
3972 {
3973 vertexAttribfvImpl("vertexAttrib1fv", index, v, 1);
3974 }
3975
3976 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsi zei size)
3977 {
3978 vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1);
3979 }
3980
3981 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dflo at v1)
3982 {
3983 vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f);
3984 }
3985
3986 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
3987 {
3988 vertexAttribfvImpl("vertexAttrib2fv", index, v, 2);
3989 }
3990
3991 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsi zei size)
3992 {
3993 vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2);
3994 }
3995
3996 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dflo at v1, GC3Dfloat v2)
3997 {
3998 vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f);
3999 }
4000
4001 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
4002 {
4003 vertexAttribfvImpl("vertexAttrib3fv", index, v, 3);
4004 }
4005
4006 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsi zei size)
4007 {
4008 vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3);
4009 }
4010
4011 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dflo at v1, GC3Dfloat v2, GC3Dfloat v3)
4012 {
4013 vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3);
4014 }
4015
4016 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
4017 {
4018 vertexAttribfvImpl("vertexAttrib4fv", index, v, 4);
4019 }
4020
4021 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsi zei size)
4022 {
4023 vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4);
4024 }
4025
4026 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC 3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset)
4027 {
4028 if (isContextLost())
4029 return;
4030 switch (type) {
4031 case GraphicsContext3D::BYTE:
4032 case GraphicsContext3D::UNSIGNED_BYTE:
4033 case GraphicsContext3D::SHORT:
4034 case GraphicsContext3D::UNSIGNED_SHORT:
4035 case GraphicsContext3D::FLOAT:
4036 break;
4037 default:
4038 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer" , "invalid type");
4039 return;
4040 }
4041 if (index >= m_maxVertexAttribs) {
4042 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer ", "index out of range");
4043 return;
4044 }
4045 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
4046 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer ", "bad size, stride or offset");
4047 return;
4048 }
4049 if (!m_boundArrayBuffer) {
4050 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPoi nter", "no bound ARRAY_BUFFER");
4051 return;
4052 }
4053 // Determine the number of elements the bound buffer can hold, given the off set, size, type and stride
4054 unsigned int typeSize = sizeInBytes(type);
4055 if (!typeSize) {
4056 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer" , "invalid type");
4057 return;
4058 }
4059 if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) {
4060 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPoi nter", "stride or offset not valid for type");
4061 return;
4062 }
4063 GC3Dsizei bytesPerElement = size * typeSize;
4064
4065 m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer);
4066 m_context->vertexAttribPointer(index, size, type, normalized, stride, static _cast<GC3Dintptr>(offset));
4067 }
4068
4069 void WebGLRenderingContext::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint di visor)
4070 {
4071 if (isContextLost())
4072 return;
4073
4074 if (index >= m_maxVertexAttribs) {
4075 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor ANGLE", "index out of range");
4076 return;
4077 }
4078
4079 m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor);
4080 m_context->getExtensions()->vertexAttribDivisorANGLE(index, divisor);
4081 }
4082
4083 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3D sizei height)
4084 {
4085 if (isContextLost())
4086 return;
4087 if (!validateSize("viewport", width, height))
4088 return;
4089 m_context->viewport(x, y, width, height);
4090 }
4091
4092 void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextM ode mode)
4093 {
4094 if (isContextLost()) {
4095 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", " context already lost");
4096 return;
4097 }
4098
4099 m_contextGroup->loseContextGroup(mode);
4100 }
4101
4102 void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMo de mode)
4103 {
4104 if (isContextLost())
4105 return;
4106
4107 m_contextLost = true;
4108 m_contextLostMode = mode;
4109
4110 if (mode == RealLostContext) {
4111 // Inform the embedder that a lost context was received. In response, th e embedder might
4112 // decide to take action such as asking the user for permission to use W ebGL again.
4113 if (Frame* frame = canvas()->document().frame())
4114 frame->loader()->client()->didLoseWebGLContext(m_context->getExtensi ons()->getGraphicsResetStatusARB());
4115 }
4116
4117 // Make absolutely sure we do not refer to an already-deleted texture or fra mebuffer.
4118 m_drawingBuffer->setTexture2DBinding(0);
4119 m_drawingBuffer->setFramebufferBinding(0);
4120
4121 detachAndRemoveAllObjects();
4122
4123 // Lose all the extensions.
4124 for (size_t i = 0; i < m_extensions.size(); ++i) {
4125 ExtensionTracker* tracker = m_extensions[i];
4126 tracker->loseExtension();
4127 }
4128
4129 removeAllCompressedTextureFormats();
4130
4131 if (mode != RealLostContext)
4132 destroyGraphicsContext3D();
4133
4134 ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInCons ole: DontDisplayInConsole;
4135 synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "con text lost", display);
4136
4137 // Don't allow restoration unless the context lost event has both been
4138 // dispatched and its default behavior prevented.
4139 m_restoreAllowed = false;
4140
4141 // Always defer the dispatch of the context lost event, to implement
4142 // the spec behavior of queueing a task.
4143 m_dispatchContextLostEventTimer.startOneShot(0);
4144 }
4145
4146 void WebGLRenderingContext::forceRestoreContext()
4147 {
4148 if (!isContextLost()) {
4149 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext" , "context not lost");
4150 return;
4151 }
4152
4153 if (!m_restoreAllowed) {
4154 if (m_contextLostMode == SyntheticLostContext)
4155 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreCont ext", "context restoration not allowed");
4156 return;
4157 }
4158
4159 if (!m_restoreTimer.isActive())
4160 m_restoreTimer.startOneShot(0);
4161 }
4162
4163 WebKit::WebLayer* WebGLRenderingContext::platformLayer() const
4164 {
4165 return m_drawingBuffer->platformLayer();
4166 }
4167
4168 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
4169 {
4170 m_contextGroup->removeObject(object);
4171 }
4172
4173 void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object)
4174 {
4175 ASSERT(!isContextLost());
4176 m_contextGroup->addObject(object);
4177 }
4178
4179 void WebGLRenderingContext::removeContextObject(WebGLContextObject* object)
4180 {
4181 m_contextObjects.remove(object);
4182 }
4183
4184 void WebGLRenderingContext::addContextObject(WebGLContextObject* object)
4185 {
4186 ASSERT(!isContextLost());
4187 m_contextObjects.add(object);
4188 }
4189
4190 void WebGLRenderingContext::detachAndRemoveAllObjects()
4191 {
4192 while (m_contextObjects.size() > 0) {
4193 HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin();
4194 (*it)->detachContext();
4195 }
4196 }
4197
4198 bool WebGLRenderingContext::hasPendingActivity() const
4199 {
4200 return false;
4201 }
4202
4203 void WebGLRenderingContext::stop()
4204 {
4205 if (!isContextLost()) {
4206 forceLostContext(SyntheticLostContext);
4207 destroyGraphicsContext3D();
4208 }
4209 }
4210
4211 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
4212 {
4213 GC3Dboolean value = 0;
4214 if (!isContextLost())
4215 m_context->getBooleanv(pname, &value);
4216 return WebGLGetInfo(static_cast<bool>(value));
4217 }
4218
4219 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
4220 {
4221 if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
4222 notImplemented();
4223 return WebGLGetInfo(0, 0);
4224 }
4225 GC3Dboolean value[4] = {0};
4226 if (!isContextLost())
4227 m_context->getBooleanv(pname, value);
4228 bool boolValue[4];
4229 for (int ii = 0; ii < 4; ++ii)
4230 boolValue[ii] = static_cast<bool>(value[ii]);
4231 return WebGLGetInfo(boolValue, 4);
4232 }
4233
4234 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
4235 {
4236 GC3Dfloat value = 0;
4237 if (!isContextLost())
4238 m_context->getFloatv(pname, &value);
4239 return WebGLGetInfo(value);
4240 }
4241
4242 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
4243 {
4244 GC3Dint value = 0;
4245 if (!isContextLost())
4246 m_context->getIntegerv(pname, &value);
4247 return WebGLGetInfo(value);
4248 }
4249
4250 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
4251 {
4252 GC3Dint value = 0;
4253 if (!isContextLost())
4254 m_context->getIntegerv(pname, &value);
4255 return WebGLGetInfo(static_cast<unsigned int>(value));
4256 }
4257
4258 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
4259 {
4260 GC3Dfloat value[4] = {0};
4261 if (!isContextLost())
4262 m_context->getFloatv(pname, value);
4263 unsigned length = 0;
4264 switch (pname) {
4265 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
4266 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
4267 case GraphicsContext3D::DEPTH_RANGE:
4268 length = 2;
4269 break;
4270 case GraphicsContext3D::BLEND_COLOR:
4271 case GraphicsContext3D::COLOR_CLEAR_VALUE:
4272 length = 4;
4273 break;
4274 default:
4275 notImplemented();
4276 }
4277 return WebGLGetInfo(Float32Array::create(value, length));
4278 }
4279
4280 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
4281 {
4282 GC3Dint value[4] = {0};
4283 if (!isContextLost())
4284 m_context->getIntegerv(pname, value);
4285 unsigned length = 0;
4286 switch (pname) {
4287 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
4288 length = 2;
4289 break;
4290 case GraphicsContext3D::SCISSOR_BOX:
4291 case GraphicsContext3D::VIEWPORT:
4292 length = 4;
4293 break;
4294 default:
4295 notImplemented();
4296 }
4297 return WebGLGetInfo(Int32Array::create(value, length));
4298 }
4299
4300 void WebGLRenderingContext::handleTextureCompleteness(const char* functionName, bool prepareToDraw)
4301 {
4302 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
4303 bool resetActiveUnit = false;
4304 WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureE xtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureFloatLinearExtensi onEnabled : 0)
4305 | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureHalfFloatLinearExt ensionEnabled : 0));
4306 for (unsigned ii = 0; ii < m_onePlusMaxNonDefaultTextureUnit; ++ii) {
4307 if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m _texture2DBinding->needToUseBlackTexture(flag))
4308 || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUni ts[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) {
4309 if (ii != m_activeTextureUnit) {
4310 m_context->activeTexture(ii);
4311 resetActiveUnit = true;
4312 } else if (resetActiveUnit) {
4313 m_context->activeTexture(ii);
4314 resetActiveUnit = false;
4315 }
4316 WebGLTexture* tex2D;
4317 WebGLTexture* texCubeMap;
4318 if (prepareToDraw) {
4319 String msg(String("texture bound to texture unit ") + String::nu mber(ii)
4320 + " is not renderable. It maybe non-power-of-2 and have inco mpatible texture filtering or is not 'texture complete'."
4321 + " Or the texture is Float or Half Float type with linear f iltering while OES_float_linear or OES_half_float_linear extension is not enable d.");
4322 emitGLWarning(functionName, msg.utf8().data());
4323 tex2D = m_blackTexture2D.get();
4324 texCubeMap = m_blackTextureCubeMap.get();
4325 } else {
4326 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
4327 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
4328 }
4329 if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_te xture2DBinding->needToUseBlackTexture(flag))
4330 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZe ro(tex2D));
4331 if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii] .m_textureCubeMapBinding->needToUseBlackTexture(flag))
4332 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, obje ctOrZero(texCubeMap));
4333 }
4334 }
4335 if (resetActiveUnit)
4336 m_context->activeTexture(m_activeTextureUnit);
4337 }
4338
4339 void WebGLRenderingContext::createFallbackBlackTextures1x1()
4340 {
4341 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
4342 unsigned char black[] = {0, 0, 0, 255};
4343 m_blackTexture2D = createTexture();
4344 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->obje ct());
4345 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::R GBA, 1, 1,
4346 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4347 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
4348 m_blackTextureCubeMap = createTexture();
4349 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCu beMap->object());
4350 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, Gra phicsContext3D::RGBA, 1, 1,
4351 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4352 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, Gra phicsContext3D::RGBA, 1, 1,
4353 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4354 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, Gra phicsContext3D::RGBA, 1, 1,
4355 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4356 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, Gra phicsContext3D::RGBA, 1, 1,
4357 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4358 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, Gra phicsContext3D::RGBA, 1, 1,
4359 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4360 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, Gra phicsContext3D::RGBA, 1, 1,
4361 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNE D_BYTE, black);
4362 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
4363 }
4364
4365 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3De num texInternalFormat,
4366 GC3De num colorBufferFormat)
4367 {
4368 unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat) ;
4369 unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat) ;
4370 return (need & have) == need;
4371 }
4372
4373 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
4374 {
4375 if (m_framebufferBinding && m_framebufferBinding->object())
4376 return m_framebufferBinding->getColorBufferFormat();
4377 if (m_attributes.alpha)
4378 return GraphicsContext3D::RGBA;
4379 return GraphicsContext3D::RGB;
4380 }
4381
4382 int WebGLRenderingContext::getBoundFramebufferWidth()
4383 {
4384 if (m_framebufferBinding && m_framebufferBinding->object())
4385 return m_framebufferBinding->getColorBufferWidth();
4386 return m_drawingBuffer->size().width();
4387 }
4388
4389 int WebGLRenderingContext::getBoundFramebufferHeight()
4390 {
4391 if (m_framebufferBinding && m_framebufferBinding->object())
4392 return m_framebufferBinding->getColorBufferHeight();
4393 return m_drawingBuffer->size().height();
4394 }
4395
4396 WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* function Name, GC3Denum target, bool useSixEnumsForCubeMap)
4397 {
4398 WebGLTexture* tex = 0;
4399 switch (target) {
4400 case GraphicsContext3D::TEXTURE_2D:
4401 tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
4402 break;
4403 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4404 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4405 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4406 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4407 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4408 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4409 if (!useSixEnumsForCubeMap) {
4410 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "in valid texture target");
4411 return 0;
4412 }
4413 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4414 break;
4415 case GraphicsContext3D::TEXTURE_CUBE_MAP:
4416 if (useSixEnumsForCubeMap) {
4417 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "in valid texture target");
4418 return 0;
4419 }
4420 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
4421 break;
4422 default:
4423 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture target");
4424 return 0;
4425 }
4426 if (!tex)
4427 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "n o texture");
4428 return tex;
4429 }
4430
4431 bool WebGLRenderingContext::validateLocationLength(const char* functionName, con st String& string)
4432 {
4433 const unsigned maxWebGLLocationLength = 256;
4434 if (string.length() > maxWebGLLocationLength) {
4435 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "locat ion length > 256");
4436 return false;
4437 }
4438 return true;
4439 }
4440
4441 bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC 3Dint y)
4442 {
4443 if (x < 0 || y < 0) {
4444 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0");
4445 return false;
4446 }
4447 return true;
4448 }
4449
4450 bool WebGLRenderingContext::validateString(const char* functionName, const Strin g& string)
4451 {
4452 for (size_t i = 0; i < string.length(); ++i) {
4453 if (!validateCharacter(string[i])) {
4454 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "s tring not ASCII");
4455 return false;
4456 }
4457 }
4458 return true;
4459 }
4460
4461 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionNam e, GC3Denum format, GC3Denum type, GC3Dint level)
4462 {
4463 switch (format) {
4464 case GraphicsContext3D::ALPHA:
4465 case GraphicsContext3D::LUMINANCE:
4466 case GraphicsContext3D::LUMINANCE_ALPHA:
4467 case GraphicsContext3D::RGB:
4468 case GraphicsContext3D::RGBA:
4469 break;
4470 case GraphicsContext3D::DEPTH_STENCIL:
4471 case GraphicsContext3D::DEPTH_COMPONENT:
4472 if (m_webglDepthTexture)
4473 break;
4474 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
4475 return false;
4476 default:
4477 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture format");
4478 return false;
4479 }
4480
4481 switch (type) {
4482 case GraphicsContext3D::UNSIGNED_BYTE:
4483 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4484 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4485 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4486 break;
4487 case GraphicsContext3D::FLOAT:
4488 if (m_oesTextureFloat)
4489 break;
4490 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture type");
4491 return false;
4492 case GraphicsContext3D::HALF_FLOAT_OES:
4493 if (m_oesTextureHalfFloat)
4494 break;
4495 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture type");
4496 return false;
4497 case GraphicsContext3D::UNSIGNED_INT:
4498 case GraphicsContext3D::UNSIGNED_INT_24_8:
4499 case GraphicsContext3D::UNSIGNED_SHORT:
4500 if (m_webglDepthTexture)
4501 break;
4502 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture type");
4503 return false;
4504 default:
4505 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d texture type");
4506 return false;
4507 }
4508
4509 // Verify that the combination of format and type is supported.
4510 switch (format) {
4511 case GraphicsContext3D::ALPHA:
4512 case GraphicsContext3D::LUMINANCE:
4513 case GraphicsContext3D::LUMINANCE_ALPHA:
4514 if (type != GraphicsContext3D::UNSIGNED_BYTE
4515 && type != GraphicsContext3D::FLOAT
4516 && type != GraphicsContext3D::HALF_FLOAT_OES) {
4517 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "invalid type for format");
4518 return false;
4519 }
4520 break;
4521 case GraphicsContext3D::RGB:
4522 if (type != GraphicsContext3D::UNSIGNED_BYTE
4523 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
4524 && type != GraphicsContext3D::FLOAT
4525 && type != GraphicsContext3D::HALF_FLOAT_OES) {
4526 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "invalid type for RGB format");
4527 return false;
4528 }
4529 break;
4530 case GraphicsContext3D::RGBA:
4531 if (type != GraphicsContext3D::UNSIGNED_BYTE
4532 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
4533 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
4534 && type != GraphicsContext3D::FLOAT
4535 && type != GraphicsContext3D::HALF_FLOAT_OES) {
4536 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "invalid type for RGBA format");
4537 return false;
4538 }
4539 break;
4540 case GraphicsContext3D::DEPTH_COMPONENT:
4541 if (!m_webglDepthTexture) {
4542 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "in valid format. DEPTH_COMPONENT not enabled");
4543 return false;
4544 }
4545 if (type != GraphicsContext3D::UNSIGNED_SHORT
4546 && type != GraphicsContext3D::UNSIGNED_INT) {
4547 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "invalid type for DEPTH_COMPONENT format");
4548 return false;
4549 }
4550 if (level > 0) {
4551 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
4552 return false;
4553 }
4554 break;
4555 case GraphicsContext3D::DEPTH_STENCIL:
4556 if (!m_webglDepthTexture) {
4557 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "in valid format. DEPTH_STENCIL not enabled");
4558 return false;
4559 }
4560 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
4561 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "invalid type for DEPTH_STENCIL format");
4562 return false;
4563 }
4564 if (level > 0) {
4565 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
4566 return false;
4567 }
4568 break;
4569 default:
4570 ASSERT_NOT_REACHED();
4571 }
4572
4573 return true;
4574 }
4575
4576 bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3De num target, GC3Dint level)
4577 {
4578 if (level < 0) {
4579 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0");
4580 return false;
4581 }
4582 switch (target) {
4583 case GraphicsContext3D::TEXTURE_2D:
4584 if (level >= m_maxTextureLevel) {
4585 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "l evel out of range");
4586 return false;
4587 }
4588 break;
4589 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4590 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4591 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4592 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4593 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4594 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4595 if (level >= m_maxCubeMapTextureLevel) {
4596 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "l evel out of range");
4597 return false;
4598 }
4599 break;
4600 }
4601 // This function only checks if level is legal, so we return true and don't
4602 // generate INVALID_ENUM if target is illegal.
4603 return true;
4604 }
4605
4606 bool WebGLRenderingContext::validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType functionType,
4607 GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height)
4608 {
4609 if (width < 0 || height < 0) {
4610 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
4611 return false;
4612 }
4613
4614 switch (target) {
4615 case GraphicsContext3D::TEXTURE_2D:
4616 if (width > (m_maxTextureSize >> level) || height > (m_maxTextureSize >> level)) {
4617 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "w idth or height out of range");
4618 return false;
4619 }
4620 break;
4621 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
4622 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
4623 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
4624 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
4625 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
4626 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
4627 if (functionType != TexSubImage2D && width != height) {
4628 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "wid th != height for cube map");
4629 return false;
4630 }
4631 // No need to check height here. For texImage width == height.
4632 // For texSubImage that will be checked when checking yoffset + height i s in range.
4633 if (width > (m_maxCubeMapTextureSize >> level)) {
4634 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "w idth or height out of range for cube map");
4635 return false;
4636 }
4637 break;
4638 default:
4639 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d target");
4640 return false;
4641 }
4642 return true;
4643 }
4644
4645 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target,
4646 GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, G C3Dint border, GC3Denum format, GC3Denum type)
4647 {
4648 // We absolutely have to validate the format and type combination.
4649 // The texImage2D entry points taking HTMLImage, etc. will produce
4650 // temporary data based on this combination, so it must be legal.
4651 if (!validateTexFuncFormatAndType(functionName, format, type, level) || !val idateTexFuncLevel(functionName, target, level))
4652 return false;
4653
4654 if (!validateTexFuncDimensions(functionName, functionType, target, level, wi dth, height))
4655 return false;
4656
4657 if (format != internalformat) {
4658 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "f ormat != internalformat");
4659 return false;
4660 }
4661
4662 if (border) {
4663 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "borde r != 0");
4664 return false;
4665 }
4666
4667 return true;
4668 }
4669
4670 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Din t level,
4671 GC3Dsizei width, GC3Dsizei heigh t,
4672 GC3Denum format, GC3Denum type,
4673 ArrayBufferView* pixels,
4674 NullDisposition disposition)
4675 {
4676 // All calling functions check isContextLost, so a duplicate check is not ne eded here.
4677 if (!pixels) {
4678 if (disposition == NullAllowed)
4679 return true;
4680 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pi xels");
4681 return false;
4682 }
4683
4684 if (!validateTexFuncFormatAndType(functionName, format, type, level))
4685 return false;
4686 if (!validateSettableTexFormat(functionName, format))
4687 return false;
4688
4689 switch (type) {
4690 case GraphicsContext3D::UNSIGNED_BYTE:
4691 if (pixels->getType() != ArrayBufferView::TypeUint8) {
4692 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
4693 return false;
4694 }
4695 break;
4696 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
4697 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
4698 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
4699 if (pixels->getType() != ArrayBufferView::TypeUint16) {
4700 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
4701 return false;
4702 }
4703 break;
4704 case GraphicsContext3D::FLOAT: // OES_texture_float
4705 if (pixels->getType() != ArrayBufferView::TypeFloat32) {
4706 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "type FLOAT but ArrayBufferView not Float32Array");
4707 return false;
4708 }
4709 break;
4710 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
4711 // As per the specification, ArrayBufferView should be null when
4712 // OES_texture_half_float is enabled.
4713 if (pixels) {
4714 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
4715 return false;
4716 }
4717 break;
4718 default:
4719 ASSERT_NOT_REACHED();
4720 }
4721
4722 unsigned int totalBytesRequired;
4723 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, hei ght, m_unpackAlignment, &totalBytesRequired, 0);
4724 if (error != GraphicsContext3D::NO_ERROR) {
4725 synthesizeGLError(error, functionName, "invalid texture dimensions");
4726 return false;
4727 }
4728 if (pixels->byteLength() < totalBytesRequired) {
4729 if (m_unpackAlignment != 1) {
4730 error = m_context->computeImageSizeInBytes(format, type, width, height , 1, &totalBytesRequired, 0);
4731 if (pixels->byteLength() == totalBytesRequired) {
4732 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
4733 return false;
4734 }
4735 }
4736 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "A rrayBufferView not big enough for request");
4737 return false;
4738 }
4739 return true;
4740 }
4741
4742 bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format)
4743 {
4744 return m_compressedTextureFormats.contains(format);
4745 }
4746
4747 bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionNa me,
4748 GC3Dsizei width, GC3Ds izei height,
4749 GC3Denum format, Array BufferView* pixels)
4750 {
4751 if (!pixels) {
4752 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pi xels");
4753 return false;
4754 }
4755 if (width < 0 || height < 0) {
4756 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
4757 return false;
4758 }
4759
4760 unsigned int bytesRequired = 0;
4761
4762 switch (format) {
4763 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
4764 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
4765 {
4766 const int kBlockWidth = 4;
4767 const int kBlockHeight = 4;
4768 const int kBlockSize = 8;
4769 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
4770 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
4771 int numBlocks = numBlocksAcross * numBlocksDown;
4772 bytesRequired = numBlocks * kBlockSize;
4773 }
4774 break;
4775 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
4776 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT:
4777 {
4778 const int kBlockWidth = 4;
4779 const int kBlockHeight = 4;
4780 const int kBlockSize = 16;
4781 int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth;
4782 int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight;
4783 int numBlocks = numBlocksAcross * numBlocksDown;
4784 bytesRequired = numBlocks * kBlockSize;
4785 }
4786 break;
4787 case Extensions3D::COMPRESSED_ATC_RGB_AMD:
4788 {
4789 bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor( static_cast<double>((height + 3) / 4)) * 8;
4790 }
4791 break;
4792 case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD:
4793 case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
4794 {
4795 bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor( static_cast<double>((height + 3) / 4)) * 16;
4796 }
4797 case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
4798 case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
4799 {
4800 bytesRequired = max(width, 8) * max(height, 8) / 2;
4801 }
4802 break;
4803 case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
4804 case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
4805 {
4806 bytesRequired = max(width, 8) * max(height, 8) / 4;
4807 }
4808 break;
4809 default:
4810 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d format");
4811 return false;
4812 }
4813
4814 if (pixels->byteLength() != bytesRequired) {
4815 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "lengt h of ArrayBufferView is not correct for dimensions");
4816 return false;
4817 }
4818
4819 return true;
4820 }
4821
4822 bool WebGLRenderingContext::validateCompressedTexDimensions(const char* function Name, TexFuncValidationFunctionType functionType, GC3Denum target, GC3Dint level , GC3Dsizei width, GC3Dsizei height, GC3Denum format)
4823 {
4824 if (!validateTexFuncDimensions(functionName, functionType, target, level, wi dth, height))
4825 return false;
4826
4827 switch (format) {
4828 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
4829 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
4830 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
4831 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
4832 const int kBlockWidth = 4;
4833 const int kBlockHeight = 4;
4834 bool widthValid = (level && width == 1) || (level && width == 2) || !(wi dth % kBlockWidth);
4835 bool heightValid = (level && height == 1) || (level && height == 2) || ! (height % kBlockHeight);
4836 if (!widthValid || !heightValid) {
4837 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level");
4838 return false;
4839 }
4840 return true;
4841 }
4842 default:
4843 return false;
4844 }
4845 }
4846
4847 bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* funct ionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
4848 GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex)
4849 {
4850 if (xoffset < 0 || yoffset < 0) {
4851 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0");
4852 return false;
4853 }
4854
4855 switch (format) {
4856 case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT:
4857 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT:
4858 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT:
4859 case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: {
4860 const int kBlockWidth = 4;
4861 const int kBlockHeight = 4;
4862 if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) {
4863 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "xoffset or yoffset not multiple of 4");
4864 return false;
4865 }
4866 if (width - xoffset > tex->getWidth(target, level)
4867 || height - yoffset > tex->getHeight(target, level)) {
4868 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName , "dimensions out of range");
4869 return false;
4870 }
4871 return validateCompressedTexDimensions(functionName, TexSubImage2D, targ et, level, width, height, format);
4872 }
4873 default:
4874 return false;
4875 }
4876 }
4877
4878 bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode)
4879 {
4880 switch (mode) {
4881 case GraphicsContext3D::POINTS:
4882 case GraphicsContext3D::LINE_STRIP:
4883 case GraphicsContext3D::LINE_LOOP:
4884 case GraphicsContext3D::LINES:
4885 case GraphicsContext3D::TRIANGLE_STRIP:
4886 case GraphicsContext3D::TRIANGLE_FAN:
4887 case GraphicsContext3D::TRIANGLES:
4888 return true;
4889 default:
4890 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d draw mode");
4891 return false;
4892 }
4893 }
4894
4895 bool WebGLRenderingContext::validateStencilSettings(const char* functionName)
4896 {
4897 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncR efBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
4898 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "f ront and back stencils settings do not match");
4899 return false;
4900 }
4901 return true;
4902 }
4903
4904 bool WebGLRenderingContext::validateStencilOrDepthFunc(const char* functionName, GC3Denum func)
4905 {
4906 switch (func) {
4907 case GraphicsContext3D::NEVER:
4908 case GraphicsContext3D::LESS:
4909 case GraphicsContext3D::LEQUAL:
4910 case GraphicsContext3D::GREATER:
4911 case GraphicsContext3D::GEQUAL:
4912 case GraphicsContext3D::EQUAL:
4913 case GraphicsContext3D::NOTEQUAL:
4914 case GraphicsContext3D::ALWAYS:
4915 return true;
4916 default:
4917 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d function");
4918 return false;
4919 }
4920 }
4921
4922 void WebGLRenderingContext::printGLErrorToConsole(const String& message)
4923 {
4924 if (!m_numGLErrorsToConsoleAllowed)
4925 return;
4926
4927 --m_numGLErrorsToConsoleAllowed;
4928 printWarningToConsole(message);
4929
4930 if (!m_numGLErrorsToConsoleAllowed)
4931 printWarningToConsole("WebGL: too many errors, no more errors will be re ported to the console for this context.");
4932
4933 return;
4934 }
4935
4936 void WebGLRenderingContext::printWarningToConsole(const String& message)
4937 {
4938 if (!canvas())
4939 return;
4940 canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessag eLevel, message);
4941 }
4942
4943 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functi onName, GC3Denum target, GC3Denum attachment)
4944 {
4945 if (target != GraphicsContext3D::FRAMEBUFFER) {
4946 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d target");
4947 return false;
4948 }
4949 switch (attachment) {
4950 case GraphicsContext3D::COLOR_ATTACHMENT0:
4951 case GraphicsContext3D::DEPTH_ATTACHMENT:
4952 case GraphicsContext3D::STENCIL_ATTACHMENT:
4953 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
4954 break;
4955 default:
4956 if (m_webglDrawBuffers
4957 && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
4958 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTAC HMENT0 + getMaxColorAttachments()))
4959 break;
4960 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d attachment");
4961 return false;
4962 }
4963 return true;
4964 }
4965
4966 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3D enum mode)
4967 {
4968 switch (mode) {
4969 case GraphicsContext3D::FUNC_ADD:
4970 case GraphicsContext3D::FUNC_SUBTRACT:
4971 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
4972 return true;
4973 default:
4974 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d mode");
4975 return false;
4976 }
4977 }
4978
4979 bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, G C3Denum src, GC3Denum dst)
4980 {
4981 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D:: ONE_MINUS_CONSTANT_COLOR)
4982 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3 D::ONE_MINUS_CONSTANT_ALPHA))
4983 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3 D::ONE_MINUS_CONSTANT_COLOR)
4984 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsConte xt3D::ONE_MINUS_CONSTANT_ALPHA))) {
4985 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "i ncompatible src and dst");
4986 return false;
4987 }
4988 return true;
4989 }
4990
4991 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denu m cap)
4992 {
4993 switch (cap) {
4994 case GraphicsContext3D::BLEND:
4995 case GraphicsContext3D::CULL_FACE:
4996 case GraphicsContext3D::DEPTH_TEST:
4997 case GraphicsContext3D::DITHER:
4998 case GraphicsContext3D::POLYGON_OFFSET_FILL:
4999 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
5000 case GraphicsContext3D::SAMPLE_COVERAGE:
5001 case GraphicsContext3D::SCISSOR_TEST:
5002 case GraphicsContext3D::STENCIL_TEST:
5003 return true;
5004 default:
5005 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d capability");
5006 return false;
5007 }
5008 }
5009
5010 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize )
5011 {
5012 if (!v) {
5013 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5014 return false;
5015 }
5016 return validateUniformMatrixParameters(functionName, location, false, v->dat a(), v->length(), requiredMinSize);
5017 }
5018
5019 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
5020 {
5021 if (!v) {
5022 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5023 return false;
5024 }
5025 return validateUniformMatrixParameters(functionName, location, false, v->dat a(), v->length(), requiredMinSize);
5026 }
5027
5028 bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei require dMinSize)
5029 {
5030 return validateUniformMatrixParameters(functionName, location, false, v, siz e, requiredMinSize);
5031 }
5032
5033 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* function Name, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
5034 {
5035 if (!v) {
5036 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5037 return false;
5038 }
5039 return validateUniformMatrixParameters(functionName, location, transpose, v- >data(), v->length(), requiredMinSize);
5040 }
5041
5042 bool WebGLRenderingContext::validateUniformMatrixParameters(const char* function Name, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3D sizei size, GC3Dsizei requiredMinSize)
5043 {
5044 if (!location)
5045 return false;
5046 if (location->program() != m_currentProgram) {
5047 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "l ocation is not from current program");
5048 return false;
5049 }
5050 if (!v) {
5051 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5052 return false;
5053 }
5054 if (transpose) {
5055 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "trans pose not FALSE");
5056 return false;
5057 }
5058 if (size < requiredMinSize || (size % requiredMinSize)) {
5059 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "inval id size");
5060 return false;
5061 }
5062 return true;
5063 }
5064
5065 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* fun ctionName, GC3Denum target, GC3Denum usage)
5066 {
5067 WebGLBuffer* buffer = 0;
5068 switch (target) {
5069 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
5070 buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
5071 break;
5072 case GraphicsContext3D::ARRAY_BUFFER:
5073 buffer = m_boundArrayBuffer.get();
5074 break;
5075 default:
5076 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d target");
5077 return 0;
5078 }
5079 if (!buffer) {
5080 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "n o buffer");
5081 return 0;
5082 }
5083 switch (usage) {
5084 case GraphicsContext3D::STREAM_DRAW:
5085 case GraphicsContext3D::STATIC_DRAW:
5086 case GraphicsContext3D::DYNAMIC_DRAW:
5087 return buffer;
5088 }
5089 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid us age");
5090 return 0;
5091 }
5092
5093 bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, H TMLImageElement* image, ExceptionState& es)
5094 {
5095 if (!image || !image->cachedImage()) {
5096 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no im age");
5097 return false;
5098 }
5099 const KURL& url = image->cachedImage()->response().url();
5100 if (url.isNull() || url.isEmpty() || !url.isValid()) {
5101 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "inval id image");
5102 return false;
5103 }
5104 if (wouldTaintOrigin(image)) {
5105 es.throwSecurityError(ExceptionMessages::failedToExecute(functionName, " WebGLRenderingContext", "the cross-origin image at " + url.elidedString() + " ma y not be loaded."));
5106 return false;
5107 }
5108 return true;
5109 }
5110
5111 bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionState& es)
5112 {
5113 if (!canvas || !canvas->buffer()) {
5114 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ca nvas");
5115 return false;
5116 }
5117 if (wouldTaintOrigin(canvas)) {
5118 es.throwSecurityError(ExceptionMessages::failedToExecute(functionName, " WebGLRenderingContext", "tainted canvases may not be loded."));
5119 return false;
5120 }
5121 return true;
5122 }
5123
5124 bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, H TMLVideoElement* video, ExceptionState& es)
5125 {
5126 if (!video || !video->videoWidth() || !video->videoHeight()) {
5127 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no vi deo");
5128 return false;
5129 }
5130 if (wouldTaintOrigin(video)) {
5131 es.throwSecurityError(ExceptionMessages::failedToExecute(functionName, " WebGLRenderingContext", "the video element contains cross-origin data, and may n ot be loaded."));
5132 return false;
5133 }
5134 return true;
5135 }
5136
5137 bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denu m mode, GC3Dint first, GC3Dsizei count)
5138 {
5139 if (isContextLost() || !validateDrawMode(functionName, mode))
5140 return false;
5141
5142 if (!validateStencilSettings(functionName))
5143 return false;
5144
5145 if (first < 0 || count < 0) {
5146 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0");
5147 return false;
5148 }
5149
5150 if (!count) {
5151 markContextChanged();
5152 return false;
5153 }
5154
5155 if (!validateRenderingState()) {
5156 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "a ttribs not setup correctly");
5157 return false;
5158 }
5159
5160 const char* reason = "framebuffer incomplete";
5161 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
5162 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, func tionName, reason);
5163 return false;
5164 }
5165
5166 return true;
5167 }
5168
5169 bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3De num mode, GC3Dsizei count, GC3Denum type, long long offset)
5170 {
5171 if (isContextLost() || !validateDrawMode(functionName, mode))
5172 return false;
5173
5174 if (!validateStencilSettings(functionName))
5175 return false;
5176
5177 switch (type) {
5178 case GraphicsContext3D::UNSIGNED_BYTE:
5179 case GraphicsContext3D::UNSIGNED_SHORT:
5180 break;
5181 case GraphicsContext3D::UNSIGNED_INT:
5182 if (m_oesElementIndexUint)
5183 break;
5184 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d type");
5185 return false;
5186 default:
5187 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invali d type");
5188 return false;
5189 }
5190
5191 if (count < 0 || offset < 0) {
5192 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0");
5193 return false;
5194 }
5195
5196 if (!count) {
5197 markContextChanged();
5198 return false;
5199 }
5200
5201 if (!m_boundVertexArrayObject->getElementArrayBuffer()) {
5202 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "n o ELEMENT_ARRAY_BUFFER bound");
5203 return false;
5204 }
5205
5206 if (!validateRenderingState()) {
5207 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "a ttribs not setup correctly");
5208 return false;
5209 }
5210
5211 const char* reason = "framebuffer incomplete";
5212 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3 D(), &reason)) {
5213 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, func tionName, reason);
5214 return false;
5215 }
5216
5217 return true;
5218 }
5219
5220 // Helper function to validate draw*Instanced calls
5221 bool WebGLRenderingContext::validateDrawInstanced(const char* functionName, GC3D sizei primcount)
5222 {
5223 if (primcount < 0) {
5224 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primc ount < 0");
5225 return false;
5226 }
5227
5228 // Ensure at least one enabled vertex attrib has a divisor of 0.
5229 for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) {
5230 const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVerte xArrayObject->getVertexAttribState(i);
5231 if (state.enabled && !state.divisor)
5232 return true;
5233 }
5234
5235 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "at le ast one enabled attribute must have a divisor of 0");
5236 return false;
5237 }
5238
5239 void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfl oat v3)
5240 {
5241 if (isContextLost())
5242 return;
5243 if (index >= m_maxVertexAttribs) {
5244 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5245 return;
5246 }
5247 // In GL, we skip setting vertexAttrib0 values.
5248 switch (expectedSize) {
5249 case 1:
5250 m_context->vertexAttrib1f(index, v0);
5251 break;
5252 case 2:
5253 m_context->vertexAttrib2f(index, v0, v1);
5254 break;
5255 case 3:
5256 m_context->vertexAttrib3f(index, v0, v1, v2);
5257 break;
5258 case 4:
5259 m_context->vertexAttrib4f(index, v0, v1, v2, v3);
5260 break;
5261 }
5262 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5263 attribValue.value[0] = v0;
5264 attribValue.value[1] = v1;
5265 attribValue.value[2] = v2;
5266 attribValue.value[3] = v3;
5267 }
5268
5269 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duin t index, Float32Array* v, GC3Dsizei expectedSize)
5270 {
5271 if (isContextLost())
5272 return;
5273 if (!v) {
5274 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5275 return;
5276 }
5277 vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize );
5278 }
5279
5280 void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duin t index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
5281 {
5282 if (isContextLost())
5283 return;
5284 if (!v) {
5285 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no ar ray");
5286 return;
5287 }
5288 if (size < expectedSize) {
5289 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "inval id size");
5290 return;
5291 }
5292 if (index >= m_maxVertexAttribs) {
5293 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range");
5294 return;
5295 }
5296 // In GL, we skip setting vertexAttrib0 values.
5297 switch (expectedSize) {
5298 case 1:
5299 m_context->vertexAttrib1fv(index, v);
5300 break;
5301 case 2:
5302 m_context->vertexAttrib2fv(index, v);
5303 break;
5304 case 3:
5305 m_context->vertexAttrib3fv(index, v);
5306 break;
5307 case 4:
5308 m_context->vertexAttrib4fv(index, v);
5309 break;
5310 }
5311 VertexAttribValue& attribValue = m_vertexAttribValue[index];
5312 attribValue.initValue();
5313 for (int ii = 0; ii < expectedSize; ++ii)
5314 attribValue.value[ii] = v[ii];
5315 }
5316
5317 void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext >*)
5318 {
5319 RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().web glcontextlostEvent, false, true, "");
5320 canvas()->dispatchEvent(event);
5321 m_restoreAllowed = event->defaultPrevented();
5322 deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAll owed);
5323 if ((m_contextLostMode == RealLostContext || m_contextLostMode == AutoRecove rSyntheticLostContext) && m_restoreAllowed)
5324 m_restoreTimer.startOneShot(0);
5325 }
5326
5327 void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
5328 {
5329 ASSERT(isContextLost());
5330
5331 // The rendering context is not restored unless the default behavior of the
5332 // webglcontextlost event was prevented earlier.
5333 //
5334 // Because of the way m_restoreTimer is set up for real vs. synthetic lost
5335 // context events, we don't have to worry about this test short-circuiting
5336 // the retry loop for real context lost events.
5337 if (!m_restoreAllowed)
5338 return;
5339
5340 Frame* frame = canvas()->document().frame();
5341 if (!frame)
5342 return;
5343
5344 Settings* settings = frame->settings();
5345
5346 if (!frame->loader()->client()->allowWebGL(settings && settings->webGLEnable d()))
5347 return;
5348
5349 // Reset the context attributes back to the requested attributes and re-appl y restrictions
5350 m_attributes = adjustAttributes(m_requestedAttributes, settings);
5351
5352 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes));
5353
5354 if (!context) {
5355 if (m_contextLostMode == RealLostContext)
5356 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
5357 else
5358 // This likely shouldn't happen but is the best way to report it to the WebGL app.
5359 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error r estoring context");
5360 return;
5361 }
5362
5363 RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptR ef(new WebGLRenderingContextEvictionManager());
5364
5365 // Construct a new drawing buffer with the new GraphicsContext3D.
5366 m_drawingBuffer->releaseResources();
5367 DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawing Buffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
5368 m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release());
5369
5370 if (m_drawingBuffer->isZeroSized())
5371 return;
5372
5373 m_drawingBuffer->bind();
5374
5375 lost_context_errors_.clear();
5376
5377 m_context = context;
5378 m_contextLost = false;
5379
5380 setupFlags();
5381 initializeNewContext();
5382 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextr estoredEvent, false, true, ""));
5383 }
5384
5385 String WebGLRenderingContext::ensureNotNull(const String& text) const
5386 {
5387 if (text.isNull())
5388 return WTF::emptyString();
5389 return text;
5390 }
5391
5392 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
5393 : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
5394 , m_capacity(capacity)
5395 {
5396 }
5397
5398 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSi ze& size)
5399 {
5400 int i;
5401 for (i = 0; i < m_capacity; ++i) {
5402 ImageBuffer* buf = m_buffers[i].get();
5403 if (!buf)
5404 break;
5405 if (buf->logicalSize() != size)
5406 continue;
5407 bubbleToFront(i);
5408 return buf;
5409 }
5410
5411 OwnPtr<ImageBuffer> temp = ImageBuffer::create(size, 1);
5412 if (!temp)
5413 return 0;
5414 i = std::min(m_capacity - 1, i);
5415 m_buffers[i] = temp.release();
5416
5417 ImageBuffer* buf = m_buffers[i].get();
5418 bubbleToFront(i);
5419 return buf;
5420 }
5421
5422 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
5423 {
5424 for (int i = idx; i > 0; --i)
5425 m_buffers[i].swap(m_buffers[i-1]);
5426 }
5427
5428 namespace {
5429
5430 String GetErrorString(GC3Denum error)
5431 {
5432 switch (error) {
5433 case GraphicsContext3D::INVALID_ENUM:
5434 return "INVALID_ENUM";
5435 case GraphicsContext3D::INVALID_VALUE:
5436 return "INVALID_VALUE";
5437 case GraphicsContext3D::INVALID_OPERATION:
5438 return "INVALID_OPERATION";
5439 case GraphicsContext3D::OUT_OF_MEMORY:
5440 return "OUT_OF_MEMORY";
5441 case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION:
5442 return "INVALID_FRAMEBUFFER_OPERATION";
5443 case GraphicsContext3D::CONTEXT_LOST_WEBGL:
5444 return "CONTEXT_LOST_WEBGL";
5445 default:
5446 return String::format("WebGL ERROR(0x%04X)", error);
5447 }
5448 }
5449
5450 } // namespace anonymous
5451
5452 void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functi onName, const char* description, ConsoleDisplayPreference display)
5453 {
5454 String errorType = GetErrorString(error);
5455 if (m_synthesizedErrorsToConsole && display == DisplayInConsole) {
5456 String message = String("WebGL: ") + errorType + ": " + String(function Name) + ": " + String(description);
5457 printGLErrorToConsole(message);
5458 }
5459 if (!isContextLost())
5460 m_context->synthesizeGLError(error);
5461 else {
5462 if (lost_context_errors_.find(error) == WTF::notFound)
5463 lost_context_errors_.append(error);
5464 }
5465 InspectorInstrumentation::didFireWebGLError(canvas(), errorType);
5466 }
5467
5468 void WebGLRenderingContext::emitGLWarning(const char* functionName, const char* description)
5469 {
5470 if (m_synthesizedErrorsToConsole) {
5471 String message = String("WebGL: ") + String(functionName) + ": " + Strin g(description);
5472 printGLErrorToConsole(message);
5473 }
5474 InspectorInstrumentation::didFireWebGLWarning(canvas());
5475 }
5476
5477 void WebGLRenderingContext::applyStencilTest()
5478 {
5479 bool haveStencilBuffer = false;
5480
5481 if (m_framebufferBinding)
5482 haveStencilBuffer = m_framebufferBinding->hasStencilBuffer();
5483 else {
5484 RefPtr<WebGLContextAttributes> attributes = getContextAttributes();
5485 haveStencilBuffer = attributes->stencil();
5486 }
5487 enableOrDisable(GraphicsContext3D::STENCIL_TEST,
5488 m_stencilEnabled && haveStencilBuffer);
5489 }
5490
5491 void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable)
5492 {
5493 if (isContextLost())
5494 return;
5495 if (enable)
5496 m_context->enable(capability);
5497 else
5498 m_context->disable(capability);
5499 }
5500
5501 IntSize WebGLRenderingContext::clampedCanvasSize()
5502 {
5503 return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]),
5504 clamp(canvas()->height(), 1, m_maxViewportDims[1]));
5505 }
5506
5507 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
5508 {
5509 if (isContextLost() || !m_webglDrawBuffers)
5510 return 0;
5511 if (!m_maxDrawBuffers)
5512 m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuf fers);
5513 if (!m_maxColorAttachments)
5514 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxCo lorAttachments);
5515 // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
5516 return std::min(m_maxDrawBuffers, m_maxColorAttachments);
5517 }
5518
5519 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
5520 {
5521 if (isContextLost() || !m_webglDrawBuffers)
5522 return 0;
5523 if (!m_maxColorAttachments)
5524 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxCo lorAttachments);
5525 return m_maxColorAttachments;
5526 }
5527
5528 void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf)
5529 {
5530 m_backDrawBuffer = buf;
5531 }
5532
5533 void WebGLRenderingContext::restoreCurrentFramebuffer()
5534 {
5535 bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get());
5536 }
5537
5538 void WebGLRenderingContext::restoreCurrentTexture2D()
5539 {
5540 bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUni t].m_texture2DBinding.get());
5541 }
5542
5543 void WebGLRenderingContext::multisamplingChanged(bool enabled)
5544 {
5545 if (m_multisamplingAllowed != enabled) {
5546 m_multisamplingAllowed = enabled;
5547 forceLostContext(WebGLRenderingContext::AutoRecoverSyntheticLostContext) ;
5548 }
5549 }
5550
5551 void WebGLRenderingContext::findNewMaxEnabledAttribIndex()
5552 {
5553 // Trace backwards from the current max to find the new max enabled attrib i ndex
5554 int startIndex = m_onePlusMaxEnabledAttribIndex - 1;
5555 for (int i = startIndex; i >= 0; --i) {
5556 if (m_boundVertexArrayObject->getVertexAttribState(i).enabled) {
5557 m_onePlusMaxEnabledAttribIndex = i + 1;
5558 return;
5559 }
5560 }
5561 m_onePlusMaxEnabledAttribIndex = 0;
5562 }
5563
5564 void WebGLRenderingContext::findNewMaxNonDefaultTextureUnit()
5565 {
5566 // Trace backwards from the current max to find the new max non-default text ure unit
5567 int startIndex = m_onePlusMaxNonDefaultTextureUnit - 1;
5568 for (int i = startIndex; i >= 0; --i) {
5569 if (m_textureUnits[i].m_texture2DBinding
5570 || m_textureUnits[i].m_textureCubeMapBinding) {
5571 m_onePlusMaxNonDefaultTextureUnit = i + 1;
5572 return;
5573 }
5574 }
5575 m_onePlusMaxNonDefaultTextureUnit = 0;
5576 }
5577
5578 } // namespace WebCore 143 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698