Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / ImageBuffer.cpp
index 52fdf80..0defbb0 100644 (file)
 #include "config.h"
 #include "platform/graphics/ImageBuffer.h"
 
+#include "GrContext.h"
 #include "platform/MIMETypeRegistry.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/graphics/BitmapImage.h"
 #include "platform/graphics/GraphicsContext.h"
-#include "platform/graphics/GraphicsContext3D.h"
+#include "platform/graphics/GraphicsTypes3D.h"
+#include "platform/graphics/ImageBufferClient.h"
 #include "platform/graphics/UnacceleratedImageBufferSurface.h"
 #include "platform/graphics/gpu/DrawingBuffer.h"
-#include "platform/graphics/gpu/SharedGraphicsContext3D.h"
+#include "platform/graphics/gpu/Extensions3DUtil.h"
 #include "platform/graphics/skia/NativeImageSkia.h"
 #include "platform/graphics/skia/SkiaUtils.h"
 #include "platform/image-encoders/skia/JPEGImageEncoder.h"
 #include "platform/image-encoders/skia/PNGImageEncoder.h"
 #include "platform/image-encoders/skia/WEBPImageEncoder.h"
 #include "public/platform/Platform.h"
+#include "public/platform/WebExternalTextureMailbox.h"
 #include "public/platform/WebGraphicsContext3D.h"
+#include "public/platform/WebGraphicsContext3DProvider.h"
+#include "third_party/skia/include/core/SkPicture.h"
 #include "third_party/skia/include/effects/SkTableColorFilter.h"
 #include "wtf/MathExtras.h"
+#include "wtf/Vector.h"
 #include "wtf/text/Base64.h"
 #include "wtf/text/WTFString.h"
 
 using namespace std;
 
-namespace WebCore {
+namespace blink {
 
 PassOwnPtr<ImageBuffer> ImageBuffer::create(PassOwnPtr<ImageBufferSurface> surface)
 {
@@ -74,12 +80,14 @@ PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
 
 ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
     : m_surface(surface)
+    , m_client(0)
 {
     if (m_surface->canvas()) {
         m_context = adoptPtr(new GraphicsContext(m_surface->canvas()));
         m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque);
         m_context->setAccelerated(m_surface->isAccelerated());
     }
+    m_surface->setImageBuffer(this);
 }
 
 ImageBuffer::~ImageBuffer()
@@ -88,34 +96,62 @@ ImageBuffer::~ImageBuffer()
 
 GraphicsContext* ImageBuffer::context() const
 {
-    m_surface->willUse();
+    if (!isSurfaceValid())
+        return 0;
     ASSERT(m_context.get());
     return m_context.get();
 }
 
 const SkBitmap& ImageBuffer::bitmap() const
 {
-    m_surface->willUse();
     return m_surface->bitmap();
 }
 
-bool ImageBuffer::isValid() const
+bool ImageBuffer::isSurfaceValid() const
 {
     return m_surface->isValid();
 }
 
+bool ImageBuffer::isDirty()
+{
+    return m_client ? m_client->isDirty() : false;
+}
+
+void ImageBuffer::didFinalizeFrame()
+{
+    if (m_client)
+        m_client->didFinalizeFrame();
+}
+
+void ImageBuffer::finalizeFrame()
+{
+    m_surface->finalizeFrame();
+    didFinalizeFrame();
+}
+
+bool ImageBuffer::restoreSurface() const
+{
+    return m_surface->isValid() || m_surface->restore();
+}
+
+void ImageBuffer::notifySurfaceInvalid()
+{
+    if (m_client)
+        m_client->notifySurfaceInvalid();
+}
+
 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap)
 {
     SkBitmap tmp;
-    if (!bitmap.deepCopyTo(&tmp, bitmap.config()))
-        bitmap.copyTo(&tmp, bitmap.config());
+    if (!bitmap.deepCopyTo(&tmp))
+        bitmap.copyTo(&tmp, bitmap.colorType());
 
     return tmp;
 }
 
 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBehavior) const
 {
-    if (!isValid())
+    if (!isSurfaceValid())
         return BitmapImage::create(NativeImageSkia::create());
 
     const SkBitmap& bitmap = m_surface->bitmap();
@@ -127,35 +163,59 @@ BackingStoreCopy ImageBuffer::fastCopyImageMode()
     return DontCopyBackingStore;
 }
 
-blink::WebLayer* ImageBuffer::platformLayer() const
+WebLayer* ImageBuffer::platformLayer() const
 {
     return m_surface->layer();
 }
 
-bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& contextSupport, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
+bool ImageBuffer::copyToPlatformTexture(WebGraphicsContext3D* context, Platform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, bool premultiplyAlpha, bool flipY)
 {
-    if (!m_surface->isAccelerated() || !platformLayer() || !isValid())
+    if (!m_surface->isAccelerated() || !platformLayer() || !isSurfaceValid())
         return false;
 
-    blink::WebGraphicsContext3D* context = contextSupport.webContext();
+    if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, level))
+        return false;
 
