Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / canvas / WebGLRenderingContext.cpp
index 56668d6..02a321e 100644 (file)
@@ -453,17 +453,6 @@ namespace {
             break;
         }
     }
-
-    blink::WebGraphicsContext3D::Attributes adjustAttributes(const blink::WebGraphicsContext3D::Attributes& attributes, Settings* settings)
-    {
-        blink::WebGraphicsContext3D::Attributes adjustedAttributes = attributes;
-        if (adjustedAttributes.antialias) {
-            if (settings && !settings->openGLMultisamplingEnabled())
-                adjustedAttributes.antialias = false;
-        }
-
-        return adjustedAttributes;
-    }
 } // namespace anonymous
 
 class WebGLRenderingContextLostCallback : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
@@ -506,41 +495,24 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
         return nullptr;
     }
 
-    bool preserveDrawingBuffer = attrs ? attrs->preserveDrawingBuffer() : false;
-    blink::WebGraphicsContext3D::Attributes requestedAttributes = attrs ? attrs->attributes() : blink::WebGraphicsContext3D::Attributes();
+    // The only situation that attrs is null is through Document::getCSSCanvasContext().
+    RefPtr<WebGLContextAttributes> defaultAttrs;
     if (!attrs) {
-        // Default attributes.
-        ASSERT(requestedAttributes.alpha);
-        ASSERT(requestedAttributes.depth);
-        ASSERT(requestedAttributes.antialias);
-        ASSERT(requestedAttributes.premultipliedAlpha);
-        ASSERT(!requestedAttributes.failIfMajorPerformanceCaveat);
-        requestedAttributes.stencil = false;
+        defaultAttrs = WebGLContextAttributes::create();
+        attrs = defaultAttrs.get();
     }
-    requestedAttributes.noExtensions = true;
-    requestedAttributes.shareResources = true;
-    requestedAttributes.preferDiscreteGPU = true;
-    requestedAttributes.topDocumentURL = document.topDocument()->url().string();
-
-    blink::WebGraphicsContext3D::Attributes attributes = adjustAttributes(requestedAttributes, settings);
-
+    blink::WebGraphicsContext3D::Attributes attributes = attrs->attributes(document.topDocument()->url().string(), settings);
     OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes));
     if (!context || !context->makeContextCurrent()) {
         canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context."));
         return nullptr;
     }
 
-    RefPtr<GraphicsContext3D> contextSupport(GraphicsContext3D::createContextSupport(context.get()));
-
-    if (!contextSupport) {
-        canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context."));
-        return nullptr;
-    }
-
-    if (contextSupport->supportsExtension("GL_EXT_debug_marker"))
+    Extensions3DUtil extensionsUtil(context.get());
+    if (extensionsUtil.supportsExtension("GL_EXT_debug_marker"))
         context->pushGroupMarkerEXT("WebGLRenderingContext");
 
-    OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context.release(), contextSupport, attributes, requestedAttributes, preserveDrawingBuffer));
+    OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context.release(), attrs));
     renderingContext->suspendIfNeeded();
 
     if (renderingContext->m_drawingBuffer->isZeroSized()) {
@@ -551,11 +523,10 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen
     return renderingContext.release();
 }
 
-WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, PassRefPtr<GraphicsContext3D> contextSupport, blink::WebGraphicsContext3D::Attributes attributes, blink::WebGraphicsContext3D::Attributes requestedAttributes, bool preserveDrawingBuffer)
+WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, WebGLContextAttributes* requestedAttributes)
     : CanvasRenderingContext(passedCanvas)
     , ActiveDOMObject(&passedCanvas->document())
     , m_context(context)
-    , m_contextSupport(contextSupport)
     , m_drawingBuffer(0)
     , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchContextLostEvent)
     , m_restoreAllowed(false)
@@ -563,17 +534,15 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     , m_generatedImageCache(4)
     , m_contextLost(false)
     , m_contextLostMode(SyntheticLostContext)
-    , m_attributes(attributes)
-    , m_requestedAttributes(requestedAttributes)
+    , m_requestedAttributes(requestedAttributes->clone())
     , m_synthesizedErrorsToConsole(true)
     , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole)
     , m_multisamplingAllowed(false)
     , m_multisamplingObserverRegistered(false)
     , m_onePlusMaxEnabledAttribIndex(0)
     , m_onePlusMaxNonDefaultTextureUnit(0)
