Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright (c) 2010, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #if ENABLE(ACCELERATED_2D_CANVAS)
     34 
     35 #include "SharedGraphicsContext3D.h"
     36 
     37 #include "AffineTransform.h"
     38 #include "BicubicShader.h"
     39 #include "Color.h"
     40 #include "ConvolutionShader.h"
     41 #include "DrawingBuffer.h"
     42 #include "Extensions3D.h"
     43 #include "FloatRect.h"
     44 #include "IntSize.h"
     45 #include "LoopBlinnSolidFillShader.h"
     46 #include "SolidFillShader.h"
     47 #include "TexShader.h"
     48 
     49 #if ENABLE(SKIA_GPU)
     50 #include "GrContext.h"
     51 // Limit the number of textures we hold in the bitmap->texture cache.
     52 static const int maxTextureCacheCount = 512;
     53 // Limit the bytes allocated toward textures in the bitmap->texture cache.
     54 static const size_t maxTextureCacheBytes = 50 * 1024 * 1024;
     55 #endif
     56 
     57 #include <wtf/OwnArrayPtr.h>
     58 #include <wtf/text/CString.h>
     59 #include <wtf/text/WTFString.h>
     60 
     61 namespace WebCore {
     62 
     63 // static
     64 PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow* hostWindow)
     65 {
     66     GraphicsContext3D::Attributes attr;
     67     attr.depth = false;
     68     attr.stencil = true;
     69     attr.antialias = useLoopBlinnForPathRendering();
     70     attr.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts.
     71     RefPtr<GraphicsContext3D> context = GraphicsContext3D::create(attr, hostWindow);
     72     if (!context)
     73         return 0;
     74     OwnPtr<SolidFillShader> solidFillShader = SolidFillShader::create(context.get());
     75     if (!solidFillShader)
     76         return 0;
     77     OwnPtr<TexShader> texShader = TexShader::create(context.get());
     78     if (!texShader)
     79         return 0;
     80     OwnPtr<BicubicShader> bicubicShader = BicubicShader::create(context.get());
     81     if (!bicubicShader)
     82         return 0;
     83     OwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders = adoptArrayPtr(new OwnPtr<ConvolutionShader>[cMaxKernelWidth]);
     84     for (int i = 0; i < cMaxKernelWidth; ++i) {
     85         convolutionShaders[i] = ConvolutionShader::create(context.get(), i + 1);
     86         if (!convolutionShaders[i])
     87             return 0;
     88     }
     89     return adoptRef(new SharedGraphicsContext3D(context.release(), solidFillShader.release(), texShader.release(), bicubicShader.release(), convolutionShaders.release()));
     90 }
     91 
     92 SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader, PassOwnPtr<BicubicShader> bicubicShader, PassOwnArrayPtr<OwnPtr<ConvolutionShader> > convolutionShaders)
     93     : m_context(context)
     94     , m_bgraSupported(false)
     95     , m_quadVertices(0)
     96     , m_solidFillShader(solidFillShader)
     97     , m_texShader(texShader)
     98     , m_bicubicShader(bicubicShader)
     99     , m_convolutionShaders(convolutionShaders)
    100     , m_oesStandardDerivativesSupported(false)
    101 #if ENABLE(SKIA_GPU)
    102     , m_grContext(0)
    103 #endif
    104 {
    105     allContexts()->add(this);
    106     Extensions3D* extensions = m_context->getExtensions();
    107     m_bgraSupported = extensions->supports("GL_EXT_texture_format_BGRA8888") && extensions->supports("GL_EXT_read_format_bgra");
    108     if (m_bgraSupported) {
    109         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
    110         extensions->ensureEnabled("GL_EXT_read_format_bgra");
    111     }
    112     m_oesStandardDerivativesSupported = extensions->supports("GL_OES_standard_derivatives");
    113     if (m_oesStandardDerivativesSupported)
    114         extensions->ensureEnabled("GL_OES_standard_derivatives");
    115 }
    116 
    117 SharedGraphicsContext3D::~SharedGraphicsContext3D()
    118 {
    119     m_context->deleteBuffer(m_quadVertices);
    120     allContexts()->remove(this);
    121 #if ENABLE(SKIA_GPU)
    122     GrSafeUnref(m_grContext);
    123 #endif
    124 }
    125 
    126 void SharedGraphicsContext3D::makeContextCurrent()
    127 {
    128     m_context->makeContextCurrent();
    129 }
    130 
    131 void SharedGraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
    132 {
    133     m_context->scissor(x, y, width, height);
    134 }
    135 
    136 void SharedGraphicsContext3D::enable(GC3Denum capacity)
    137 {
    138     m_context->enable(capacity);
    139 }
    140 
    141 void SharedGraphicsContext3D::disable(GC3Denum capacity)
    142 {
    143     m_context->disable(capacity);
    144 }
    145 
    146 void SharedGraphicsContext3D::clearColor(const Color& color)
    147 {
    148     float rgba[4];
    149     color.getRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
    150     m_context->clearColor(rgba[0], rgba[1], rgba[2], rgba[3]);
    151 }
    152 
    153 void SharedGraphicsContext3D::clear(GC3Dbitfield mask)
    154 {
    155     m_context->clear(mask);
    156 }
    157 
    158 void SharedGraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
    159 {
    160     m_context->drawArrays(mode, first, count);
    161 }
    162 
    163 GC3Denum SharedGraphicsContext3D::getError()
    164 {
    165     return m_context->getError();
    166 }
    167 
    168 void SharedGraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
    169 {
    170     m_context->getIntegerv(pname, value);
    171 }
    172 
    173 void SharedGraphicsContext3D::flush()
    174 {
    175     m_context->flush();
    176 }
    177 
    178 Platform3DObject SharedGraphicsContext3D::createBuffer()
    179 {
    180     return m_context->createBuffer();
    181 }
    182 
    183 Platform3DObject SharedGraphicsContext3D::createFramebuffer()
    184 {
    185     return m_context->createFramebuffer();
    186 }
    187 
    188 Platform3DObject SharedGraphicsContext3D::createTexture()
    189 {
    190     return m_context->createTexture();
    191 }
    192 
    193 void SharedGraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
    194 {
    195     m_context->deleteFramebuffer(framebuffer);
    196 }
    197 
    198 void SharedGraphicsContext3D::deleteTexture(Platform3DObject texture)
    199 {
    200     m_context->deleteTexture(texture);
    201 }
    202 
    203 void SharedGraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
    204 {
    205     m_context->framebufferTexture2D(target, attachment, textarget, texture, level);
    206 }
    207 
    208 void SharedGraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
    209 {
    210     m_context->texParameteri(target, pname, param);
    211 }
    212 
    213 bool SharedGraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
    214 {
    215     if (!pixels)
    216         return m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border, format, type);
    217     return m_context->texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
    218 }
    219 
    220 void SharedGraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
    221 {
    222     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
    223 }
    224 
    225 void SharedGraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
    226 {
    227     m_context->readPixels(x, y, width, height, format, type, data);
    228 }
    229 
    230 bool SharedGraphicsContext3D::supportsBGRA()
    231 {
    232     return m_bgraSupported;
    233 }
    234 
    235 Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
    236 {
    237     RefPtr<Texture> texture = m_textures.get(ptr);
    238     if (texture)
    239         return texture.get();
    240 
    241     texture = Texture::create(m_context.get(), format, width, height);
    242     Texture* t = texture.get();
    243     m_textures.set(ptr, texture);
    244     return t;
    245 }
    246 
    247 Texture* SharedGraphicsContext3D::getTexture(NativeImagePtr ptr)
    248 {
    249     RefPtr<Texture> texture = m_textures.get(ptr);
    250     return texture ? texture.get() : 0;
    251 }
    252 
    253 void SharedGraphicsContext3D::removeTextureFor(NativeImagePtr ptr)
    254 {
    255     TextureHashMap::iterator it = m_textures.find(ptr);
    256     if (it != m_textures.end())
    257         m_textures.remove(it);
    258 }
    259 
    260 // static
    261 void SharedGraphicsContext3D::removeTexturesFor(NativeImagePtr ptr)
    262 {
    263     for (HashSet<SharedGraphicsContext3D*>::iterator it = allContexts()->begin(); it != allContexts()->end(); ++it)
    264         (*it)->removeTextureFor(ptr);
    265 }
    266 
    267 // static
    268 HashSet<SharedGraphicsContext3D*>* SharedGraphicsContext3D::allContexts()
    269 {
    270     DEFINE_STATIC_LOCAL(HashSet<SharedGraphicsContext3D*>, allContextsSet, ());
    271     return &allContextsSet;
    272 }
    273 
    274 
    275 PassRefPtr<Texture> SharedGraphicsContext3D::createTexture(Texture::Format format, int width, int height)
    276 {
    277     return Texture::create(m_context.get(), format, width, height);
    278 }
    279 
    280 void SharedGraphicsContext3D::applyCompositeOperator(CompositeOperator op)
    281 {
    282     switch (op) {
    283     case CompositeClear:
    284         m_context->enable(GraphicsContext3D::BLEND);
    285         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ZERO);
    286         break;
    287     case CompositeCopy:
    288         m_context->disable(GraphicsContext3D::BLEND);
    289         break;
    290     case CompositeSourceOver:
    291         m_context->enable(GraphicsContext3D::BLEND);
    292         m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
    293         break;
    294     case CompositeSourceIn:
    295         m_context->enable(GraphicsContext3D::BLEND);
    296         m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ZERO);
    297         break;
    298     case CompositeSourceOut:
    299         m_context->enable(GraphicsContext3D::BLEND);
    300         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ZERO);
    301         break;
    302     case CompositeSourceAtop:
    303         m_context->enable(GraphicsContext3D::BLEND);
    304         m_context->blendFunc(GraphicsContext3D::DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
    305         break;
    306     case CompositeDestinationOver:
    307         m_context->enable(GraphicsContext3D::BLEND);
    308         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE);
    309         break;
    310     case CompositeDestinationIn:
    311         m_context->enable(GraphicsContext3D::BLEND);
    312         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::SRC_ALPHA);
    313         break;
    314     case CompositeDestinationOut:
    315         m_context->enable(GraphicsContext3D::BLEND);
    316         m_context->blendFunc(GraphicsContext3D::ZERO, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
    317         break;
    318     case CompositeDestinationAtop:
    319         m_context->enable(GraphicsContext3D::BLEND);
    320         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::SRC_ALPHA);
    321         break;
    322     case CompositeXOR:
    323         m_context->enable(GraphicsContext3D::BLEND);
    324         m_context->blendFunc(GraphicsContext3D::ONE_MINUS_DST_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA);
    325         break;
    326     case CompositePlusDarker:
    327     case CompositeHighlight:
    328         // unsupported
    329         m_context->disable(GraphicsContext3D::BLEND);
    330         break;
    331     case CompositePlusLighter:
    332         m_context->enable(GraphicsContext3D::BLEND);
    333         m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE);
    334         break;
    335     }
    336 }
    337 
    338 void SharedGraphicsContext3D::enableStencil(bool enable)
    339 {
    340     if (enable)
    341         m_context->enable(GraphicsContext3D::STENCIL_TEST);
    342     else
    343         m_context->disable(GraphicsContext3D::STENCIL_TEST);
    344 }
    345 
    346 void SharedGraphicsContext3D::useQuadVertices()
    347 {
    348     if (!m_quadVertices) {
    349         float vertices[] = { 0.0f, 0.0f,
    350                              1.0f, 0.0f,
    351                              0.0f, 1.0f,
    352                              1.0f, 1.0f };
    353         m_quadVertices = m_context->createBuffer();
    354         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
    355         m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, sizeof(vertices), vertices, GraphicsContext3D::STATIC_DRAW);
    356     } else {
    357         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_quadVertices);
    358     }
    359 }
    360 
    361 void SharedGraphicsContext3D::setActiveTexture(GC3Denum textureUnit)
    362 {
    363     m_context->activeTexture(textureUnit);
    364 }
    365 
    366 void SharedGraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
    367 {
    368     m_context->bindBuffer(target, buffer);
    369 }
    370 
    371 void SharedGraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
    372 {
    373     m_context->bindTexture(target, texture);
    374 }
    375 
    376 void SharedGraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
    377 {
    378     m_context->bufferData(target, size, usage);
    379 }
    380 
    381 void SharedGraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
    382 {
    383     m_context->bufferData(target, size, data, usage);
    384 }
    385 
    386 void SharedGraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
    387 {
    388     m_context->bufferSubData(target, offset, size, data);
    389 }
    390 
    391 void SharedGraphicsContext3D::useFillSolidProgram(const AffineTransform& transform, const Color& color)
    392 {
    393     m_solidFillShader->use(transform, color);
    394 }
    395 
    396 void SharedGraphicsContext3D::useTextureProgram(const AffineTransform& transform, const AffineTransform& texTransform, float alpha)
    397 {
    398     m_texShader->use(transform, texTransform, 0, alpha);
    399 }
    400 
    401 void SharedGraphicsContext3D::useBicubicProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float coefficients[16], const float imageIncrement[2], float alpha)
    402 {
    403     m_bicubicShader->use(transform, texTransform, coefficients, imageIncrement, alpha);
    404 }
    405 
    406 void SharedGraphicsContext3D::useConvolutionProgram(const AffineTransform& transform, const AffineTransform& texTransform, const float* kernel, int kernelWidth, float imageIncrement[2])
    407 {
    408     ASSERT(kernelWidth >= 1 && kernelWidth <= cMaxKernelWidth);
    409     m_convolutionShaders[kernelWidth - 1]->use(transform, texTransform, kernel, kernelWidth, imageIncrement);
    410 }
    411 
    412 void SharedGraphicsContext3D::bindFramebuffer(Platform3DObject framebuffer)
    413 {
    414     m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, framebuffer);
    415 }
    416 
    417 void SharedGraphicsContext3D::setViewport(const IntSize& size)
    418 {
    419     m_context->viewport(0, 0, size.width(), size.height());
    420 }
    421 
    422 bool SharedGraphicsContext3D::paintsIntoCanvasBuffer() const
    423 {
    424     return m_context->paintsIntoCanvasBuffer();
    425 }
    426 
    427 bool SharedGraphicsContext3D::useLoopBlinnForPathRendering()
    428 {
    429     return false;
    430 }
    431 
    432 void SharedGraphicsContext3D::useLoopBlinnInteriorProgram(unsigned vertexOffset, const AffineTransform& transform, const Color& color)
    433 {
    434     if (!m_loopBlinnInteriorShader) {
    435         m_loopBlinnInteriorShader = LoopBlinnSolidFillShader::create(m_context.get(),
    436                                                                      LoopBlinnShader::Interior,
    437                                                                      Shader::NotAntialiased);
    438     }
    439     ASSERT(m_loopBlinnInteriorShader);
    440     m_loopBlinnInteriorShader->use(vertexOffset, 0, transform, color);
    441 }
    442 
    443 void SharedGraphicsContext3D::useLoopBlinnExteriorProgram(unsigned vertexOffset, unsigned klmOffset, const AffineTransform& transform, const Color& color)
    444 {
    445     if (!m_loopBlinnExteriorShader) {
    446         m_loopBlinnExteriorShader = LoopBlinnSolidFillShader::create(m_context.get(),
    447                                                                      LoopBlinnShader::Exterior,
    448                                                                      m_oesStandardDerivativesSupported ? Shader::Antialiased : Shader::NotAntialiased);
    449     }
    450     ASSERT(m_loopBlinnExteriorShader);
    451     m_loopBlinnExteriorShader->use(vertexOffset, klmOffset, transform, color);
    452 }
    453 
    454 DrawingBuffer* SharedGraphicsContext3D::getOffscreenBuffer(unsigned index, const IntSize& size)
    455 {
    456     if (index >= m_offscreenBuffers.size())
    457         m_offscreenBuffers.resize(index + 1);
    458 
    459     if (!m_offscreenBuffers[index])
    460         m_offscreenBuffers[index] = m_context->createDrawingBuffer(size);
    461 
    462     if (size.width() != m_offscreenBuffers[index]->size().width()
    463         || size.height() != m_offscreenBuffers[index]->size().height())
    464         m_offscreenBuffers[index]->reset(size);
    465     return m_offscreenBuffers[index].get();
    466 }
    467 
    468 #if ENABLE(SKIA_GPU)
    469 GrContext* SharedGraphicsContext3D::grContext()
    470 {
    471     if (!m_grContext) {
    472         m_grContext = GrContext::CreateGLShaderContext();
    473         m_grContext->setTextureCacheLimits(maxTextureCacheCount, maxTextureCacheBytes);
    474     }
    475     return m_grContext;
    476 }
    477 #endif
    478 
    479 } // namespace WebCore
    480 
    481 #endif
    482