-    if (!context->makeContextCurrent())
+    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+    if (!provider)
+        return false;
+    WebGraphicsContext3D* sharedContext = provider->context3d();
+    if (!sharedContext || !sharedContext->makeContextCurrent())
         return false;
 
-    if (!contextSupport.supportsExtension("GL_CHROMIUM_copy_texture") || !contextSupport.supportsExtension("GL_CHROMIUM_flipy")
-        || !contextSupport.canUseCopyTextureCHROMIUM(internalFormat, destType, level))
+    OwnPtr<WebExternalTextureMailbox> mailbox = adoptPtr(new WebExternalTextureMailbox);
+
+    // Contexts may be in a different share group. We must transfer the texture through a mailbox first
+    sharedContext->genMailboxCHROMIUM(mailbox->name);
+    sharedContext->produceTextureDirectCHROMIUM(getBackingTexture(), GL_TEXTURE_2D, mailbox->name);
+    sharedContext->flush();
+
+    mailbox->syncPoint = sharedContext->insertSyncPoint();
+
+    if (!context->makeContextCurrent())
         return false;
 
+    context->waitSyncPoint(mailbox->syncPoint);
+    Platform3DObject sourceTexture = context->createAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox->name);
+
     // The canvas is stored in a premultiplied format, so unpremultiply if necessary.
     context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, !premultiplyAlpha);
 
     // The canvas is stored in an inverted position, so the flip semantics are reversed.
     context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, !flipY);
-    context->copyTextureCHROMIUM(GL_TEXTURE_2D, getBackingTexture(), texture, level, internalFormat, destType);
+    context->copyTextureCHROMIUM(GL_TEXTURE_2D, sourceTexture, texture, level, internalFormat, destType);
 
     context->pixelStorei(GC3D_UNPACK_FLIP_Y_CHROMIUM, false);
     context->pixelStorei(GC3D_UNPACK_UNPREMULTIPLY_ALPHA_CHROMIUM, false);
+
+    context->deleteTexture(sourceTexture);
+
     context->flush();
+    sharedContext->waitSyncPoint(context->insertSyncPoint());
+
+    // Undo grContext texture binding changes introduced in this function
+    provider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
+
     return true;
 }
 
@@ -170,36 +230,46 @@ Platform3DObject ImageBuffer::getBackingTexture()
     return m_surface->getBackingTexture();
 }
 
-bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer)
+bool ImageBuffer::copyRenderingResultsFromDrawingBuffer(DrawingBuffer* drawingBuffer, bool fromFrontBuffer)
 {
     if (!drawingBuffer)
         return false;
-    RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get();
+    OwnPtr<WebGraphicsContext3DProvider> provider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
+    if (!provider)
+        return false;
+    WebGraphicsContext3D* context3D = provider->context3d();
     Platform3DObject tex = m_surface->getBackingTexture();
     if (!context3D || !tex)
         return false;
+
     m_surface->invalidateCachedBitmap();
-    return drawingBuffer->copyToPlatformTexture(*(context3D.get()), tex, GL_RGBA,
-        GL_UNSIGNED_BYTE, 0, true, false);
+    return drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA,
+        GL_UNSIGNED_BYTE, 0, true, false, fromFrontBuffer);
 }
 
-void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect& srcRect,
-    CompositeOperator op, blink::WebBlendMode blendMode, bool useLowQualityScale)
+void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, const FloatRect* srcPtr, CompositeOperator op, WebBlendMode blendMode)
 {
-    if (!isValid())
+    if (!isSurfaceValid())
         return;
 
+    FloatRect srcRect = srcPtr ? *srcPtr : FloatRect(FloatPoint(), size());
+    RefPtr<SkPicture> picture = m_surface->getPicture();
+    if (picture) {
+        context->drawPicture(picture.release(), destRect, srcRect, op, blendMode);
+        return;
+    }
+
     SkBitmap bitmap = m_surface->bitmap();
     // For ImageBufferSurface that enables cachedBitmap, Use the cached Bitmap for CPU side usage
     // if it is available, otherwise generate and use it.
-    if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->cachedBitmapEnabled() && m_surface->isValid()) {
+    if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->cachedBitmapEnabled() && isSurfaceValid()) {
         m_surface->updateCachedBitmapIfNeeded();
         bitmap = m_surface->cachedBitmap();
     }
 
     RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap));
 
-    context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespectImageOrientation, useLowQualityScale);
+    context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespectImageOrientation);
 }
 
 void ImageBuffer::flush()
@@ -210,9 +280,9 @@ void ImageBuffer::flush()
 }
 
 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const FloatSize& scale,