-    , m_preserveDrawingBuffer(preserveDrawingBuffer)
 {
-    ASSERT(m_contextSupport);
+    ASSERT(m_context);
     ScriptWrappable::init(this);
 
     m_contextGroup = WebGLContextGroup::create();
@@ -585,7 +554,7 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager());
 
     // Create the DrawingBuffer and initialize the platform layer.
-    DrawingBuffer::PreserveDrawingBuffer preserve = preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
+    DrawingBuffer::PreserveDrawingBuffer preserve = requestedAttributes->preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
     m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release());
 
     if (!m_drawingBuffer->isZeroSized()) {
@@ -599,7 +568,7 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     static const char* const bothPrefixes[] = { "", "WEBKIT_", 0, };
 
     registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays);
-    registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, PrefixedExtension, webkitPrefix);
+    registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, ApprovedExtension, bothPrefixes);
     registerExtension<OESElementIndexUint>(m_oesElementIndexUint);
     registerExtension<OESStandardDerivatives>(m_oesStandardDerivatives);
     registerExtension<OESTextureFloat>(m_oesTextureFloat);
@@ -609,8 +578,8 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     registerExtension<OESVertexArrayObject>(m_oesVertexArrayObject);
     registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, PrefixedExtension, webkitPrefix);
     registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC, PrefixedExtension, webkitPrefix);
-    registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, PrefixedExtension, bothPrefixes);
-    registerExtension<WebGLDepthTexture>(m_webglDepthTexture, PrefixedExtension, bothPrefixes);
+    registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, ApprovedExtension, bothPrefixes);
+    registerExtension<WebGLDepthTexture>(m_webglDepthTexture, ApprovedExtension, bothPrefixes);
     registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers);
     registerExtension<WebGLLoseContext>(m_webglLoseContext, ApprovedExtension, bothPrefixes);
 
@@ -706,19 +675,19 @@ void WebGLRenderingContext::initializeNewContext()
 
 void WebGLRenderingContext::setupFlags()
 {
-    ASSERT(m_contextSupport);
+    ASSERT(m_context);
     if (Page* p = canvas()->document().page()) {
         m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled();
 
-        if (!m_multisamplingObserverRegistered && m_requestedAttributes.antialias) {
+        if (!m_multisamplingObserverRegistered && m_requestedAttributes->antialias()) {
             m_multisamplingAllowed = m_drawingBuffer->multisample();
             p->addMultisamplingChangedObserver(this);
             m_multisamplingObserverRegistered = true;
         }
     }
 
-    m_isGLES2NPOTStrict = !m_contextSupport->isExtensionEnabled("GL_OES_texture_npot");
-    m_isDepthStencilSupported = m_contextSupport->isExtensionEnabled("GL_OES_packed_depth_stencil");
+    m_isGLES2NPOTStrict = !extensionsUtil()->isExtensionEnabled("GL_OES_texture_npot");
+    m_isDepthStencilSupported = extensionsUtil()->isExtensionEnabled("GL_OES_packed_depth_stencil");
 }
 
 bool WebGLRenderingContext::allowPrivilegedExtensions() const
@@ -771,10 +740,10 @@ WebGLRenderingContext::~WebGLRenderingContext()
         delete m_extensions[i];
 
     // Context must be removed from the group prior to the destruction of the
-    // GraphicsContext3D, otherwise shared objects may not be properly deleted.
+    // WebGraphicsContext3D, otherwise shared objects may not be properly deleted.
     m_contextGroup->removeContext(this);
 
-    destroyGraphicsContext3D();
+    destroyContext();
 
     if (m_multisamplingObserverRegistered) {
         Page* page = canvas()->document().page();
@@ -785,7 +754,7 @@ WebGLRenderingContext::~WebGLRenderingContext()
     willDestroyContext(this);
 }
 
-void WebGLRenderingContext::destroyGraphicsContext3D()
+void WebGLRenderingContext::destroyContext()
 {
     m_contextLost = true;
 
@@ -793,9 +762,7 @@ void WebGLRenderingContext::destroyGraphicsContext3D()
     // in order for the context to be released.
     m_drawingBuffer->releaseResources();
 
-    if (m_contextSupport) {
-        m_contextSupport.clear();
-    }
+    m_extensionsUtil.clear();
 
     if (m_context) {
         m_context->setContextLostCallback(0);
@@ -831,7 +798,7 @@ bool WebGLRenderingContext::clearIfComposited(GLbitfield mask)
         return false;
 
     if (!m_drawingBuffer->layerComposited() || m_layerCleared
-        || m_preserveDrawingBuffer || (mask && m_framebufferBinding))
+        || m_requestedAttributes->preserveDrawingBuffer() || (mask && m_framebufferBinding))
         return false;
 
     RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
@@ -910,7 +877,7 @@ void WebGLRenderingContext::paintRenderingResultsToCanvas()
 
     // Until the canvas is written to by the application, the clear that
     // happened after it was composited should be ignored by the compositor.
-    if (m_drawingBuffer->layerComposited() && !m_preserveDrawingBuffer) {
+    if (m_drawingBuffer->layerComposited() && !m_requestedAttributes->preserveDrawingBuffer()) {
         m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer());
 
         canvas()->makePresentationCopy();
@@ -1346,7 +1313,7 @@ void WebGLRenderingContext::clear(GLbitfield mask)
         return;
     }
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
         return;
     }
@@ -1473,7 +1440,7 @@ void WebGLRenderingContext::compressedTexSubImage2D(GLenum target, GLint level,
 
 bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GLenum format)
 {
-    if (GraphicsContext3D::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
+    if (WebGLImageConversion::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) {
         synthesizeGLError(GL_INVALID_OPERATION, functionName, "format can not be set, only rendered to");
         return false;
     }
@@ -1500,7 +1467,7 @@ void WebGLRenderingContext::copyTexImage2D(GLenum target, GLint level, GLenum in
         return;
     }
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
         return;
     }
@@ -1543,7 +1510,7 @@ void WebGLRenderingContext::copyTexSubImage2D(GLenum target, GLint level, GLint
         return;
     }
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason);
         return;
     }
