| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2008, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, Google Inc. All rights reserved. |
| 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 3 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
| 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are | 7 * modification, are permitted provided that the following conditions are |
| 8 * met: | 8 * met: |
| 9 * | 9 * |
| 10 * * Redistributions of source code must retain the above copyright | 10 * * Redistributions of source code must retain the above copyright |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 using namespace std; | 62 using namespace std; |
| 63 | 63 |
| 64 namespace WebCore { | 64 namespace WebCore { |
| 65 | 65 |
| 66 static SkCanvas* createAcceleratedCanvas(const IntSize& size, OwnPtr<Canvas2DLay
erBridge>* outLayerBridge, OpacityMode opacityMode) | 66 static SkCanvas* createAcceleratedCanvas(const IntSize& size, OwnPtr<Canvas2DLay
erBridge>* outLayerBridge, OpacityMode opacityMode) |
| 67 { | 67 { |
| 68 RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); | 68 RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); |
| 69 if (!context3D) | 69 if (!context3D) |
| 70 return 0; | 70 return 0; |
| 71 GrContext* gr = context3D->grContext(); | |
| 72 if (!gr) | |
| 73 return 0; | |
| 74 gr->resetContext(); | |
| 75 Canvas2DLayerBridge::OpacityMode bridgeOpacityMode = opacityMode == Opaque ?
Canvas2DLayerBridge::Opaque : Canvas2DLayerBridge::NonOpaque; | 71 Canvas2DLayerBridge::OpacityMode bridgeOpacityMode = opacityMode == Opaque ?
Canvas2DLayerBridge::Opaque : Canvas2DLayerBridge::NonOpaque; |
| 76 Canvas2DLayerBridge::ThreadMode threadMode = WebKit::Platform::current()->is
ThreadedCompositingEnabled() ? Canvas2DLayerBridge::Threaded : Canvas2DLayerBrid
ge::SingleThread; | 72 Canvas2DLayerBridge::ThreadMode threadMode = WebKit::Platform::current()->is
ThreadedCompositingEnabled() ? Canvas2DLayerBridge::Threaded : Canvas2DLayerBrid
ge::SingleThread; |
| 77 SkImage::Info info; | 73 *outLayerBridge = Canvas2DLayerBridge::create(context3D.release(), size, bri
dgeOpacityMode, threadMode); |
| 78 info.fWidth = size.width(); | |
| 79 info.fHeight = size.height(); | |
| 80 info.fColorType = SkImage::kPMColor_ColorType; | |
| 81 info.fAlphaType = SkImage::kPremul_AlphaType; | |
| 82 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context3D->grCont
ext(), info)); | |
| 83 if (!surface.get()) | |
| 84 return 0; | |
| 85 SkDeferredCanvas* canvas = new SkDeferredCanvas(surface.get()); | |
| 86 *outLayerBridge = Canvas2DLayerBridge::create(context3D.release(), canvas, b
ridgeOpacityMode, threadMode); | |
| 87 // If canvas buffer allocation failed, debug build will have asserted | 74 // If canvas buffer allocation failed, debug build will have asserted |
| 88 // For release builds, we must verify whether the device has a render target | 75 // For release builds, we must verify whether the device has a render target |
| 89 return canvas; | 76 return (*outLayerBridge) ? (*outLayerBridge)->getCanvas() : 0; |
| 90 } | 77 } |
| 91 | 78 |
| 92 static SkCanvas* createNonPlatformCanvas(const IntSize& size) | 79 static SkCanvas* createNonPlatformCanvas(const IntSize& size) |
| 93 { | 80 { |
| 94 SkAutoTUnref<SkDevice> device(new SkDevice(SkBitmap::kARGB_8888_Config, size
.width(), size.height())); | 81 SkAutoTUnref<SkDevice> device(new SkDevice(SkBitmap::kARGB_8888_Config, size
.width(), size.height())); |
| 95 SkPixelRef* pixelRef = device->accessBitmap(false).pixelRef(); | 82 SkPixelRef* pixelRef = device->accessBitmap(false).pixelRef(); |
| 96 return pixelRef ? new SkCanvas(device) : 0; | 83 return pixelRef ? new SkCanvas(device) : 0; |
| 97 } | 84 } |
| 98 | 85 |
| 99 PassOwnPtr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const IntSize& size,
float resolutionScale, const GraphicsContext* context, bool hasAlpha) | 86 PassOwnPtr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const IntSize& size,
float resolutionScale, const GraphicsContext* context, bool hasAlpha) |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 GraphicsContext* ImageBuffer::context() const | 163 GraphicsContext* ImageBuffer::context() const |
| 177 { | 164 { |
| 178 if (m_layerBridge) { | 165 if (m_layerBridge) { |
| 179 // We're using context acquisition as a signal that someone is about to
render into our buffer and we need | 166 // We're using context acquisition as a signal that someone is about to
render into our buffer and we need |
| 180 // to be ready. This isn't logically const-correct, hence the cast. | 167 // to be ready. This isn't logically const-correct, hence the cast. |
| 181 const_cast<Canvas2DLayerBridge*>(m_layerBridge.get())->contextAcquired()
; | 168 const_cast<Canvas2DLayerBridge*>(m_layerBridge.get())->contextAcquired()
; |
| 182 } | 169 } |
| 183 return m_context.get(); | 170 return m_context.get(); |
| 184 } | 171 } |
| 185 | 172 |
| 173 |
| 174 bool ImageBuffer::isValid() const |
| 175 { |
| 176 if (m_layerBridge.get()) |
| 177 return const_cast<Canvas2DLayerBridge*>(m_layerBridge.get())->isValid(); |
| 178 return true; |
| 179 } |
| 180 |
| 186 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) | 181 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) |
| 187 { | 182 { |
| 188 SkBitmap tmp; | 183 SkBitmap tmp; |
| 189 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) | 184 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) |
| 190 bitmap.copyTo(&tmp, bitmap.config()); | 185 bitmap.copyTo(&tmp, bitmap.config()); |
| 191 | 186 |
| 192 return tmp; | 187 return tmp; |
| 193 } | 188 } |
| 194 | 189 |
| 195 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh
avior) const | 190 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh
avior) const |
| 196 { | 191 { |
| 192 if (!isValid()) |
| 193 return BitmapImage::create(NativeImageSkia::create()); |
| 194 |
| 197 const SkBitmap& bitmap = *context()->bitmap(); | 195 const SkBitmap& bitmap = *context()->bitmap(); |
| 198 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. | 196 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. |
| 199 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki
ngStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); | 197 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki
ngStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); |
| 200 } | 198 } |
| 201 | 199 |
| 202 BackingStoreCopy ImageBuffer::fastCopyImageMode() | 200 BackingStoreCopy ImageBuffer::fastCopyImageMode() |
| 203 { | 201 { |
| 204 return DontCopyBackingStore; | 202 return DontCopyBackingStore; |
| 205 } | 203 } |
| 206 | 204 |
| 207 WebKit::WebLayer* ImageBuffer::platformLayer() const | 205 WebKit::WebLayer* ImageBuffer::platformLayer() const |
| 208 { | 206 { |
| 209 return m_layerBridge ? m_layerBridge->layer() : 0; | 207 return m_layerBridge ? m_layerBridge->layer() : 0; |
| 210 } | 208 } |
| 211 | 209 |
| 212 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb
ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr
emultiplyAlpha, bool flipY) | 210 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb
ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr
emultiplyAlpha, bool flipY) |
| 213 { | 211 { |
| 214 if (!m_layerBridge || !platformLayer()) | 212 if (!m_layerBridge || !platformLayer() || !isValid()) |
| 215 return false; | 213 return false; |
| 216 | 214 |
| 217 Platform3DObject sourceTexture = m_layerBridge->backBufferTexture(); | 215 Platform3DObject sourceTexture = m_layerBridge->backBufferTexture(); |
| 218 | 216 |
| 219 if (!context.makeContextCurrent()) | 217 if (!context.makeContextCurrent()) |
| 220 return false; | 218 return false; |
| 221 | 219 |
| 222 Extensions3D* extensions = context.getExtensions(); | 220 Extensions3D* extensions = context.getExtensions(); |
| 223 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor
ts("GL_CHROMIUM_flipy") | 221 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor
ts("GL_CHROMIUM_flipy") |
| 224 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve
l)) | 222 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve
l)) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 244 } | 242 } |
| 245 | 243 |
| 246 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) | 244 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) |
| 247 { | 245 { |
| 248 return (src == dst); | 246 return (src == dst); |
| 249 } | 247 } |
| 250 | 248 |
| 251 void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, cons
t FloatRect& srcRect, | 249 void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, cons
t FloatRect& srcRect, |
| 252 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) | 250 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) |
| 253 { | 251 { |
| 252 if (!isValid()) |
| 253 return; |
| 254 |
| 254 const SkBitmap& bitmap = *m_context->bitmap(); | 255 const SkBitmap& bitmap = *m_context->bitmap(); |
| 255 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 256 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 256 context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespe
ctImageOrientation, useLowQualityScale); | 257 context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespe
ctImageOrientation, useLowQualityScale); |
| 257 } | 258 } |
| 258 | 259 |
| 259 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
, const FloatSize& scale, | 260 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
, const FloatSize& scale, |
| 260 const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) | 261 const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) |
| 261 { | 262 { |
| 263 if (!isValid()) |
| 264 return; |
| 265 |
| 262 const SkBitmap& bitmap = *m_context->bitmap(); | 266 const SkBitmap& bitmap = *m_context->bitmap(); |
| 263 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 267 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 264 image->drawPattern(context, srcRect, scale, phase, op, destRect); | 268 image->drawPattern(context, srcRect, scale, phase, op, destRect); |
| 265 } | 269 } |
| 266 | 270 |
| 267 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
lorSpace) | 271 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
lorSpace) |
| 268 { | 272 { |
| 269 if (srcColorSpace == dstColorSpace) | 273 if (srcColorSpace == dstColorSpace) |
| 270 return; | 274 return; |
| 271 | 275 |
| 272 // only sRGB <-> linearRGB are supported at the moment | 276 // only sRGB <-> linearRGB are supported at the moment |
| 273 if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDevi
ceRGB) | 277 if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDevi
ceRGB) |
| 274 || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceD
eviceRGB)) | 278 || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceD
eviceRGB)) |
| 275 return; | 279 return; |
| 276 | 280 |
| 277 // FIXME: Disable color space conversions on accelerated canvases (for now). | 281 // FIXME: Disable color space conversions on accelerated canvases (for now). |
| 278 if (context()->isAccelerated()) | 282 if (context()->isAccelerated() || !isValid()) |
| 279 return; | 283 return; |
| 280 | 284 |
| 281 const SkBitmap& bitmap = *context()->bitmap(); | 285 const SkBitmap& bitmap = *context()->bitmap(); |
| 282 if (bitmap.isNull()) | 286 if (bitmap.isNull()) |
| 283 return; | 287 return; |
| 284 | 288 |
| 285 const Vector<uint8_t>& lookUpTable = dstColorSpace == ColorSpaceLinearRGB ? | 289 const Vector<uint8_t>& lookUpTable = dstColorSpace == ColorSpaceLinearRGB ? |
| 286 getLinearRgbLUT() : getDeviceRgbLUT(); | 290 getLinearRgbLUT() : getDeviceRgbLUT(); |
| 287 | 291 |
| 288 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); | 292 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 config8888 = SkCanvas::kRGBA_Premul_Config8888; | 362 config8888 = SkCanvas::kRGBA_Premul_Config8888; |
| 359 else | 363 else |
| 360 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; | 364 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; |
| 361 | 365 |
| 362 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); | 366 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); |
| 363 return result.release(); | 367 return result.release(); |
| 364 } | 368 } |
| 365 | 369 |
| 366 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec
t& rect, CoordinateSystem) const | 370 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec
t& rect, CoordinateSystem) const |
| 367 { | 371 { |
| 372 if (!isValid()) |
| 373 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); |
| 368 return getImageData<Unmultiplied>(rect, context(), m_size); | 374 return getImageData<Unmultiplied>(rect, context(), m_size); |
| 369 } | 375 } |
| 370 | 376 |
| 371 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe
ct& rect, CoordinateSystem) const | 377 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe
ct& rect, CoordinateSystem) const |
| 372 { | 378 { |
| 379 if (!isValid()) |
| 380 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); |
| 373 return getImageData<Premultiplied>(rect, context(), m_size); | 381 return getImageData<Premultiplied>(rect, context(), m_size); |
| 374 } | 382 } |
| 375 | 383 |
| 376 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
CoordinateSystem) | 384 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
CoordinateSystem) |
| 377 { | 385 { |
| 386 if (!isValid()) |
| 387 return; |
| 388 |
| 378 ASSERT(sourceRect.width() > 0); | 389 ASSERT(sourceRect.width() > 0); |
| 379 ASSERT(sourceRect.height() > 0); | 390 ASSERT(sourceRect.height() > 0); |
| 380 | 391 |
| 381 int originX = sourceRect.x(); | 392 int originX = sourceRect.x(); |
| 382 int destX = destPoint.x() + sourceRect.x(); | 393 int destX = destPoint.x() + sourceRect.x(); |
| 383 ASSERT(destX >= 0); | 394 ASSERT(destX >= 0); |
| 384 ASSERT(destX < m_size.width()); | 395 ASSERT(destX < m_size.width()); |
| 385 ASSERT(originX >= 0); | 396 ASSERT(originX >= 0); |
| 386 ASSERT(originX < sourceRect.maxX()); | 397 ASSERT(originX < sourceRect.maxX()); |
| 387 | 398 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 } | 470 } |
| 460 | 471 |
| 461 return true; | 472 return true; |
| 462 } | 473 } |
| 463 | 474 |
| 464 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo
rdinateSystem) const | 475 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo
rdinateSystem) const |
| 465 { | 476 { |
| 466 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 477 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 467 | 478 |
| 468 Vector<char> encodedImage; | 479 Vector<char> encodedImage; |
| 469 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage)) | 480 if (!isValid() || !encodeImage(*context()->bitmap(), mimeType, quality, &enc
odedImage)) |
| 470 return "data:,"; | 481 return "data:,"; |
| 471 | |
| 472 Vector<char> base64Data; | 482 Vector<char> base64Data; |
| 473 base64Encode(encodedImage, base64Data); | 483 base64Encode(encodedImage, base64Data); |
| 474 | 484 |
| 475 return "data:" + mimeType + ";base64," + base64Data; | 485 return "data:" + mimeType + ";base64," + base64Data; |
| 476 } | 486 } |
| 477 | 487 |
| 478 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co
nst double* quality) | 488 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co
nst double* quality) |
| 479 { | 489 { |
| 480 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 490 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 481 | 491 |
| 482 Vector<char> encodedImage; | 492 Vector<char> encodedImage; |
| 483 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) | 493 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) |
| 484 return "data:,"; | 494 return "data:,"; |
| 485 | 495 |
| 486 Vector<char> base64Data; | 496 Vector<char> base64Data; |
| 487 base64Encode(encodedImage, base64Data); | 497 base64Encode(encodedImage, base64Data); |
| 488 | 498 |
| 489 return "data:" + mimeType + ";base64," + base64Data; | 499 return "data:" + mimeType + ";base64," + base64Data; |
| 490 } | 500 } |
| 491 | 501 |
| 492 void ImageBuffer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | 502 void ImageBuffer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
| 493 { | 503 { |
| 494 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); | 504 MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); |
| 495 info.addMember(m_canvas, "canvas"); | 505 info.addMember(m_canvas, "canvas"); |
| 496 info.addMember(m_context, "context"); | 506 info.addMember(m_context, "context"); |
| 497 info.addMember(m_layerBridge, "layerBridge"); | 507 info.addMember(m_layerBridge, "layerBridge"); |
| 498 } | 508 } |
| 499 | 509 |
| 500 } // namespace WebCore | 510 } // namespace WebCore |
| OLD | NEW |