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

Side by Side Diff: sky/engine/core/html/canvas/WebGLRenderingContextBase.cpp

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

Powered by Google App Engine
This is Rietveld 408576698