@@ -1650,7 +1617,7 @@ bool WebGLRenderingContext::deleteObject(WebGLObject* object)
     if (object->object()) {
         // We need to pass in context here because we want
         // things in this context unbound.
-        object->deleteObject(webGraphicsContext3D());
+        object->deleteObject(m_context.get());
     }
     return true;
 }
@@ -1763,7 +1730,7 @@ void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* sha
         return;
     }
     m_context->detachShader(objectOrZero(program), objectOrZero(shader));
-    shader->onDetached(webGraphicsContext3D());
+    shader->onDetached(m_context.get());
 }
 
 void WebGLRenderingContext::disable(GLenum cap)
@@ -2148,18 +2115,14 @@ PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes()
         return 0;
     // We always need to return a new WebGLContextAttributes object to
     // prevent the user from mutating any cached version.
-
-    // Also, we need to enforce requested values of "false" for depth
-    // and stencil, regardless of the properties of the underlying
-    // GraphicsContext3D or DrawingBuffer.
-    RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes());
-    attributes->setPreserveDrawingBuffer(m_preserveDrawingBuffer);
-    if (!m_attributes.depth)
+    blink::WebGraphicsContext3D::Attributes attrs = m_context->getContextAttributes();
+    RefPtr<WebGLContextAttributes> attributes = m_requestedAttributes->clone();
+    // Some requested attributes may not be honored, so we need to query the underlying
+    // context/drawing buffer and adjust accordingly.
+    if (m_requestedAttributes->depth() && !attrs.depth)
         attributes->setDepth(false);
-    if (!m_attributes.stencil)
+    if (m_requestedAttributes->stencil() && !attrs.stencil)
         attributes->setStencil(false);
-    // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(),
-    // but it makes its own determination of whether multisampling is supported.
     attributes->setAntialias(m_drawingBuffer->multisample());
     return attributes.release();
 }
@@ -2313,7 +2276,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GLenum pname)
     case GL_CURRENT_PROGRAM:
         return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
     case GL_DEPTH_BITS:
