Chromium Code Reviews| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 // the ownership easier to manage. | 66 // the ownership easier to manage. |
| 67 ImageBufferData::ImageBufferData(const IntSize& size) | 67 ImageBufferData::ImageBufferData(const IntSize& size) |
| 68 { | 68 { |
| 69 } | 69 } |
| 70 | 70 |
| 71 static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* d ata, OpacityMode opacityMode) | 71 static SkCanvas* createAcceleratedCanvas(const IntSize& size, ImageBufferData* d ata, OpacityMode opacityMode) |
| 72 { | 72 { |
| 73 RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); | 73 RefPtr<GraphicsContext3D> context3D = SharedGraphicsContext3D::get(); |
| 74 if (!context3D) | 74 if (!context3D) |
| 75 return 0; | 75 return 0; |
| 76 GrContext* gr = context3D->grContext(); | |
| 77 if (!gr) | |
| 78 return 0; | |
| 79 gr->resetContext(); | |
| 80 Canvas2DLayerBridge::OpacityMode bridgeOpacityMode = opacityMode == Opaque ? Canvas2DLayerBridge::Opaque : Canvas2DLayerBridge::NonOpaque; | 76 Canvas2DLayerBridge::OpacityMode bridgeOpacityMode = opacityMode == Opaque ? Canvas2DLayerBridge::Opaque : Canvas2DLayerBridge::NonOpaque; |
| 81 Canvas2DLayerBridge::ThreadMode threadMode = WebKit::Platform::current()->is ThreadedCompositingEnabled() ? Canvas2DLayerBridge::Threaded : Canvas2DLayerBrid ge::SingleThread; | 77 Canvas2DLayerBridge::ThreadMode threadMode = WebKit::Platform::current()->is ThreadedCompositingEnabled() ? Canvas2DLayerBridge::Threaded : Canvas2DLayerBrid ge::SingleThread; |
| 82 SkImage::Info info; | 78 data->m_layerBridge = Canvas2DLayerBridge::create(context3D.release(), size, bridgeOpacityMode, threadMode); |
|
Stephen White
2013/05/31 15:06:18
Thanks for refactoring this!
| |
| 83 info.fWidth = size.width(); | |
| 84 info.fHeight = size.height(); | |
| 85 info.fColorType = SkImage::kPMColor_ColorType; | |
| 86 info.fAlphaType = SkImage::kPremul_AlphaType; | |
| 87 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(context3D->grCont ext(), info)); | |
| 88 if (!surface.get()) | |
| 89 return 0; | |
| 90 SkDeferredCanvas* canvas = new SkDeferredCanvas(surface.get()); | |
| 91 data->m_layerBridge = Canvas2DLayerBridge::create(context3D.release(), canva s, bridgeOpacityMode, threadMode); | |
| 92 // If canvas buffer allocation failed, debug build will have asserted | 79 // If canvas buffer allocation failed, debug build will have asserted |
| 93 // For release builds, we must verify whether the device has a render target | 80 // For release builds, we must verify whether the device has a render target |
| 94 return canvas; | 81 return data->m_layerBridge ? data->m_layerBridge->getCanvas() : 0; |
| 95 } | 82 } |
| 96 | 83 |
| 97 static SkCanvas* createNonPlatformCanvas(const IntSize& size) | 84 static SkCanvas* createNonPlatformCanvas(const IntSize& size) |
| 98 { | 85 { |
| 99 SkAutoTUnref<SkDevice> device(new SkDevice(SkBitmap::kARGB_8888_Config, size .width(), size.height())); | 86 SkAutoTUnref<SkDevice> device(new SkDevice(SkBitmap::kARGB_8888_Config, size .width(), size.height())); |
| 100 SkPixelRef* pixelRef = device->accessBitmap(false).pixelRef(); | 87 SkPixelRef* pixelRef = device->accessBitmap(false).pixelRef(); |
| 101 return pixelRef ? new SkCanvas(device) : 0; | 88 return pixelRef ? new SkCanvas(device) : 0; |
| 102 } | 89 } |
| 103 | 90 |
| 104 PassOwnPtr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, const GraphicsContext* context, b ool hasAlpha) | 91 PassOwnPtr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, const GraphicsContext* context, b ool hasAlpha) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 GraphicsContext* ImageBuffer::context() const | 173 GraphicsContext* ImageBuffer::context() const |
| 187 { | 174 { |
| 188 if (m_data.m_layerBridge) { | 175 if (m_data.m_layerBridge) { |
| 189 // We're using context acquisition as a signal that someone is about to render into our buffer and we need | 176 // We're using context acquisition as a signal that someone is about to render into our buffer and we need |
| 190 // to be ready. This isn't logically const-correct, hence the cast. | 177 // to be ready. This isn't logically const-correct, hence the cast. |
| 191 const_cast<Canvas2DLayerBridge*>(m_data.m_layerBridge.get())->contextAcq uired(); | 178 const_cast<Canvas2DLayerBridge*>(m_data.m_layerBridge.get())->contextAcq uired(); |
| 192 } | 179 } |
| 193 return m_context.get(); | 180 return m_context.get(); |
| 194 } | 181 } |
| 195 | 182 |
| 183 bool ImageBuffer::isValid() const | |
| 184 { | |
| 185 if (m_data.m_layerBridge) | |
| 186 return const_cast<Canvas2DLayerBridge*>(m_data.m_layerBridge.get())->isV alid(); | |
| 187 return true; | |
| 188 } | |
| 189 | |
| 196 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) | 190 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) |
| 197 { | 191 { |
| 198 SkBitmap tmp; | 192 SkBitmap tmp; |
| 199 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) | 193 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) |
| 200 bitmap.copyTo(&tmp, bitmap.config()); | 194 bitmap.copyTo(&tmp, bitmap.config()); |
| 201 | 195 |
| 202 return tmp; | 196 return tmp; |
| 203 } | 197 } |
| 204 | 198 |
| 205 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh avior) const | 199 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh avior) const |
| 206 { | 200 { |
| 201 if (!isValid()) | |
| 202 return BitmapImage::create(NativeImageSkia::create()); | |
| 203 | |
| 207 const SkBitmap& bitmap = *context()->bitmap(); | 204 const SkBitmap& bitmap = *context()->bitmap(); |
| 208 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. | 205 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. |
| 209 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki ngStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); | 206 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki ngStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); |
| 210 } | 207 } |
| 211 | 208 |
| 212 BackingStoreCopy ImageBuffer::fastCopyImageMode() | 209 BackingStoreCopy ImageBuffer::fastCopyImageMode() |
| 213 { | 210 { |
| 214 return DontCopyBackingStore; | 211 return DontCopyBackingStore; |
| 215 } | 212 } |
| 216 | 213 |
| 217 PlatformLayer* ImageBuffer::platformLayer() const | 214 PlatformLayer* ImageBuffer::platformLayer() const |
| 218 { | 215 { |
| 219 return m_data.m_layerBridge ? m_data.m_layerBridge->layer() : 0; | 216 return m_data.m_layerBridge ? m_data.m_layerBridge->layer() : 0; |
| 220 } | 217 } |
| 221 | 218 |
| 222 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr emultiplyAlpha, bool flipY) | 219 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr emultiplyAlpha, bool flipY) |
| 223 { | 220 { |
| 224 if (!m_data.m_layerBridge || !platformLayer()) | 221 if (!m_data.m_layerBridge || !platformLayer() || !isValid()) |
| 225 return false; | 222 return false; |
| 226 | 223 |
| 227 Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture(); | 224 Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture(); |
| 228 | 225 |
| 229 if (!context.makeContextCurrent()) | 226 if (!context.makeContextCurrent()) |
| 230 return false; | 227 return false; |
| 231 | 228 |
| 232 Extensions3D* extensions = context.getExtensions(); | 229 Extensions3D* extensions = context.getExtensions(); |
| 233 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor ts("GL_CHROMIUM_flipy") | 230 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor ts("GL_CHROMIUM_flipy") |
| 234 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve l)) | 231 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve l)) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 254 } | 251 } |
| 255 | 252 |
| 256 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) | 253 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) |
| 257 { | 254 { |
| 258 return (src == dst); | 255 return (src == dst); |
| 259 } | 256 } |
| 260 | 257 |
| 261 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con st FloatRect& destRect, const FloatRect& srcRect, | 258 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con st FloatRect& destRect, const FloatRect& srcRect, |
| 262 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) | 259 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) |
| 263 { | 260 { |
| 261 if (!isValid()) | |
| 262 return; | |
| 263 | |
| 264 const SkBitmap& bitmap = *m_context->bitmap(); | 264 const SkBitmap& bitmap = *m_context->bitmap(); |
| 265 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 265 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 266 context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blen dMode, DoNotRespectImageOrientation, useLowQualityScale); | 266 context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blen dMode, DoNotRespectImageOrientation, useLowQualityScale); |
| 267 } | 267 } |
| 268 | 268 |
| 269 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect , const AffineTransform& patternTransform, | 269 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect , const AffineTransform& patternTransform, |
| 270 const FloatPoint& phase, ColorSpace styleColorSpac e, CompositeOperator op, const FloatRect& destRect) | 270 const FloatPoint& phase, ColorSpace styleColorSpac e, CompositeOperator op, const FloatRect& destRect) |
| 271 { | 271 { |
| 272 if (!isValid()) | |
| 273 return; | |
| 274 | |
| 272 const SkBitmap& bitmap = *m_context->bitmap(); | 275 const SkBitmap& bitmap = *m_context->bitmap(); |
| 273 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 276 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 274 image->drawPattern(context, srcRect, patternTransform, phase, styleColorSpac e, op, destRect); | 277 image->drawPattern(context, srcRect, patternTransform, phase, styleColorSpac e, op, destRect); |
| 275 } | 278 } |
| 276 | 279 |
| 277 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) | 280 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) |
| 278 { | 281 { |
| 279 // FIXME: Disable color space conversions on accelerated canvases (for now). | 282 // FIXME: Disable color space conversions on accelerated canvases (for now). |
| 280 if (context()->isAccelerated()) | 283 if (context()->isAccelerated() || !isValid()) |
| 281 return; | 284 return; |
| 282 | 285 |
| 283 const SkBitmap& bitmap = *context()->bitmap(); | 286 const SkBitmap& bitmap = *context()->bitmap(); |
| 284 if (bitmap.isNull()) | 287 if (bitmap.isNull()) |
| 285 return; | 288 return; |
| 286 | 289 |
| 287 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); | 290 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| 288 SkAutoLockPixels bitmapLock(bitmap); | 291 SkAutoLockPixels bitmapLock(bitmap); |
| 289 for (int y = 0; y < m_size.height(); ++y) { | 292 for (int y = 0; y < m_size.height(); ++y) { |
| 290 uint32_t* srcRow = bitmap.getAddr32(0, y); | 293 uint32_t* srcRow = bitmap.getAddr32(0, y); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 config8888 = SkCanvas::kRGBA_Premul_Config8888; | 328 config8888 = SkCanvas::kRGBA_Premul_Config8888; |
| 326 else | 329 else |
| 327 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; | 330 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; |
| 328 | 331 |
| 329 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); | 332 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); |
| 330 return result.release(); | 333 return result.release(); |
| 331 } | 334 } |
| 332 | 335 |
| 333 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec t& rect, CoordinateSystem) const | 336 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec t& rect, CoordinateSystem) const |
| 334 { | 337 { |
| 338 if (!isValid()) | |
| 339 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); | |
| 335 return getImageData<Unmultiplied>(rect, context(), m_size); | 340 return getImageData<Unmultiplied>(rect, context(), m_size); |
| 336 } | 341 } |
| 337 | 342 |
| 338 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const | 343 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const |
| 339 { | 344 { |
| 345 if (!isValid()) | |
| 346 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); | |
| 340 return getImageData<Premultiplied>(rect, context(), m_size); | 347 return getImageData<Premultiplied>(rect, context(), m_size); |
| 341 } | 348 } |
| 342 | 349 |
| 343 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) | 350 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) |
| 344 { | 351 { |
| 352 if (!isValid()) | |
| 353 return; | |
| 354 | |
| 345 ASSERT(sourceRect.width() > 0); | 355 ASSERT(sourceRect.width() > 0); |
| 346 ASSERT(sourceRect.height() > 0); | 356 ASSERT(sourceRect.height() > 0); |
| 347 | 357 |
| 348 int originX = sourceRect.x(); | 358 int originX = sourceRect.x(); |
| 349 int destX = destPoint.x() + sourceRect.x(); | 359 int destX = destPoint.x() + sourceRect.x(); |
| 350 ASSERT(destX >= 0); | 360 ASSERT(destX >= 0); |
| 351 ASSERT(destX < m_size.width()); | 361 ASSERT(destX < m_size.width()); |
| 352 ASSERT(originX >= 0); | 362 ASSERT(originX >= 0); |
| 353 ASSERT(originX < sourceRect.maxX()); | 363 ASSERT(originX < sourceRect.maxX()); |
| 354 | 364 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 ASSERT(mimeType == "image/png"); | 415 ASSERT(mimeType == "image/png"); |
| 406 } | 416 } |
| 407 | 417 |
| 408 return true; | 418 return true; |
| 409 } | 419 } |
| 410 | 420 |
| 411 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const | 421 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const |
| 412 { | 422 { |
| 413 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 423 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 414 | 424 |
| 415 Vector<char> encodedImage; | |
| 416 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage)) | |
| 417 return "data:,"; | |
| 418 | |
| 419 Vector<char> base64Data; | 425 Vector<char> base64Data; |
| 420 base64Encode(encodedImage, base64Data); | 426 if (isValid()) { |
| 427 Vector<char> encodedImage; | |
| 428 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage) ) | |
| 429 return "data:,"; | |
| 430 base64Encode(encodedImage, base64Data); | |
| 431 } | |
| 421 | 432 |
| 422 return "data:" + mimeType + ";base64," + base64Data; | 433 return "data:" + mimeType + ";base64," + base64Data; |
| 423 } | 434 } |
| 424 | 435 |
| 425 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t | 436 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t |
| 426 { | 437 { |
| 427 MemoryClassInfo info(memoryObjectInfo, this); | 438 MemoryClassInfo info(memoryObjectInfo, this); |
| 428 info.addMember(m_canvas, "canvas"); | 439 info.addMember(m_canvas, "canvas"); |
| 429 info.addMember(m_layerBridge, "layerBridge"); | 440 info.addMember(m_layerBridge, "layerBridge"); |
| 430 } | 441 } |
| 431 | 442 |
| 432 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality) | 443 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality) |
| 433 { | 444 { |
| 434 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 445 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 435 | 446 |
| 436 Vector<char> encodedImage; | 447 Vector<char> encodedImage; |
| 437 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) | 448 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) |
| 438 return "data:,"; | 449 return "data:,"; |
| 439 | 450 |
| 440 Vector<char> base64Data; | 451 Vector<char> base64Data; |
| 441 base64Encode(encodedImage, base64Data); | 452 base64Encode(encodedImage, base64Data); |
| 442 | 453 |
| 443 return "data:" + mimeType + ";base64," + base64Data; | 454 return "data:" + mimeType + ";base64," + base64Data; |
| 444 } | 455 } |
| 445 | 456 |
| 446 } // namespace WebCore | 457 } // namespace WebCore |
| OLD | NEW |