15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
2591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (c) 2008, Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
4591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
7591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * modification, are permitted provided that the following conditions are
8591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * met:
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
10591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Redistributions of source code must retain the above copyright
11591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * notice, this list of conditions and the following disclaimer.
12591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Redistributions in binary form must reproduce the above
13591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * copyright notice, this list of conditions and the following disclaimer
14591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * in the documentation and/or other materials provided with the
15591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * distribution.
16591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Neither the name of Google Inc. nor the names of its
17591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * contributors may be used to endorse or promote products derived from
18591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * this software without specific prior written permission.
19591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *
20591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/ImageBuffer.h"
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
36323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)#include "GrContext.h"
3751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/MIMETypeRegistry.h"
381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/geometry/IntRect.h"
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/BitmapImage.h"
40a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
4109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/GraphicsTypes3D.h"
42aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "platform/graphics/ImageBufferClient.h"
43a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/UnacceleratedImageBufferSurface.h"
44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/gpu/DrawingBuffer.h"
4509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "platform/graphics/gpu/Extensions3DUtil.h"
46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/skia/NativeImageSkia.h"
47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/skia/SkiaUtils.h"
48a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/JPEGImageEncoder.h"
49a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/PNGImageEncoder.h"
50a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/image-encoders/skia/WEBPImageEncoder.h"
51591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/Platform.h"
5243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)#include "public/platform/WebExternalTextureMailbox.h"
5309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/WebGraphicsContext3D.h"
5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/WebGraphicsContext3DProvider.h"
55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "third_party/skia/include/core/SkPicture.h"
56c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#include "third_party/skia/include/effects/SkTableColorFilter.h"
57591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/MathExtras.h"
58c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "wtf/Vector.h"
59591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/Base64.h"
60591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/text/WTFString.h"
61591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
62c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassOwnPtr<ImageBuffer> ImageBuffer::create(PassOwnPtr<ImageBufferSurface> surface)
65591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
66a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!surface->isValid())
67591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return nullptr;
68a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return adoptPtr(new ImageBuffer(surface));
69591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
70591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
71a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opacityMode)
7251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSurface(size, opacityMode));
74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!surface->isValid())
7551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return nullptr;
76a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return adoptPtr(new ImageBuffer(surface.release()));
77591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
78591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    : m_surface(surface)
81aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    , m_client(0)
82591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
83a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_surface->canvas()) {
84a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_context = adoptPtr(new GraphicsContext(m_surface->canvas()));
85a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque);
86a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_context->setAccelerated(m_surface->isAccelerated());
8751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
88c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_surface->setImageBuffer(this);
89591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
90591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
91591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochImageBuffer::~ImageBuffer()
92591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
93591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
94591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
95591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochGraphicsContext* ImageBuffer::context() const
96591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
97aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid())
98aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch        return 0;
9909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ASSERT(m_context.get());
100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return m_context.get();
101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
102591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)const SkBitmap& ImageBuffer::bitmap() const
10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return m_surface->bitmap();
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
107fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
108aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochbool ImageBuffer::isSurfaceValid() const
109fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch{
110a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_surface->isValid();
111fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch}
112fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool ImageBuffer::isDirty()
114aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_client ? m_client->isDirty() : false;
116aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch}
117aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ImageBuffer::didFinalizeFrame()
119aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{
120aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (m_client)
121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_client->didFinalizeFrame();
122aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch}
123aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch
1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid ImageBuffer::finalizeFrame(const FloatRect &dirtyRect)
125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_surface->finalizeFrame(dirtyRect);
127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    didFinalizeFrame();
128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)bool ImageBuffer::restoreSurface() const
131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_surface->isValid() || m_surface->restore();
133c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ImageBuffer::notifySurfaceInvalid()
136197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
137197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_client)
138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_client->notifySurfaceInvalid();
139197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
140197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
141591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap)
142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
143591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SkBitmap tmp;
144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!bitmap.deepCopyTo(&tmp))
145d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        bitmap.copyTo(&tmp, bitmap.colorType());
146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
147591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return tmp;
148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
149591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
150591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const
151591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
152aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid())
153fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        return BitmapImage::create(NativeImageSkia::create());
154fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
155a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const SkBitmap& bitmap = m_surface->bitmap();
156a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBackingStore ? deepSkBitmapCopy(bitmap) : bitmap));
157591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
158591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
159591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochBackingStoreCopy ImageBuffer::fastCopyImageMode()
160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return DontCopyBackingStore;
162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
163591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
164e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)WebLayer* ImageBuffer::platformLayer() const
165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
166a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_surface->layer();
167591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
168591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
169e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ImageBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
170591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_surface->isAccelerated() || !getBackingTexture() || !isSurfaceValid())
172591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return false;
173591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
17443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level))
175591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return false;
176591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
177e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
17843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    if (!provider)
17943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        return false;
180e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebGraphicsContext3D* sharedContext = provider->context3d();
1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!sharedContext)
18243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        return false;
18343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
184e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    OwnPtr<WebExternalTextureMailbox> mailbox = adoptPtr(new WebExternalTextureMailbox);
18543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
18643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // Contexts may be in a different share group. We must transfer the texture through a mailbox first
18743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    sharedContext->genMailboxCHROMIUM(mailbox->name);
1885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    sharedContext->produceTextureDirectCHROMIUM(getBackingTexture(), GL_TEXTURE_2D, mailbox->name);
18943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    sharedContext->flush();
19043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
19143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    mailbox->syncPoint = sharedContext->insertSyncPoint();
19243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
19343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    context->waitSyncPoint(mailbox->syncPoint);
1945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name);
19543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
196591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // The canvas is stored in a premultiplied format, so unpremultiply if necessary.
19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);
198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // The canvas is stored in an inverted position, so the flip semantics are reversed.
20009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, !flipY);
20143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
202591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
20309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false);
20409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
20543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
20643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    context->deleteTexture(sourceTexture);
20743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
20809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    context->flush();
20943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    sharedContext->waitSyncPoint(context->insertSyncPoint());
21043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
211323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    // Undo grContext texture binding changes introduced in this function
212323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
213323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
214591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return true;
215591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
216591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst)
218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
219a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(dst);
220591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return (src == dst);
221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
222591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
22351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)Platform3DObject ImageBuffer::getBackingTexture()
22451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
225a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_surface->getBackingTexture();
22651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
22751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid ImageBuffer::didModifyBackingTexture()
2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_surface->didModifyBackingTexture();
2317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2335d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer, bool fromFrontBuffer)
23451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
23551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!drawingBuffer)
23651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return false;
237e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!provider)
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return false;
240e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    WebGraphicsContext3D* context3D = provider->context3d();
241a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    Platform3DObject tex = m_surface->getBackingTexture();
24251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!context3D || !tex)
24351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return false;
2445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
24509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_surface->invalidateCachedBitmap();
2467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool result = drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA,
2475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer);
2487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (result) {
2507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_surface->didModifyBackingTexture();
2517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
2527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return result;
25451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
25551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
256c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect* srcPtr, CompositeOperator op, WebBlendMode blendMode)
257591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
258aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid())
259fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        return;
260fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
261f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    FloatRect srcRect = srcPtr ? *srcPtr : FloatRect(FloatPoint(), size());
262c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RefPtr<SkPicture> picture = m_surface->getPicture();
263c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (picture) {
264c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        context->drawPicture(picture.release(), destRect, srcRect, op, blendMode);
265c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
266c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
267c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
26809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkBitmap bitmap = m_surface->bitmap();
26909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // For ImageBufferSurface that enables cachedBitmap, Use the cached Bitmap for CPU side usage
27009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // if it is available, otherwise generate and use it.
271aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->cachedBitmapEnabled() && isSurfaceValid()) {
27209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_surface->updateCachedBitmapIfNeeded();
27309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        bitmap = m_surface->cachedBitmap();
27409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
27509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
276591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap));
27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
278c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespectImageOrientation);
279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
281a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ImageBuffer::flush()
282a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
283a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_surface->canvas()) {
284a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_surface->canvas()->flush();
285a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
286a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
287a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
288591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const FloatSize& scale,
289e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing)
290591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
291aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid())
292fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        return;
293fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
294a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const SkBitmap& bitmap = m_surface->bitmap();
295591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap));
2961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    image->drawPattern(context, srcRect, scale, phase, op, destRect, blendMode, repeatSpacing);
297591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
299591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
300591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
30109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
30209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!lookUpTable)
303591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
304591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // FIXME: Disable color space conversions on accelerated canvases (for now).
306aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (context()->isAccelerated() || !isSurfaceValid())
307591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
308591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
309a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    const SkBitmap& bitmap = m_surface->bitmap();
310591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (bitmap.isNull())
311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return;
312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
313197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ASSERT(bitmap.colorType() == kN32_SkColorType);
314a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    IntSize size = m_surface->size();
315591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SkAutoLockPixels bitmapLock(bitmap);
316a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    for (int y = 0; y < size.height(); ++y) {
317591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        uint32_t* srcRow = bitmap.getAddr32(0, y);
318a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        for (int x = 0; x < size.width(); ++x) {
319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            SkColor color = SkPMColorToColor(srcRow[x]);
320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            srcRow[x] = SkPreMultiplyARGB(
321591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                SkColorGetA(color),
322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                lookUpTable[SkColorGetR(color)],
323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                lookUpTable[SkColorGetG(color)],
324591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                lookUpTable[SkColorGetB(color)]);
325591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
326591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
327591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
328591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
329c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)PassRefPtr<SkColorFilter> ImageBuffer::createColorSpaceFilter(ColorSpace srcColorSpace,
330c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    ColorSpace dstColorSpace)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
33209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const uint8_t* lut = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!lut)
334d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
3355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
336c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)    return adoptRef(SkTableColorFilter::CreateARGB(0, lut, lut, lut));
337c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)}
338591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
339197021e6b966cfb06891637935ef33fff06433d1Ben MurdochPassRefPtr<Uint8ClampedArray> ImageBuffer::getImageData(Multiply multiplied, const IntRect& rect) const
3405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
341197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (!isSurfaceValid())
342197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
343197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    float area = 4.0f * rect.width() * rect.height();
345591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (area > static_cast<float>(std::numeric_limits<int>::max()))
346d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (rect.x() < 0
351591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        || rect.y() < 0
352197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        || rect.maxX() > m_surface->size().width()
353197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        || rect.maxY() > m_surface->size().height())
354591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        result->zeroFill();
355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
35607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
35707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType);
358591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
359e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_surface->willAccessPixels();
360197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    context()->readPixels(info, result->data(), 4 * rect.width(), rect.x(), rect.y());
361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return result.release();
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
364a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
365591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
366aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid())
367fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        return;
368fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch
369591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(sourceRect.width() > 0);
370591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(sourceRect.height() > 0);
371591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int originX = sourceRect.x();
373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int destX = destPoint.x() + sourceRect.x();
374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(destX >= 0);
375a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(destX < m_surface->size().width());
376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(originX >= 0);
377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(originX < sourceRect.maxX());
378591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
379591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int originY = sourceRect.y();
380591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    int destY = destPoint.y() + sourceRect.y();
381591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(destY >= 0);
382a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(destY < m_surface->size().height());
383591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(originY >= 0);
384591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(originY < sourceRect.maxY());
385591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
386d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const size_t srcBytesPerRow = 4 * sourceSize.width();
387d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const void* srcAddr = source->data() + originY * srcBytesPerRow + originX * 4;
388197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
389d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    SkImageInfo info = SkImageInfo::Make(sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, alphaType);
390591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
391e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_surface->willAccessPixels();
392e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
393d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    context()->writePixels(info, srcAddr, srcBytesPerRow, destX, destY);
394591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
395591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
396591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochtemplate <typename T>
397591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochstatic bool encodeImage(T& source, const String& mimeType, const double* quality, Vector<char>* output)
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
399591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned char>* encodedImage = reinterpret_cast<Vector<unsigned char>*>(output);
400591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
401591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (mimeType == "image/jpeg") {
402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
403591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (quality && *quality >= 0.0 && *quality <= 1.0)
404591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            compressionQuality = static_cast<int>(*quality * 100 + 0.5);
405591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!JPEGImageEncoder::encode(source, compressionQuality, encodedImage))
406591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return false;
407591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else if (mimeType == "image/webp") {
408591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        int compressionQuality = WEBPImageEncoder::DefaultCompressionQuality;
409591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (quality && *quality >= 0.0 && *quality <= 1.0)
410591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            compressionQuality = static_cast<int>(*quality * 100 + 0.5);
411591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!WEBPImageEncoder::encode(source, compressionQuality, encodedImage))
412591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return false;
413591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } else {
414591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!PNGImageEncoder::encode(source, encodedImage))
415591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return false;
416591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ASSERT(mimeType == "image/png");
417591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
418591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
419591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return true;
420591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
421591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
422a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
423591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
424591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
425591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
426591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<char> encodedImage;
427aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch    if (!isSurfaceValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage))
428591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return "data:,";
429591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return "data:" + mimeType + ";base64," + base64Encode(encodedImage);
431591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
432591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
43351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)String ImageDataToDataURL(const ImageDataBuffer& imageData, const String& mimeType, const double* quality)
434591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
435591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
436591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
437591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<char> encodedImage;
438591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (!encodeImage(imageData, mimeType, quality, &encodedImage))
439591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        return "data:,";
440591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
4417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return "data:" + mimeType + ";base64," + base64Encode(encodedImage);
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
444c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
445