-        if (!m_framebufferBinding && !m_attributes.depth)
+        if (!m_framebufferBinding && !m_requestedAttributes->depth())
             return WebGLGetInfo(intZero);
         return getIntParameter(pname);
     case GL_DEPTH_CLEAR_VALUE:
@@ -2408,7 +2371,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GLenum pname)
     case GL_STENCIL_BACK_WRITEMASK:
         return getUnsignedIntParameter(pname);
     case GL_STENCIL_BITS:
-        if (!m_framebufferBinding && !m_attributes.stencil)
+        if (!m_framebufferBinding && !m_requestedAttributes->stencil())
             return WebGLGetInfo(intZero);
         return getIntParameter(pname);
     case GL_STENCIL_CLEAR_VALUE:
@@ -3108,14 +3071,14 @@ void WebGLRenderingContext::readPixels(GLint x, GLint y, GLsizei width, GLsizei
         return;
     }
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
         return;
     }
     // Calculate array size, taking into consideration of PACK_ALIGNMENT.
     unsigned totalBytesRequired = 0;
     unsigned padding = 0;
-    GLenum error = m_contextSupport->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
+    GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding);
     if (error != GL_NO_ERROR) {
         synthesizeGLError(error, "readPixels", "invalid dimensions");
         return;
@@ -3313,6 +3276,18 @@ void WebGLRenderingContext::stencilOpSeparate(GLenum face, GLenum fail, GLenum z
     m_context->stencilOpSeparate(face, fail, zfail, zpass);
 }
 
+GLenum WebGLRenderingContext::convertTexInternalFormat(GLenum internalformat, GLenum type)
+{
+    // Convert to sized internal formats that are renderable with GL_CHROMIUM_color_buffer_float_rgb(a).
+    if (type == GL_FLOAT && internalformat == GL_RGBA
+        && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"))
+        return GL_RGBA32F_EXT;
+    if (type == GL_FLOAT && internalformat == GL_RGB
+        && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"))
+        return GL_RGB32F_EXT;
+    return internalformat;
+}
+
 void WebGLRenderingContext::texImage2DBase(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels, ExceptionState& exceptionState)
 {
     // All calling functions check isContextLost, so a duplicate check is not needed here.
@@ -3322,29 +3297,28 @@ void WebGLRenderingContext::texImage2DBase(GLenum target, GLint level, GLenum in
     ASSERT(tex);
     ASSERT(!level || !WebGLTexture::isNPOT(width, height));
     ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat));
-    m_context->texImage2D(target, level, internalformat, width, height,
-                          border, format, type, pixels);
+    m_context->texImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels);
     tex->setLevelInfo(target, level, internalformat, width, height, type);
 }
 
-void WebGLRenderingContext::texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState)
+void WebGLRenderingContext::texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState)
 {
     // All calling functions check isContextLost, so a duplicate check is not needed here.
     Vector<uint8_t> data;
-    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
+    WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
     if (!imageExtractor.extractSucceeded()) {
         synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
         return;
     }
-    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
-    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
+    WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
+    WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
     const void* imagePixelData = imageExtractor.imagePixelData();
 
     bool needConversion = true;
-    if (type == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
+    if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY)
         needConversion = false;
     else {
-        if (!m_contextSupport->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
+        if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
             synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "packImage error");
             return;
         }
@@ -3426,11 +3400,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     Vector<uint8_t> tempData;
     bool changeUnpackAlignment = false;
     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
-        if (!m_contextSupport->extractTextureData(width, height, format, type,
-                                           m_unpackAlignment,
-                                           m_unpackFlipY, m_unpackPremultiplyAlpha,
-                                           data,
-                                           tempData))
+        if (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData))
             return;
         data = tempData.data();
         changeUnpackAlignment = true;
@@ -3454,7 +3424,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GL_RGBA && type == GL_UNSIGNED_BYTE)
         needConversion = false;
     else {
-        if (!m_contextSupport->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
+        if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
             synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
             return;
         }
@@ -3479,7 +3449,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0))
         return;
 
