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