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