Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  * Copyright (C) 2010 Google Inc. All rights reserved.
      4  * Copyright (C) 2010 Mozilla Corporation. All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "config.h"
     29 
     30 #include "platform/graphics/GraphicsContext3D.h"
     31 #include "platform/CheckedInt.h"
     32 #include "platform/graphics/GraphicsContext.h"
     33 #include "platform/graphics/ImageBuffer.h"
     34 #include "platform/graphics/ImageObserver.h"
     35 #include "platform/graphics/gpu/DrawingBuffer.h"
     36 #include "platform/image-decoders/ImageDecoder.h"
     37 #include "third_party/skia/include/gpu/GrContext.h"
     38 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
     39 #include "wtf/CPU.h"
     40 #include "wtf/text/CString.h"
     41 #include "wtf/text/StringHash.h"
     42 
     43 #include "public/platform/Platform.h"
     44 #include "public/platform/WebGraphicsContext3D.h"
     45 #include "public/platform/WebGraphicsContext3DProvider.h"
     46 
     47 namespace WebCore {
     48 
     49 namespace {
     50 
     51 void getDrawingParameters(DrawingBuffer* drawingBuffer, blink::WebGraphicsContext3D* graphicsContext3D,
     52                           Platform3DObject* frameBufferId, int* width, int* height)
     53 {
     54     ASSERT(drawingBuffer);
     55     *frameBufferId = drawingBuffer->framebuffer();
     56     *width = drawingBuffer->size().width();
     57     *height = drawingBuffer->size().height();
     58 }
     59 
     60 } // anonymous namespace
     61 
     62 GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
     63     : m_impl(webContext.get())
     64     , m_ownedWebContext(webContext)
     65     , m_initializedAvailableExtensions(false)
     66     , m_layerComposited(false)
     67     , m_preserveDrawingBuffer(preserveDrawingBuffer)
     68     , m_packAlignment(4)
     69     , m_resourceSafety(ResourceSafetyUnknown)
     70     , m_grContext(0)
     71 {
     72 }
     73 
     74 GraphicsContext3D::GraphicsContext3D(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
     75     : m_provider(provider)
     76     , m_impl(m_provider->context3d())
     77     , m_initializedAvailableExtensions(false)
     78     , m_layerComposited(false)
     79     , m_preserveDrawingBuffer(preserveDrawingBuffer)
     80     , m_packAlignment(4)
     81     , m_resourceSafety(ResourceSafetyUnknown)
     82     , m_grContext(m_provider->grContext())
     83 {
     84 }
     85 
     86 GraphicsContext3D::~GraphicsContext3D()
     87 {
     88     setContextLostCallback(nullptr);
     89     setErrorMessageCallback(nullptr);
     90 }
     91 
     92 // Macros to assist in delegating from GraphicsContext3D to
     93 // WebGraphicsContext3D.
     94 
     95 #define DELEGATE_TO_WEBCONTEXT(name) \
     96 void GraphicsContext3D::name() \
     97 { \
     98     m_impl->name(); \
     99 }
    100 
    101 #define DELEGATE_TO_WEBCONTEXT_R(name, rt) \
    102 rt GraphicsContext3D::name() \
    103 { \
    104     return m_impl->name(); \
    105 }
    106 
    107 #define DELEGATE_TO_WEBCONTEXT_1(name, t1) \
    108 void GraphicsContext3D::name(t1 a1) \
    109 { \
    110     m_impl->name(a1); \
    111 }
    112 
    113 #define DELEGATE_TO_WEBCONTEXT_1R(name, t1, rt) \
    114 rt GraphicsContext3D::name(t1 a1) \
    115 { \
    116     return m_impl->name(a1); \
    117 }
    118 
    119 #define DELEGATE_TO_WEBCONTEXT_2(name, t1, t2) \
    120 void GraphicsContext3D::name(t1 a1, t2 a2) \
    121 { \
    122     m_impl->name(a1, a2); \
    123 }
    124 
    125 #define DELEGATE_TO_WEBCONTEXT_2R(name, t1, t2, rt) \
    126 rt GraphicsContext3D::name(t1 a1, t2 a2) \
    127 { \
    128     return m_impl->name(a1, a2); \
    129 }
    130 
    131 #define DELEGATE_TO_WEBCONTEXT_3(name, t1, t2, t3) \
    132 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
    133 { \
    134     m_impl->name(a1, a2, a3); \
    135 }
    136 
    137 #define DELEGATE_TO_WEBCONTEXT_3R(name, t1, t2, t3, rt) \
    138 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3) \
    139 { \
    140     return m_impl->name(a1, a2, a3); \
    141 }
    142 
    143 #define DELEGATE_TO_WEBCONTEXT_4(name, t1, t2, t3, t4) \
    144 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
    145 { \
    146     m_impl->name(a1, a2, a3, a4); \
    147 }
    148 
    149 #define DELEGATE_TO_WEBCONTEXT_4R(name, t1, t2, t3, t4, rt) \
    150 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4) \
    151 { \
    152     return m_impl->name(a1, a2, a3, a4); \
    153 }
    154 
    155 #define DELEGATE_TO_WEBCONTEXT_5(name, t1, t2, t3, t4, t5) \
    156 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
    157 { \
    158     m_impl->name(a1, a2, a3, a4, a5); \
    159 }
    160 
    161 #define DELEGATE_TO_WEBCONTEXT_6(name, t1, t2, t3, t4, t5, t6) \
    162 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
    163 { \
    164     m_impl->name(a1, a2, a3, a4, a5, a6); \
    165 }
    166 
    167 #define DELEGATE_TO_WEBCONTEXT_6R(name, t1, t2, t3, t4, t5, t6, rt) \
    168 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
    169 { \
    170     return m_impl->name(a1, a2, a3, a4, a5, a6); \
    171 }
    172 
    173 #define DELEGATE_TO_WEBCONTEXT_7(name, t1, t2, t3, t4, t5, t6, t7) \
    174 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
    175 { \
    176     m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
    177 }
    178 
    179 #define DELEGATE_TO_WEBCONTEXT_7R(name, t1, t2, t3, t4, t5, t6, t7, rt) \
    180 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
    181 { \
    182     return m_impl->name(a1, a2, a3, a4, a5, a6, a7); \
    183 }
    184 
    185 #define DELEGATE_TO_WEBCONTEXT_8(name, t1, t2, t3, t4, t5, t6, t7, t8) \
    186 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
    187 { \
    188     m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8); \
    189 }
    190 
    191 #define DELEGATE_TO_WEBCONTEXT_9(name, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
    192 void GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
    193 { \
    194     m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
    195 }
    196 
    197 #define DELEGATE_TO_WEBCONTEXT_9R(name, t1, t2, t3, t4, t5, t6, t7, t8, t9, rt) \
    198 rt GraphicsContext3D::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8, t9 a9) \
    199 { \
    200     return m_impl->name(a1, a2, a3, a4, a5, a6, a7, a8, a9); \
    201 }
    202 
    203 class GraphicsContext3DContextLostCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
    204 public:
    205     GraphicsContext3DContextLostCallbackAdapter(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
    206         : m_contextLostCallback(callback) { }
    207     virtual ~GraphicsContext3DContextLostCallbackAdapter() { }
    208 
    209     virtual void onContextLost()
    210     {
    211         if (m_contextLostCallback)
    212             m_contextLostCallback->onContextLost();
    213     }
    214 private:
    215     OwnPtr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback;
    216 };
    217 
    218 class GraphicsContext3DErrorMessageCallbackAdapter : public blink::WebGraphicsContext3D::WebGraphicsErrorMessageCallback {
    219 public:
    220     GraphicsContext3DErrorMessageCallbackAdapter(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
    221         : m_errorMessageCallback(callback) { }
    222     virtual ~GraphicsContext3DErrorMessageCallbackAdapter() { }
    223 
    224     virtual void onErrorMessage(const blink::WebString& message, blink::WGC3Dint id)
    225     {
    226         if (m_errorMessageCallback)
    227             m_errorMessageCallback->onErrorMessage(message, id);
    228     }
    229 private:
    230     OwnPtr<GraphicsContext3D::ErrorMessageCallback> m_errorMessageCallback;
    231 };
    232 
    233 void GraphicsContext3D::setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback)
    234 {
    235     if (m_ownedWebContext) {
    236         m_contextLostCallbackAdapter = adoptPtr(new GraphicsContext3DContextLostCallbackAdapter(callback));
    237         m_ownedWebContext->setContextLostCallback(m_contextLostCallbackAdapter.get());
    238     }
    239 }
    240 
    241 void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<GraphicsContext3D::ErrorMessageCallback> callback)
    242 {
    243     if (m_ownedWebContext) {
    244         m_errorMessageCallbackAdapter = adoptPtr(new GraphicsContext3DErrorMessageCallbackAdapter(callback));
    245         m_ownedWebContext->setErrorMessageCallback(m_errorMessageCallbackAdapter.get());
    246     }
    247 }
    248 
    249 PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs)
    250 {
    251     blink::WebGraphicsContext3D::Attributes webAttributes;
    252     webAttributes.alpha = attrs.alpha;
    253     webAttributes.depth = attrs.depth;
    254     webAttributes.stencil = attrs.stencil;
    255     webAttributes.antialias = attrs.antialias;
    256     webAttributes.premultipliedAlpha = attrs.premultipliedAlpha;
    257     webAttributes.noExtensions = attrs.noExtensions;
    258     webAttributes.shareResources = attrs.shareResources;
    259     webAttributes.preferDiscreteGPU = attrs.preferDiscreteGPU;
    260     webAttributes.failIfMajorPerformanceCaveat = attrs.failIfMajorPerformanceCaveat;
    261     webAttributes.topDocumentURL = attrs.topDocumentURL.string();
    262 
    263     OwnPtr<blink::WebGraphicsContext3D> webContext = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(webAttributes));
    264     if (!webContext)
    265         return 0;
    266 
    267     return GraphicsContext3D::createGraphicsContextFromWebContext(webContext.release(), attrs.preserveDrawingBuffer);
    268 }
    269 
    270 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromProvider(PassOwnPtr<blink::WebGraphicsContext3DProvider> provider, bool preserveDrawingBuffer)
    271 {
    272     RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(provider, preserveDrawingBuffer));
    273     return context.release();
    274 }
    275 
    276 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createGraphicsContextFromWebContext(PassOwnPtr<blink::WebGraphicsContext3D> webContext, bool preserveDrawingBuffer)
    277 {
    278     RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(webContext, preserveDrawingBuffer));
    279     return context.release();
    280 }
    281 
    282 GrContext* GraphicsContext3D::grContext()
    283 {
    284     return m_grContext;
    285 }
    286 
    287 DELEGATE_TO_WEBCONTEXT_R(makeContextCurrent, bool)
    288 DELEGATE_TO_WEBCONTEXT_R(lastFlushID, uint32_t)
    289 
    290 DELEGATE_TO_WEBCONTEXT_1(activeTexture, GC3Denum)
    291 DELEGATE_TO_WEBCONTEXT_2(attachShader, Platform3DObject, Platform3DObject)
    292 
    293 void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
    294 {
    295     m_impl->bindAttribLocation(program, index, name.utf8().data());
    296 }
    297 
    298 DELEGATE_TO_WEBCONTEXT_2(bindBuffer, GC3Denum, Platform3DObject)
    299 DELEGATE_TO_WEBCONTEXT_2(bindFramebuffer, GC3Denum, Platform3DObject)
    300 DELEGATE_TO_WEBCONTEXT_2(bindRenderbuffer, GC3Denum, Platform3DObject)
    301 DELEGATE_TO_WEBCONTEXT_2(bindTexture, GC3Denum, Platform3DObject)
    302 DELEGATE_TO_WEBCONTEXT_4(blendColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
    303 DELEGATE_TO_WEBCONTEXT_1(blendEquation, GC3Denum)
    304 DELEGATE_TO_WEBCONTEXT_2(blendEquationSeparate, GC3Denum, GC3Denum)
    305 DELEGATE_TO_WEBCONTEXT_2(blendFunc, GC3Denum, GC3Denum)
    306 DELEGATE_TO_WEBCONTEXT_4(blendFuncSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
    307 
    308 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
    309 {
    310     bufferData(target, size, 0, usage);
    311 }
    312 
    313 DELEGATE_TO_WEBCONTEXT_4(bufferData, GC3Denum, GC3Dsizeiptr, const void*, GC3Denum)
    314 DELEGATE_TO_WEBCONTEXT_4(bufferSubData, GC3Denum, GC3Dintptr, GC3Dsizeiptr, const void*)
    315 
    316 DELEGATE_TO_WEBCONTEXT_1R(checkFramebufferStatus, GC3Denum, GC3Denum)
    317 DELEGATE_TO_WEBCONTEXT_1(clear, GC3Dbitfield)
    318 DELEGATE_TO_WEBCONTEXT_4(clearColor, GC3Dclampf, GC3Dclampf, GC3Dclampf, GC3Dclampf)
    319 DELEGATE_TO_WEBCONTEXT_1(clearDepth, GC3Dclampf)
    320 DELEGATE_TO_WEBCONTEXT_1(clearStencil, GC3Dint)
    321 DELEGATE_TO_WEBCONTEXT_4(colorMask, GC3Dboolean, GC3Dboolean, GC3Dboolean, GC3Dboolean)
    322 DELEGATE_TO_WEBCONTEXT_1(compileShader, Platform3DObject)
    323 
    324 DELEGATE_TO_WEBCONTEXT_8(compressedTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, const void*)
    325 DELEGATE_TO_WEBCONTEXT_9(compressedTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Denum, GC3Dsizei, const void*)
    326 DELEGATE_TO_WEBCONTEXT_8(copyTexImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dint)
    327 DELEGATE_TO_WEBCONTEXT_8(copyTexSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
    328 DELEGATE_TO_WEBCONTEXT_1(cullFace, GC3Denum)
    329 DELEGATE_TO_WEBCONTEXT_1(depthFunc, GC3Denum)
    330 DELEGATE_TO_WEBCONTEXT_1(depthMask, GC3Dboolean)
    331 DELEGATE_TO_WEBCONTEXT_2(depthRange, GC3Dclampf, GC3Dclampf)
    332 DELEGATE_TO_WEBCONTEXT_2(detachShader, Platform3DObject, Platform3DObject)
    333 DELEGATE_TO_WEBCONTEXT_1(disable, GC3Denum)
    334 DELEGATE_TO_WEBCONTEXT_1(disableVertexAttribArray, GC3Duint)
    335 DELEGATE_TO_WEBCONTEXT_3(drawArrays, GC3Denum, GC3Dint, GC3Dsizei)
    336 DELEGATE_TO_WEBCONTEXT_4(drawElements, GC3Denum, GC3Dsizei, GC3Denum, GC3Dintptr)
    337 
    338 DELEGATE_TO_WEBCONTEXT_1(enable, GC3Denum)
    339 DELEGATE_TO_WEBCONTEXT_1(enableVertexAttribArray, GC3Duint)
    340 DELEGATE_TO_WEBCONTEXT(finish)
    341 DELEGATE_TO_WEBCONTEXT(flush)
    342 DELEGATE_TO_WEBCONTEXT_4(framebufferRenderbuffer, GC3Denum, GC3Denum, GC3Denum, Platform3DObject)
    343 DELEGATE_TO_WEBCONTEXT_5(framebufferTexture2D, GC3Denum, GC3Denum, GC3Denum, Platform3DObject, GC3Dint)
    344 DELEGATE_TO_WEBCONTEXT_1(frontFace, GC3Denum)
    345 DELEGATE_TO_WEBCONTEXT_1(generateMipmap, GC3Denum)
    346 
    347 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
    348 {
    349     blink::WebGraphicsContext3D::ActiveInfo webInfo;
    350     if (!m_impl->getActiveAttrib(program, index, webInfo))
    351         return false;
    352     info.name = webInfo.name;
    353     info.type = webInfo.type;
    354     info.size = webInfo.size;
    355     return true;
    356 }
    357 
    358 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
    359 {
    360     blink::WebGraphicsContext3D::ActiveInfo webInfo;
    361     if (!m_impl->getActiveUniform(program, index, webInfo))
    362         return false;
    363     info.name = webInfo.name;
    364     info.type = webInfo.type;
    365     info.size = webInfo.size;
    366     return true;
    367 }
    368 
    369 DELEGATE_TO_WEBCONTEXT_4(getAttachedShaders, Platform3DObject, GC3Dsizei, GC3Dsizei*, Platform3DObject*)
    370 
    371 GC3Dint GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
    372 {
    373     return m_impl->getAttribLocation(program, name.utf8().data());
    374 }
    375 
    376 DELEGATE_TO_WEBCONTEXT_2(getBooleanv, GC3Denum, GC3Dboolean*)
    377 DELEGATE_TO_WEBCONTEXT_3(getBufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
    378 
    379 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
    380 {
    381     blink::WebGraphicsContext3D::Attributes webAttributes = m_impl->getContextAttributes();
    382     GraphicsContext3D::Attributes attributes;
    383     attributes.alpha = webAttributes.alpha;
    384     attributes.depth = webAttributes.depth;
    385     attributes.stencil = webAttributes.stencil;
    386     attributes.antialias = webAttributes.antialias;
    387     attributes.premultipliedAlpha = webAttributes.premultipliedAlpha;
    388     attributes.preserveDrawingBuffer = m_preserveDrawingBuffer;
    389     attributes.preferDiscreteGPU = webAttributes.preferDiscreteGPU;
    390     return attributes;
    391 }
    392 
    393 DELEGATE_TO_WEBCONTEXT_R(getError, GC3Denum)
    394 DELEGATE_TO_WEBCONTEXT_2(getFloatv, GC3Denum, GC3Dfloat*)
    395 DELEGATE_TO_WEBCONTEXT_4(getFramebufferAttachmentParameteriv, GC3Denum, GC3Denum, GC3Denum, GC3Dint*)
    396 DELEGATE_TO_WEBCONTEXT_2(getIntegerv, GC3Denum, GC3Dint*)
    397 DELEGATE_TO_WEBCONTEXT_3(getProgramiv, Platform3DObject, GC3Denum, GC3Dint*)
    398 DELEGATE_TO_WEBCONTEXT_1R(getProgramInfoLog, Platform3DObject, String)
    399 DELEGATE_TO_WEBCONTEXT_3(getRenderbufferParameteriv, GC3Denum, GC3Denum, GC3Dint*)
    400 DELEGATE_TO_WEBCONTEXT_3(getShaderiv, Platform3DObject, GC3Denum, GC3Dint*)
    401 DELEGATE_TO_WEBCONTEXT_1R(getShaderInfoLog, Platform3DObject, String)
    402 DELEGATE_TO_WEBCONTEXT_4(getShaderPrecisionFormat, GC3Denum, GC3Denum, GC3Dint*, GC3Dint*)
    403 DELEGATE_TO_WEBCONTEXT_1R(getShaderSource, Platform3DObject, String)
    404 DELEGATE_TO_WEBCONTEXT_1R(getString, GC3Denum, String)
    405 DELEGATE_TO_WEBCONTEXT_3(getTexParameterfv, GC3Denum, GC3Denum, GC3Dfloat*)
    406 DELEGATE_TO_WEBCONTEXT_3(getTexParameteriv, GC3Denum, GC3Denum, GC3Dint*)
    407 DELEGATE_TO_WEBCONTEXT_3(getUniformfv, Platform3DObject, GC3Dint, GC3Dfloat*)
    408 DELEGATE_TO_WEBCONTEXT_3(getUniformiv, Platform3DObject, GC3Dint, GC3Dint*)
    409 
    410 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
    411 {
    412     return m_impl->getUniformLocation(program, name.utf8().data());
    413 }
    414 
    415 DELEGATE_TO_WEBCONTEXT_3(getVertexAttribfv, GC3Duint, GC3Denum, GC3Dfloat*)
    416 DELEGATE_TO_WEBCONTEXT_3(getVertexAttribiv, GC3Duint, GC3Denum, GC3Dint*)
    417 DELEGATE_TO_WEBCONTEXT_2R(getVertexAttribOffset, GC3Duint, GC3Denum, GC3Dsizeiptr)
    418 
    419 DELEGATE_TO_WEBCONTEXT_2(hint, GC3Denum, GC3Denum)
    420 DELEGATE_TO_WEBCONTEXT_1R(isBuffer, Platform3DObject, GC3Dboolean)
    421 DELEGATE_TO_WEBCONTEXT_1R(isEnabled, GC3Denum, GC3Dboolean)
    422 DELEGATE_TO_WEBCONTEXT_1R(isFramebuffer, Platform3DObject, GC3Dboolean)
    423 DELEGATE_TO_WEBCONTEXT_1R(isProgram, Platform3DObject, GC3Dboolean)
    424 DELEGATE_TO_WEBCONTEXT_1R(isRenderbuffer, Platform3DObject, GC3Dboolean)
    425 DELEGATE_TO_WEBCONTEXT_1R(isShader, Platform3DObject, GC3Dboolean)
    426 DELEGATE_TO_WEBCONTEXT_1R(isTexture, Platform3DObject, GC3Dboolean)
    427 DELEGATE_TO_WEBCONTEXT_1(lineWidth, GC3Dfloat)
    428 DELEGATE_TO_WEBCONTEXT_1(linkProgram, Platform3DObject)
    429 
    430 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
    431 {
    432     if (pname == GL_PACK_ALIGNMENT)
    433         m_packAlignment = param;
    434     m_impl->pixelStorei(pname, param);
    435 }
    436 
    437 DELEGATE_TO_WEBCONTEXT_2(polygonOffset, GC3Dfloat, GC3Dfloat)
    438 
    439 DELEGATE_TO_WEBCONTEXT_7(readPixels, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, void*)
    440 
    441 DELEGATE_TO_WEBCONTEXT(releaseShaderCompiler)
    442 DELEGATE_TO_WEBCONTEXT_4(renderbufferStorage, GC3Denum, GC3Denum, GC3Dsizei, GC3Dsizei)
    443 DELEGATE_TO_WEBCONTEXT_2(sampleCoverage, GC3Dclampf, GC3Dboolean)
    444 DELEGATE_TO_WEBCONTEXT_4(scissor, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
    445 
    446 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
    447 {
    448     m_impl->shaderSource(shader, string.utf8().data());
    449 }
    450 
    451 DELEGATE_TO_WEBCONTEXT_3(stencilFunc, GC3Denum, GC3Dint, GC3Duint)
    452 DELEGATE_TO_WEBCONTEXT_4(stencilFuncSeparate, GC3Denum, GC3Denum, GC3Dint, GC3Duint)
    453 DELEGATE_TO_WEBCONTEXT_1(stencilMask, GC3Duint)
    454 DELEGATE_TO_WEBCONTEXT_2(stencilMaskSeparate, GC3Denum, GC3Duint)
    455 DELEGATE_TO_WEBCONTEXT_3(stencilOp, GC3Denum, GC3Denum, GC3Denum)
    456 DELEGATE_TO_WEBCONTEXT_4(stencilOpSeparate, GC3Denum, GC3Denum, GC3Denum, GC3Denum)
    457 
    458 DELEGATE_TO_WEBCONTEXT_9(texImage2D, GC3Denum, GC3Dint, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Denum, GC3Denum, const void*)
    459 DELEGATE_TO_WEBCONTEXT_3(texParameterf, GC3Denum, GC3Denum, GC3Dfloat)
    460 DELEGATE_TO_WEBCONTEXT_3(texParameteri, GC3Denum, GC3Denum, GC3Dint)
    461 DELEGATE_TO_WEBCONTEXT_9(texSubImage2D, GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, const void*)
    462 
    463 DELEGATE_TO_WEBCONTEXT_2(uniform1f, GC3Dint, GC3Dfloat)
    464 DELEGATE_TO_WEBCONTEXT_3(uniform1fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
    465 DELEGATE_TO_WEBCONTEXT_2(uniform1i, GC3Dint, GC3Dint)
    466 DELEGATE_TO_WEBCONTEXT_3(uniform1iv, GC3Dint, GC3Dsizei, GC3Dint*)
    467 DELEGATE_TO_WEBCONTEXT_3(uniform2f, GC3Dint, GC3Dfloat, GC3Dfloat)
    468 DELEGATE_TO_WEBCONTEXT_3(uniform2fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
    469 DELEGATE_TO_WEBCONTEXT_3(uniform2i, GC3Dint, GC3Dint, GC3Dint)
    470 DELEGATE_TO_WEBCONTEXT_3(uniform2iv, GC3Dint, GC3Dsizei, GC3Dint*)
    471 DELEGATE_TO_WEBCONTEXT_4(uniform3f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
    472 DELEGATE_TO_WEBCONTEXT_3(uniform3fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
    473 DELEGATE_TO_WEBCONTEXT_4(uniform3i, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
    474 DELEGATE_TO_WEBCONTEXT_3(uniform3iv, GC3Dint, GC3Dsizei, GC3Dint*)
    475 DELEGATE_TO_WEBCONTEXT_5(uniform4f, GC3Dint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
    476 DELEGATE_TO_WEBCONTEXT_3(uniform4fv, GC3Dint, GC3Dsizei, GC3Dfloat*)
    477 DELEGATE_TO_WEBCONTEXT_5(uniform4i, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
    478 DELEGATE_TO_WEBCONTEXT_3(uniform4iv, GC3Dint, GC3Dsizei, GC3Dint*)
    479 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix2fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
    480 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix3fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
    481 DELEGATE_TO_WEBCONTEXT_4(uniformMatrix4fv, GC3Dint, GC3Dsizei, GC3Dboolean, GC3Dfloat*)
    482 
    483 DELEGATE_TO_WEBCONTEXT_1(useProgram, Platform3DObject)
    484 DELEGATE_TO_WEBCONTEXT_1(validateProgram, Platform3DObject)
    485 
    486 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1f, GC3Duint, GC3Dfloat)
    487 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib1fv, GC3Duint, GC3Dfloat*)
    488 DELEGATE_TO_WEBCONTEXT_3(vertexAttrib2f, GC3Duint, GC3Dfloat, GC3Dfloat)
    489 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib2fv, GC3Duint, GC3Dfloat*)
    490 DELEGATE_TO_WEBCONTEXT_4(vertexAttrib3f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat)
    491 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib3fv, GC3Duint, GC3Dfloat*)
    492 DELEGATE_TO_WEBCONTEXT_5(vertexAttrib4f, GC3Duint, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat)
    493 DELEGATE_TO_WEBCONTEXT_2(vertexAttrib4fv, GC3Duint, GC3Dfloat*)
    494 DELEGATE_TO_WEBCONTEXT_6(vertexAttribPointer, GC3Duint, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr)
    495 
    496 DELEGATE_TO_WEBCONTEXT_4(viewport, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
    497 
    498 void GraphicsContext3D::markContextChanged()
    499 {
    500     m_layerComposited = false;
    501 }
    502 
    503 bool GraphicsContext3D::layerComposited() const
    504 {
    505     return m_layerComposited;
    506 }
    507 
    508 void GraphicsContext3D::markLayerComposited()
    509 {
    510     m_layerComposited = true;
    511 }
    512 
    513 void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer* drawingBuffer)
    514 {
    515     Platform3DObject framebufferId;
    516     int width, height;
    517     getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
    518     paintFramebufferToCanvas(framebufferId, width, height, !getContextAttributes().premultipliedAlpha, imageBuffer);
    519 }
    520 
    521 PassRefPtr<Uint8ClampedArray> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer, int& width, int& height)
    522 {
    523     if (getContextAttributes().premultipliedAlpha)
    524         return 0;
    525 
    526     Platform3DObject framebufferId;
    527     getDrawingParameters(drawingBuffer, m_impl, &framebufferId, &width, &height);
    528 
    529     Checked<int, RecordOverflow> dataSize = 4;
    530     dataSize *= width;
    531     dataSize *= height;
    532     if (dataSize.hasOverflowed())
    533         return 0;
    534 
    535     RefPtr<Uint8ClampedArray> pixels = Uint8ClampedArray::createUninitialized(width * height * 4);
    536 
    537     m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebufferId);
    538     readBackFramebuffer(pixels->data(), width, height, ReadbackRGBA, AlphaDoNothing);
    539     flipVertically(pixels->data(), width, height);
    540 
    541     return pixels.release();
    542 }
    543 
    544 void GraphicsContext3D::readBackFramebuffer(unsigned char* pixels, int width, int height, ReadbackOrder readbackOrder, AlphaOp op)
    545 {
    546     if (m_packAlignment > 4)
    547         m_impl->pixelStorei(GL_PACK_ALIGNMENT, 1);
    548     m_impl->readPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    549     if (m_packAlignment > 4)
    550         m_impl->pixelStorei(GL_PACK_ALIGNMENT, m_packAlignment);
    551 
    552     size_t bufferSize = 4 * width * height;
    553 
    554     if (readbackOrder == ReadbackSkia) {
    555 #if (SK_R32_SHIFT == 16) && !SK_B32_SHIFT
    556         // Swizzle red and blue channels to match SkBitmap's byte ordering.
    557         // TODO(kbr): expose GL_BGRA as extension.
    558         for (size_t i = 0; i < bufferSize; i += 4) {
    559             std::swap(pixels[i], pixels[i + 2]);
    560         }
    561 #endif
    562     }
    563 
    564     if (op == AlphaDoPremultiply) {
    565         for (size_t i = 0; i < bufferSize; i += 4) {
    566             pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
    567             pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
    568             pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
    569         }
    570     } else if (op != AlphaDoNothing) {
    571         ASSERT_NOT_REACHED();
    572     }
    573 }
    574 
    575 DELEGATE_TO_WEBCONTEXT_R(createBuffer, Platform3DObject)
    576 DELEGATE_TO_WEBCONTEXT_R(createFramebuffer, Platform3DObject)
    577 DELEGATE_TO_WEBCONTEXT_R(createProgram, Platform3DObject)
    578 DELEGATE_TO_WEBCONTEXT_R(createRenderbuffer, Platform3DObject)
    579 DELEGATE_TO_WEBCONTEXT_1R(createShader, GC3Denum, Platform3DObject)
    580 DELEGATE_TO_WEBCONTEXT_R(createTexture, Platform3DObject)
    581 
    582 DELEGATE_TO_WEBCONTEXT_1(deleteBuffer, Platform3DObject)
    583 DELEGATE_TO_WEBCONTEXT_1(deleteFramebuffer, Platform3DObject)
    584 DELEGATE_TO_WEBCONTEXT_1(deleteProgram, Platform3DObject)
    585 DELEGATE_TO_WEBCONTEXT_1(deleteRenderbuffer, Platform3DObject)
    586 DELEGATE_TO_WEBCONTEXT_1(deleteShader, Platform3DObject)
    587 DELEGATE_TO_WEBCONTEXT_1(deleteTexture, Platform3DObject)
    588 
    589 DELEGATE_TO_WEBCONTEXT_1(synthesizeGLError, GC3Denum)
    590 
    591 Extensions3D* GraphicsContext3D::extensions()
    592 {
    593     if (!m_extensions)
    594         m_extensions = adoptPtr(new Extensions3D(this));
    595     return m_extensions.get();
    596 }
    597 
    598 bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment)
    599 {
    600     ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8);
    601     texImage2D(target, level, internalformat, width, height, border, format, type, 0);
    602     return true;
    603 }
    604 
    605 bool GraphicsContext3D::computeFormatAndTypeParameters(GC3Denum format,
    606                                                        GC3Denum type,
    607                                                        unsigned int* componentsPerPixel,
    608                                                        unsigned int* bytesPerComponent)
    609 {
    610     switch (format) {
    611     case GL_ALPHA:
    612     case GL_LUMINANCE:
    613     case GL_DEPTH_COMPONENT:
    614     case GL_DEPTH_STENCIL_OES:
    615         *componentsPerPixel = 1;
    616         break;
    617     case GL_LUMINANCE_ALPHA:
    618         *componentsPerPixel = 2;
    619         break;
    620     case GL_RGB:
    621         *componentsPerPixel = 3;
    622         break;
    623     case GL_RGBA:
    624     case Extensions3D::BGRA_EXT: // GL_EXT_texture_format_BGRA8888
    625         *componentsPerPixel = 4;
    626         break;
    627     default:
    628         return false;
    629     }
    630     switch (type) {
    631     case GL_UNSIGNED_BYTE:
    632         *bytesPerComponent = sizeof(GC3Dubyte);
    633         break;
    634     case GL_UNSIGNED_SHORT:
    635         *bytesPerComponent = sizeof(GC3Dushort);
    636         break;
    637     case GL_UNSIGNED_SHORT_5_6_5:
    638     case GL_UNSIGNED_SHORT_4_4_4_4:
    639     case GL_UNSIGNED_SHORT_5_5_5_1:
    640         *componentsPerPixel = 1;
    641         *bytesPerComponent = sizeof(GC3Dushort);
    642         break;
    643     case GL_UNSIGNED_INT_24_8_OES:
    644     case GL_UNSIGNED_INT:
    645         *bytesPerComponent = sizeof(GC3Duint);
    646         break;
    647     case GL_FLOAT: // OES_texture_float
    648         *bytesPerComponent = sizeof(GC3Dfloat);
    649         break;
    650     case GL_HALF_FLOAT_OES: // OES_texture_half_float
    651         *bytesPerComponent = sizeof(GC3Dhalffloat);
    652         break;
    653     default:
    654         return false;
    655     }
    656     return true;
    657 }
    658 
    659 GC3Denum GraphicsContext3D::computeImageSizeInBytes(GC3Denum format, GC3Denum type, GC3Dsizei width, GC3Dsizei height, GC3Dint alignment,
    660                                                     unsigned int* imageSizeInBytes, unsigned int* paddingInBytes)
    661 {
    662     ASSERT(imageSizeInBytes);
    663     ASSERT(alignment == 1 || alignment == 2 || alignment == 4 || alignment == 8);
    664     if (width < 0 || height < 0)
    665         return GL_INVALID_VALUE;
    666     unsigned int bytesPerComponent, componentsPerPixel;
    667     if (!computeFormatAndTypeParameters(format, type, &bytesPerComponent, &componentsPerPixel))
    668         return GL_INVALID_ENUM;
    669     if (!width || !height) {
    670         *imageSizeInBytes = 0;
    671         if (paddingInBytes)
    672             *paddingInBytes = 0;
    673         return GL_NO_ERROR;
    674     }
    675     CheckedInt<uint32_t> checkedValue(bytesPerComponent * componentsPerPixel);
    676     checkedValue *=  width;
    677     if (!checkedValue.isValid())
    678         return GL_INVALID_VALUE;
    679     unsigned int validRowSize = checkedValue.value();
    680     unsigned int padding = 0;
    681     unsigned int residual = validRowSize % alignment;
    682     if (residual) {
    683         padding = alignment - residual;
    684         checkedValue += padding;
    685     }
    686     // Last row needs no padding.
    687     checkedValue *= (height - 1);
    688     checkedValue += validRowSize;
    689     if (!checkedValue.isValid())
    690         return GL_INVALID_VALUE;
    691     *imageSizeInBytes = checkedValue.value();
    692     if (paddingInBytes)
    693         *paddingInBytes = padding;
    694     return GL_NO_ERROR;
    695 }
    696 
    697 GraphicsContext3D::ImageExtractor::ImageExtractor(Image* image, ImageHtmlDomSource imageHtmlDomSource, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
    698 {
    699     m_image = image;
    700     m_imageHtmlDomSource = imageHtmlDomSource;
    701     m_extractSucceeded = extractImage(premultiplyAlpha, ignoreGammaAndColorProfile);
    702 }
    703 
    704 GraphicsContext3D::ImageExtractor::~ImageExtractor()
    705 {
    706     if (m_skiaImage)
    707         m_skiaImage->bitmap().unlockPixels();
    708 }
    709 
    710 bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
    711 {
    712     if (!m_image)
    713         return false;
    714     m_skiaImage = m_image->nativeImageForCurrentFrame();
    715     m_alphaOp = AlphaDoNothing;
    716     bool hasAlpha = m_skiaImage ? !m_skiaImage->bitmap().isOpaque() : true;
    717     if ((!m_skiaImage || ignoreGammaAndColorProfile || (hasAlpha && !premultiplyAlpha)) && m_image->data()) {
    718         // Attempt to get raw unpremultiplied image data.
    719         OwnPtr<ImageDecoder> decoder(ImageDecoder::create(
    720             *(m_image->data()), ImageSource::AlphaNotPremultiplied,
    721             ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
    722         if (!decoder)
    723             return false;
    724         decoder->setData(m_image->data(), true);
    725         if (!decoder->frameCount())
    726             return false;
    727         ImageFrame* frame = decoder->frameBufferAtIndex(0);
    728         if (!frame || frame->status() != ImageFrame::FrameComplete)
    729             return false;
    730         hasAlpha = frame->hasAlpha();
    731         m_nativeImage = frame->asNewNativeImage();
    732         if (!m_nativeImage.get() || !m_nativeImage->isDataComplete() || !m_nativeImage->bitmap().width() || !m_nativeImage->bitmap().height())
    733             return false;
    734         SkBitmap::Config skiaConfig = m_nativeImage->bitmap().config();
    735         if (skiaConfig != SkBitmap::kARGB_8888_Config)
    736             return false;
    737         m_skiaImage = m_nativeImage.get();
    738         if (hasAlpha && premultiplyAlpha)
    739             m_alphaOp = AlphaDoPremultiply;
    740     } else if (!premultiplyAlpha && hasAlpha) {
    741         // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value for each pixel is 0xFF
    742         // which is true at present and may be changed in the future and needs adjustment accordingly.
    743         // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port,
    744         // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false.
    745         if (m_imageHtmlDomSource != HtmlDomVideo)
    746             m_alphaOp = AlphaDoUnmultiply;
    747     }
    748     if (!m_skiaImage)
    749         return false;
    750 
    751     m_imageSourceFormat = SK_B32_SHIFT ? DataFormatRGBA8 : DataFormatBGRA8;
    752     m_imageWidth = m_skiaImage->bitmap().width();
    753     m_imageHeight = m_skiaImage->bitmap().height();
    754     if (!m_imageWidth || !m_imageHeight)
    755         return false;
    756     m_imageSourceUnpackAlignment = 0;
    757     m_skiaImage->bitmap().lockPixels();
    758     m_imagePixelData = m_skiaImage->bitmap().getPixels();
    759     return true;
    760 }
    761 
    762 unsigned GraphicsContext3D::getClearBitsByFormat(GC3Denum format)
    763 {
    764     switch (format) {
    765     case GL_ALPHA:
    766     case GL_LUMINANCE:
    767     case GL_LUMINANCE_ALPHA:
    768     case GL_RGB:
    769     case GL_RGB565:
    770     case GL_RGBA:
    771     case GL_RGBA4:
    772     case GL_RGB5_A1:
    773         return GL_COLOR_BUFFER_BIT;
    774     case GL_DEPTH_COMPONENT16:
    775     case GL_DEPTH_COMPONENT:
    776         return GL_DEPTH_BUFFER_BIT;
    777     case GL_STENCIL_INDEX8:
    778         return GL_STENCIL_BUFFER_BIT;
    779     case GL_DEPTH_STENCIL_OES:
    780         return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
    781     default:
    782         return 0;
    783     }
    784 }
    785 
    786 unsigned GraphicsContext3D::getChannelBitsByFormat(GC3Denum format)
    787 {
    788     switch (format) {
    789     case GL_ALPHA:
    790         return ChannelAlpha;
    791     case GL_LUMINANCE:
    792         return ChannelRGB;
    793     case GL_LUMINANCE_ALPHA:
    794         return ChannelRGBA;
    795     case GL_RGB:
    796     case GL_RGB565:
    797         return ChannelRGB;
    798     case GL_RGBA:
    799     case GL_RGBA4:
    800     case GL_RGB5_A1:
    801         return ChannelRGBA;
    802     case GL_DEPTH_COMPONENT16:
    803     case GL_DEPTH_COMPONENT:
    804         return ChannelDepth;
    805     case GL_STENCIL_INDEX8:
    806         return ChannelStencil;
    807     case GL_DEPTH_STENCIL_OES:
    808         return ChannelDepth | ChannelStencil;
    809     default:
    810         return 0;
    811     }
    812 }
    813 
    814 void GraphicsContext3D::paintFramebufferToCanvas(int framebuffer, int width, int height, bool premultiplyAlpha, ImageBuffer* imageBuffer)
    815 {
    816     unsigned char* pixels = 0;
    817 
    818     const SkBitmap& canvasBitmap = imageBuffer->bitmap();
    819     const SkBitmap* readbackBitmap = 0;
    820     ASSERT(canvasBitmap.config() == SkBitmap::kARGB_8888_Config);
    821     if (canvasBitmap.width() == width && canvasBitmap.height() == height) {
    822         // This is the fastest and most common case. We read back
    823         // directly into the canvas's backing store.
    824         readbackBitmap = &canvasBitmap;
    825         m_resizingBitmap.reset();
    826     } else {
    827         // We need to allocate a temporary bitmap for reading back the
    828         // pixel data. We will then use Skia to rescale this bitmap to
    829         // the size of the canvas's backing store.
    830         if (m_resizingBitmap.width() != width || m_resizingBitmap.height() != height) {
    831             m_resizingBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    832             if (!m_resizingBitmap.allocPixels())
    833                 return;
    834         }
    835         readbackBitmap = &m_resizingBitmap;
    836     }
    837 
    838     // Read back the frame buffer.
    839     SkAutoLockPixels bitmapLock(*readbackBitmap);
    840     pixels = static_cast<unsigned char*>(readbackBitmap->getPixels());
    841 
    842     m_impl->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    843     readBackFramebuffer(pixels, width, height, ReadbackSkia, premultiplyAlpha ? AlphaDoPremultiply : AlphaDoNothing);
    844     flipVertically(pixels, width, height);
    845 
    846     readbackBitmap->notifyPixelsChanged();
    847     if (m_resizingBitmap.readyToDraw()) {
    848         // We need to draw the resizing bitmap into the canvas's backing store.
    849         SkCanvas canvas(canvasBitmap);
    850         SkRect dst;
    851         dst.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(canvasBitmap.width()), SkIntToScalar(canvasBitmap.height()));
    852         canvas.drawBitmapRect(m_resizingBitmap, 0, dst);
    853     }
    854 }
    855 
    856 namespace {
    857 
    858 void splitStringHelper(const String& str, HashSet<String>& set)
    859 {
    860     Vector<String> substrings;
    861     str.split(" ", substrings);
    862     for (size_t i = 0; i < substrings.size(); ++i)
    863         set.add(substrings[i]);
    864 }
    865 
    866 String mapExtensionName(const String& name)
    867 {
    868     if (name == "GL_ANGLE_framebuffer_blit"
    869         || name == "GL_ANGLE_framebuffer_multisample")
    870         return "GL_CHROMIUM_framebuffer_multisample";
    871     return name;
    872 }
    873 
    874 } // anonymous namespace
    875 
    876 void GraphicsContext3D::initializeExtensions()
    877 {
    878     if (m_initializedAvailableExtensions)
    879         return;
    880 
    881     m_initializedAvailableExtensions = true;
    882     bool success = m_impl->makeContextCurrent();
    883     ASSERT(success);
    884     if (!success)
    885         return;
    886 
    887     String extensionsString = m_impl->getString(GL_EXTENSIONS);
    888     splitStringHelper(extensionsString, m_enabledExtensions);
    889 
    890     String requestableExtensionsString = m_impl->getRequestableExtensionsCHROMIUM();
    891     splitStringHelper(requestableExtensionsString, m_requestableExtensions);
    892 }
    893 
    894 
    895 bool GraphicsContext3D::supportsExtension(const String& name)
    896 {
    897     initializeExtensions();
    898     String mappedName = mapExtensionName(name);
    899     return m_enabledExtensions.contains(mappedName) || m_requestableExtensions.contains(mappedName);
    900 }
    901 
    902 bool GraphicsContext3D::ensureExtensionEnabled(const String& name)
    903 {
    904     initializeExtensions();
    905 
    906     String mappedName = mapExtensionName(name);
    907     if (m_enabledExtensions.contains(mappedName))
    908         return true;
    909 
    910     if (m_requestableExtensions.contains(mappedName)) {
    911         m_impl->requestExtensionCHROMIUM(mappedName.ascii().data());
    912         m_enabledExtensions.clear();
    913         m_requestableExtensions.clear();
    914         m_initializedAvailableExtensions = false;
    915     }
    916 
    917     initializeExtensions();
    918     fprintf(stderr, "m_enabledExtensions.contains(%s) == %d\n", mappedName.ascii().data(), m_enabledExtensions.contains(mappedName));
    919     return m_enabledExtensions.contains(mappedName);
    920 }
    921 
    922 bool GraphicsContext3D::isExtensionEnabled(const String& name)
    923 {
    924     initializeExtensions();
    925     String mappedName = mapExtensionName(name);
    926     return m_enabledExtensions.contains(mappedName);
    927 }
    928 
    929 void GraphicsContext3D::flipVertically(uint8_t* framebuffer, int width, int height)
    930 {
    931     m_scanline.resize(width * 4);
    932     uint8* scanline = &m_scanline[0];
    933     unsigned rowBytes = width * 4;
    934     unsigned count = height / 2;
    935     for (unsigned i = 0; i < count; i++) {
    936         uint8* rowA = framebuffer + i * rowBytes;
    937         uint8* rowB = framebuffer + (height - i - 1) * rowBytes;
    938         memcpy(scanline, rowB, rowBytes);
    939         memcpy(rowB, rowA, rowBytes);
    940         memcpy(rowA, scanline, rowBytes);
    941     }
    942 }
    943 
    944 } // namespace WebCore
    945