-    const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, blink::WebBlendMode blendMode, const IntSize& repeatSpacing)
+    const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, WebBlendMode blendMode, const IntSize& repeatSpacing)
 {
-    if (!isValid())
+    if (!isSurfaceValid())
         return;
 
     const SkBitmap& bitmap = m_surface->bitmap();
@@ -227,14 +297,14 @@ void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
         return;
 
     // FIXME: Disable color space conversions on accelerated canvases (for now).
-    if (context()->isAccelerated() || !isValid())
+    if (context()->isAccelerated() || !isSurfaceValid())
         return;
 
     const SkBitmap& bitmap = m_surface->bitmap();
     if (bitmap.isNull())
         return;
 
-    ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
+    ASSERT(bitmap.colorType() == kN32_SkColorType);
     IntSize size = m_surface->size();
     SkAutoLockPixels bitmapLock(bitmap);
     for (int y = 0; y < size.height(); ++y) {
@@ -255,60 +325,39 @@ PassRefPtr<SkColorFilter> ImageBuffer::createColorSpaceFilter(ColorSpace srcColo
 {
     const uint8_t* lut = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace);
     if (!lut)
-        return 0;
+        return nullptr;
 
     return adoptRef(SkTableColorFilter::CreateARGB(0, lut, lut, lut));
 }
 
-template <Multiply multiplied>
-PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, GraphicsContext* context, const IntSize& size)
+PassRefPtr<Uint8ClampedArray> ImageBuffer::getImageData(Multiply multiplied, const IntRect& rect) const
 {
+    if (!isSurfaceValid())
+        return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
+
     float area = 4.0f * rect.width() * rect.height();
     if (area > static_cast<float>(std::numeric_limits<int>::max()))
-        return 0;
+        return nullptr;
 
     RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4);
 
-    unsigned char* data = result->data();
-
     if (rect.x() < 0
         || rect.y() < 0
-        || rect.maxX() > size.width()
-        || rect.maxY() > size.height())
+        || rect.maxX() > m_surface->size().width()
+        || rect.maxY() > m_surface->size().height())
         result->zeroFill();
 
-    unsigned destBytesPerRow = 4 * rect.width();
-    SkBitmap destBitmap;
-    destBitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height(), destBytesPerRow);
-    destBitmap.setPixels(data);
-
-    SkCanvas::Config8888 config8888;
-    if (multiplied == Premultiplied)
-        config8888 = SkCanvas::kRGBA_Premul_Config8888;
-    else
-        config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+    SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+    SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888_SkColorType, alphaType);
 
-    context->readPixels(&destBitmap, rect.x(), rect.y(), config8888);
+    m_surface->willAccessPixels();
+    context()->readPixels(info, result->data(), 4 * rect.width(), rect.x(), rect.y());
     return result.release();
 }
 
-PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
-{
-    if (!isValid())
-        return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
-    return getImageData<Unmultiplied>(rect, context(), m_surface->size());
-}
-
-PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
-{
-    if (!isValid())
-        return Uint8ClampedArray::create(rect.width() * rect.height() * 4);
-    return getImageData<Premultiplied>(rect, context(), m_surface->size());
-}
-
 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
 {
-    if (!isValid())
+    if (!isSurfaceValid())
         return;
 
     ASSERT(sourceRect.width() > 0);
@@ -321,11 +370,6 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
     ASSERT(originX >= 0);
     ASSERT(originX < sourceRect.maxX());
 
-    int endX = destPoint.x() + sourceRect.maxX();
-    ASSERT(endX <= m_surface->size().width());
-
-    int numColumns = endX - destX;
-
     int originY = sourceRect.y();
     int destY = destPoint.y() + sourceRect.y();
     ASSERT(destY >= 0);
@@ -333,22 +377,14 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
     ASSERT(originY >= 0);
     ASSERT(originY < sourceRect.maxY());
 
-    int endY = destPoint.y() + sourceRect.maxY();
-    ASSERT(endY <= m_surface->size().height());
-    int numRows = endY - destY;
-
-    unsigned srcBytesPerRow = 4 * sourceSize.width();
-    SkBitmap srcBitmap;
-    srcBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow);
-    srcBitmap.setPixels(source->data() + originY * srcBytesPerRow + originX * 4);
+    const size_t srcBytesPerRow = 4 * sourceSize.width();
+    const void* srcAddr = source->data() + originY * srcBytesPerRow + originX * 4;
+    SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
+    SkImageInfo info = SkImageInfo::Make(sourceRect.width(), sourceRect.height(), kRGBA_8888_SkColorType, alphaType);
 
-    SkCanvas::Config8888 config8888;
-    if (multiplied == Premultiplied)
-        config8888 = SkCanvas::kRGBA_Premul_Config8888;
-    else
-        config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
+    m_surface->willAccessPixels();
 
-    context()->writePixels(srcBitmap, destX, destY, config8888);
+    context()->writePixels(info, srcAddr, srcBytesPerRow, destX, destY);
 }
 
 template <typename T>
@@ -382,7 +418,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
     Vector<char> encodedImage;
-    if (!isValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage))
+    if (!isSurfaceValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &encodedImage))
         return "data:,";
     Vector<char> base64Data;
     base64Encode(encodedImage, base64Data);
@@ -404,4 +440,4 @@ String ImageDataToDataURL(const ImageDataBuffer& imageData, const String& mimeTy
     return "data:" + mimeType + ";base64," + base64Data;
 }
 
-} // namespace WebCore
+} // namespace blink