-    texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+    texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum internalformat,
@@ -3494,14 +3464,14 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     if (GL_TEXTURE_2D == target && texture) {
         if (!canvas->is3D()) {
             ImageBuffer* buffer = canvas->buffer();
-            if (buffer && buffer->copyToPlatformTexture(*m_contextSupport.get(), texture->object(), internalformat, type,
+            if (buffer && buffer->copyToPlatformTexture(m_context.get(), texture->object(), internalformat, type,
                 level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
                 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
                 return;
             }
         } else {
             WebGLRenderingContext* gl = toWebGLRenderingContext(canvas->renderingContext());
-            if (gl && gl->m_drawingBuffer->copyToPlatformTexture(*m_contextSupport.get(), texture->object(), internalformat, type,
+            if (gl && gl->m_drawingBuffer->copyToPlatformTexture(m_context.get(), texture->object(), internalformat, type,
                 level, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
                 texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type);
                 return;
@@ -3513,7 +3483,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     if (imageData)
         texImage2D(target, level, internalformat, format, type, imageData.get(), exceptionState);
     else
-        texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+        texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy)
@@ -3541,7 +3511,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     // Otherwise, it will fall back to the normal SW path.
     WebGLTexture* texture = validateTextureBinding("texImage2D", target, true);
     if (GL_TEXTURE_2D == target && texture) {
-        if (video->copyVideoTextureToPlatformTexture(m_contextSupport.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
+        if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) {
             texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type);
             return;
         }
@@ -3551,7 +3521,7 @@ void WebGLRenderingContext::texImage2D(GLenum target, GLint level, GLenum intern
     RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode());
     if (!image)
         return;
-    texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+    texImage2DImpl(target, level, internalformat, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 void WebGLRenderingContext::texParameter(GLenum target, GLenum pname, GLfloat paramf, GLint parami, bool isFloat)
@@ -3623,24 +3593,24 @@ void WebGLRenderingContext::texSubImage2DBase(GLenum target, GLint level, GLint
     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
 }
 
-void WebGLRenderingContext::texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState)
+void WebGLRenderingContext::texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState)
 {
     // All calling functions check isContextLost, so a duplicate check is not needed here.
     Vector<uint8_t> data;
-    GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
+    WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE);
     if (!imageExtractor.extractSucceeded()) {
         synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image");
         return;
     }
-    GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
-    GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
+    WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
+    WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
     const void* imagePixelData = imageExtractor.imagePixelData();
 
     bool needConversion = true;
-    if (type == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
+    if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY)
         needConversion = false;
     else {
-        if (!m_contextSupport->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
+        if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
             synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data");
             return;
         }
@@ -3664,7 +3634,7 @@ void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoff
     Vector<uint8_t> tempData;
     bool changeUnpackAlignment = false;
     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
-        if (!m_contextSupport->extractTextureData(width, height, format, type,
+        if (!WebGLImageConversion::extractTextureData(width, height, format, type,
                                            m_unpackAlignment,
                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
                                            data,
@@ -3693,7 +3663,7 @@ void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoff
     if (format == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
         needConversion = false;
     else {
-        if (!m_contextSupport->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
+        if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
             synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data");
             return;
         }
@@ -3718,7 +3688,7 @@ void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoff
     if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
         return;
 
-    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
@@ -3732,7 +3702,7 @@ void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoff
     if (imageData)
         texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), exceptionState);
     else
-        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+        texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
@@ -3745,7 +3715,7 @@ void WebGLRenderingContext::texSubImage2D(GLenum target, GLint level, GLint xoff
     RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode());
     if (!image)
         return;
-    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState);
 }
 
 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GLfloat x)
@@ -4035,7 +4005,7 @@ void WebGLRenderingContext::useProgram(WebGLProgram* program)
     }
     if (m_currentProgram != program) {
         if (m_currentProgram)
-            m_currentProgram->onDetached(webGraphicsContext3D());
+            m_currentProgram->onDetached(m_context.get());
         m_currentProgram = program;
         m_context->useProgram(objectOrZero(program));
         if (program)
@@ -4216,7 +4186,7 @@ void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMo
     removeAllCompressedTextureFormats();
 
     if (mode != RealLostContext)
-        destroyGraphicsContext3D();
+        destroyContext();
 
     ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole;
     synthesizeGLError(GC3D_CONTEXT_LOST_WEBGL, "loseContext", "context lost", display);
@@ -4252,6 +4222,13 @@ blink::WebLayer* WebGLRenderingContext::platformLayer() const
     return m_drawingBuffer->platformLayer();
 }
 
+Extensions3DUtil* WebGLRenderingContext::extensionsUtil()
+{
+    if (!m_extensionsUtil)
+        m_extensionsUtil = adoptPtr(new Extensions3DUtil(m_context.get()));
+    return m_extensionsUtil.get();
+}
+
 void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object)
 {
     m_contextGroup->removeObject(object);
@@ -4291,7 +4268,7 @@ void WebGLRenderingContext::stop()
 {
     if (!isContextLost()) {
         forceLostContext(SyntheticLostContext);
-        destroyGraphicsContext3D();
+        destroyContext();
     }
 }
 
@@ -4451,8 +4428,8 @@ void WebGLRenderingContext::createFallbackBlackTextures1x1()
 
 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GLenum texInternalFormat, GLenum colorBufferFormat)
 {
-    unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat);
-    unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat);
+    unsigned need = WebGLImageConversion::getChannelBitsByFormat(texInternalFormat);
+    unsigned have = WebGLImageConversion::getChannelBitsByFormat(colorBufferFormat);
     return (need & have) == need;
 }
 
@@ -4460,7 +4437,7 @@ GLenum WebGLRenderingContext::boundFramebufferColorFormat()
 {
     if (m_framebufferBinding && m_framebufferBinding->object())
         return m_framebufferBinding->colorBufferFormat();
-    if (m_attributes.alpha)
+    if (m_requestedAttributes->alpha())
         return GL_RGBA;
     return GL_RGB;
 }
@@ -4802,14 +4779,14 @@ bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GLint
     }
 
     unsigned totalBytesRequired;
-    GLenum error = m_contextSupport->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
+    GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
     if (error != GL_NO_ERROR) {
         synthesizeGLError(error, functionName, "invalid texture dimensions");
         return false;
     }
     if (pixels->byteLength() < totalBytesRequired) {
         if (m_unpackAlignment != 1) {
-            error = m_contextSupport->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
+            error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
             if (pixels->byteLength() == totalBytesRequired) {
                 synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
                 return false;
@@ -5237,7 +5214,7 @@ bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GLenum
     }
 
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
         return false;
     }
@@ -5287,7 +5264,7 @@ bool WebGLRenderingContext::validateDrawElements(const char* functionName, GLenu
     }
 
     const char* reason = "framebuffer incomplete";
-    if (m_framebufferBinding && !m_framebufferBinding->onAccess(webGraphicsContext3D(), &reason)) {
+    if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
         synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason);
         return false;
     }
@@ -5424,13 +5401,9 @@ void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
     if (!frame->loader().client()->allowWebGL(settings && settings->webGLEnabled()))
         return;
 
-    // Reset the context attributes back to the requested attributes and re-apply restrictions
-    m_attributes = adjustAttributes(m_requestedAttributes, settings);
-
-    OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(m_attributes));
-    RefPtr<GraphicsContext3D> contextSupport(GraphicsContext3D::createContextSupport(context.get()));
-
-    if (!context || !contextSupport) {
+    blink::WebGraphicsContext3D::Attributes attributes = m_requestedAttributes->attributes(canvas()->document().topDocument()->url().string(), settings);
+    OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes));
+    if (!context) {
         if (m_contextLostMode == RealLostContext) {
             m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts);
         } else {
@@ -5442,9 +5415,9 @@ void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
 
     RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager());
 
-    // Construct a new drawing buffer with the new GraphicsContext3D.
+    // Construct a new drawing buffer with the new WebGraphicsContext3D.
     m_drawingBuffer->releaseResources();
-    DrawingBuffer::PreserveDrawingBuffer preserve = m_preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
+    DrawingBuffer::PreserveDrawingBuffer preserve = m_requestedAttributes->preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard;
     m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release());
 
     if (m_drawingBuffer->isZeroSized())
@@ -5454,7 +5427,6 @@ void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*)
 
     m_lostContextErrors.clear();
 
-    m_contextSupport = contextSupport;
     m_context = context.release();
     m_contextLost = false;