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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 GraphicsContext* ImageBuffer::context() const | 186 GraphicsContext* ImageBuffer::context() const |
| 187 { | 187 { |
| 188 if (m_data.m_layerBridge) { | 188 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 | 189 // 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. | 190 // to be ready. This isn't logically const-correct, hence the cast. |
| 191 const_cast<Canvas2DLayerBridge*>(m_data.m_layerBridge.get())->contextAcq uired(); | 191 const_cast<Canvas2DLayerBridge*>(m_data.m_layerBridge.get())->contextAcq uired(); |
| 192 } | 192 } |
| 193 return m_context.get(); | 193 return m_context.get(); |
| 194 } | 194 } |
| 195 | 195 |
| 196 static bool contextIsValid(const ImageBufferData* data) | |
|
Stephen White
2013/05/24 17:51:01
I think this should be ImageBuffer::isValid(), and
| |
| 197 { | |
| 198 if (data->m_layerBridge) | |
| 199 return const_cast<Canvas2DLayerBridge*>(data->m_layerBridge.get())->cont extIsValid(); | |
| 200 return true; | |
| 201 } | |
| 202 | |
| 196 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) | 203 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) |
| 197 { | 204 { |
| 198 SkBitmap tmp; | 205 SkBitmap tmp; |
| 199 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) | 206 if (!bitmap.deepCopyTo(&tmp, bitmap.config())) |
| 200 bitmap.copyTo(&tmp, bitmap.config()); | 207 bitmap.copyTo(&tmp, bitmap.config()); |
| 201 | 208 |
| 202 return tmp; | 209 return tmp; |
| 203 } | 210 } |
| 204 | 211 |
| 205 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh avior) const | 212 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh avior) const |
| 206 { | 213 { |
| 207 const SkBitmap& bitmap = *context()->bitmap(); | 214 if (contextIsValid(&m_data)) { |
|
Stephen White
2013/05/24 17:51:01
Since this is the exceptional state, this should b
| |
| 208 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. | 215 const SkBitmap& bitmap = *context()->bitmap(); |
| 209 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki ngStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); | 216 // FIXME: Start honoring ScaleBehavior to scale 2x buffers down to 1x. |
| 217 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyB ackingStore ? deepSkBitmapCopy(bitmap) : bitmap, m_resolutionScale)); | |
| 218 } | |
| 219 return BitmapImage::create(NativeImageSkia::create()); | |
| 210 } | 220 } |
| 211 | 221 |
| 212 BackingStoreCopy ImageBuffer::fastCopyImageMode() | 222 BackingStoreCopy ImageBuffer::fastCopyImageMode() |
| 213 { | 223 { |
| 214 return DontCopyBackingStore; | 224 return DontCopyBackingStore; |
| 215 } | 225 } |
| 216 | 226 |
| 217 PlatformLayer* ImageBuffer::platformLayer() const | 227 PlatformLayer* ImageBuffer::platformLayer() const |
| 218 { | 228 { |
| 219 return m_data.m_layerBridge ? m_data.m_layerBridge->layer() : 0; | 229 return m_data.m_layerBridge ? m_data.m_layerBridge->layer() : 0; |
| 220 } | 230 } |
| 221 | 231 |
| 222 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr emultiplyAlpha, bool flipY) | 232 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D& context, Platform3DOb ject texture, GC3Denum internalFormat, GC3Denum destType, GC3Dint level, bool pr emultiplyAlpha, bool flipY) |
| 223 { | 233 { |
| 224 if (!m_data.m_layerBridge || !platformLayer()) | 234 if (!m_data.m_layerBridge || !platformLayer() || !contextIsValid(&m_data)) |
| 225 return false; | 235 return false; |
| 226 | 236 |
| 227 Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture(); | 237 Platform3DObject sourceTexture = m_data.m_layerBridge->backBufferTexture(); |
| 228 | 238 |
| 229 if (!context.makeContextCurrent()) | 239 if (!context.makeContextCurrent()) |
| 230 return false; | 240 return false; |
| 231 | 241 |
| 232 Extensions3D* extensions = context.getExtensions(); | 242 Extensions3D* extensions = context.getExtensions(); |
| 233 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor ts("GL_CHROMIUM_flipy") | 243 if (!extensions->supports("GL_CHROMIUM_copy_texture") || !extensions->suppor ts("GL_CHROMIUM_flipy") |
| 234 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve l)) | 244 || !extensions->canUseCopyTextureCHROMIUM(internalFormat, destType, leve l)) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 254 } | 264 } |
| 255 | 265 |
| 256 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) | 266 static bool drawNeedsCopy(GraphicsContext* src, GraphicsContext* dst) |
| 257 { | 267 { |
| 258 return (src == dst); | 268 return (src == dst); |
| 259 } | 269 } |
| 260 | 270 |
| 261 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con st FloatRect& destRect, const FloatRect& srcRect, | 271 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, con st FloatRect& destRect, const FloatRect& srcRect, |
| 262 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) | 272 CompositeOperator op, BlendMode blendMode, bool useLowQualityScale) |
| 263 { | 273 { |
| 264 const SkBitmap& bitmap = *m_context->bitmap(); | 274 if (contextIsValid(&m_data)) { |
|
Stephen White
2013/05/24 17:51:01
Same here:
if (!isValid())
return;
| |
| 265 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 275 const SkBitmap& bitmap = *m_context->bitmap(); |
| 266 context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blen dMode, DoNotRespectImageOrientation, useLowQualityScale); | 276 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNe edsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 277 context->drawImage(image.get(), styleColorSpace, destRect, srcRect, op, blendMode, DoNotRespectImageOrientation, useLowQualityScale); | |
| 278 } | |
| 267 } | 279 } |
| 268 | 280 |
| 269 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect , const AffineTransform& patternTransform, | 281 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect , const AffineTransform& patternTransform, |
| 270 const FloatPoint& phase, ColorSpace styleColorSpac e, CompositeOperator op, const FloatRect& destRect) | 282 const FloatPoint& phase, ColorSpace styleColorSpac e, CompositeOperator op, const FloatRect& destRect) |
| 271 { | 283 { |
| 272 const SkBitmap& bitmap = *m_context->bitmap(); | 284 if (contextIsValid(&m_data)) { |
|
Stephen White
2013/05/24 17:51:01
Same here (and more places below; I'll stop naggin
| |
| 273 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 285 const SkBitmap& bitmap = *m_context->bitmap(); |
| 274 image->drawPattern(context, srcRect, patternTransform, phase, styleColorSpac e, op, destRect); | 286 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNe edsCopy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
| 287 image->drawPattern(context, srcRect, patternTransform, phase, styleColor Space, op, destRect); | |
| 288 } | |
| 275 } | 289 } |
| 276 | 290 |
| 277 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) | 291 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) |
| 278 { | 292 { |
| 279 // FIXME: Disable color space conversions on accelerated canvases (for now). | 293 // FIXME: Disable color space conversions on accelerated canvases (for now). |
| 280 if (context()->isAccelerated()) | 294 if (context()->isAccelerated() || !contextIsValid(&m_data)) |
| 281 return; | 295 return; |
| 282 | 296 |
| 283 const SkBitmap& bitmap = *context()->bitmap(); | 297 const SkBitmap& bitmap = *context()->bitmap(); |
| 284 if (bitmap.isNull()) | 298 if (bitmap.isNull()) |
| 285 return; | 299 return; |
| 286 | 300 |
| 287 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); | 301 ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); |
| 288 SkAutoLockPixels bitmapLock(bitmap); | 302 SkAutoLockPixels bitmapLock(bitmap); |
| 289 for (int y = 0; y < m_size.height(); ++y) { | 303 for (int y = 0; y < m_size.height(); ++y) { |
| 290 uint32_t* srcRow = bitmap.getAddr32(0, y); | 304 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; | 339 config8888 = SkCanvas::kRGBA_Premul_Config8888; |
| 326 else | 340 else |
| 327 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; | 341 config8888 = SkCanvas::kRGBA_Unpremul_Config8888; |
| 328 | 342 |
| 329 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); | 343 context->readPixels(&destBitmap, rect.x(), rect.y(), config8888); |
| 330 return result.release(); | 344 return result.release(); |
| 331 } | 345 } |
| 332 | 346 |
| 333 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec t& rect, CoordinateSystem) const | 347 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec t& rect, CoordinateSystem) const |
| 334 { | 348 { |
| 335 return getImageData<Unmultiplied>(rect, context(), m_size); | 349 if (contextIsValid(&m_data)) |
| 350 return getImageData<Unmultiplied>(rect, context(), m_size); | |
| 351 RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::create(rect.width() * rect.height() * 4); | |
| 352 return result.release(); | |
| 336 } | 353 } |
| 337 | 354 |
| 338 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const | 355 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const |
| 339 { | 356 { |
| 340 return getImageData<Premultiplied>(rect, context(), m_size); | 357 if (contextIsValid(&m_data)) |
| 358 return getImageData<Premultiplied>(rect, context(), m_size); | |
| 359 RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::create(rect.width() * rect.height() * 4); | |
| 360 return result.release(); | |
| 341 } | 361 } |
| 342 | 362 |
| 343 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) | 363 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) |
| 344 { | 364 { |
| 365 if (!contextIsValid(&m_data)) | |
| 366 return; | |
| 367 | |
| 345 ASSERT(sourceRect.width() > 0); | 368 ASSERT(sourceRect.width() > 0); |
| 346 ASSERT(sourceRect.height() > 0); | 369 ASSERT(sourceRect.height() > 0); |
| 347 | 370 |
| 348 int originX = sourceRect.x(); | 371 int originX = sourceRect.x(); |
| 349 int destX = destPoint.x() + sourceRect.x(); | 372 int destX = destPoint.x() + sourceRect.x(); |
| 350 ASSERT(destX >= 0); | 373 ASSERT(destX >= 0); |
| 351 ASSERT(destX < m_size.width()); | 374 ASSERT(destX < m_size.width()); |
| 352 ASSERT(originX >= 0); | 375 ASSERT(originX >= 0); |
| 353 ASSERT(originX < sourceRect.maxX()); | 376 ASSERT(originX < sourceRect.maxX()); |
| 354 | 377 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 405 ASSERT(mimeType == "image/png"); | 428 ASSERT(mimeType == "image/png"); |
| 406 } | 429 } |
| 407 | 430 |
| 408 return true; | 431 return true; |
| 409 } | 432 } |
| 410 | 433 |
| 411 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const | 434 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const |
| 412 { | 435 { |
| 413 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 436 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 414 | 437 |
| 415 Vector<char> encodedImage; | |
| 416 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage)) | |
| 417 return "data:,"; | |
| 418 | |
| 419 Vector<char> base64Data; | 438 Vector<char> base64Data; |
| 420 base64Encode(encodedImage, base64Data); | 439 if (contextIsValid(&m_data)) { |
| 440 Vector<char> encodedImage; | |
| 441 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage) ) | |
| 442 return "data:,"; | |
| 443 base64Encode(encodedImage, base64Data); | |
| 444 } | |
| 421 | 445 |
| 422 return "data:" + mimeType + ";base64," + base64Data; | 446 return "data:" + mimeType + ";base64," + base64Data; |
| 423 } | 447 } |
| 424 | 448 |
| 425 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t | 449 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t |
| 426 { | 450 { |
| 427 MemoryClassInfo info(memoryObjectInfo, this); | 451 MemoryClassInfo info(memoryObjectInfo, this); |
| 428 info.addMember(m_canvas, "canvas"); | 452 info.addMember(m_canvas, "canvas"); |
| 429 info.addMember(m_layerBridge, "layerBridge"); | 453 info.addMember(m_layerBridge, "layerBridge"); |
| 430 } | 454 } |
| 431 | 455 |
| 432 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality) | 456 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality) |
| 433 { | 457 { |
| 434 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 458 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
| 435 | 459 |
| 436 Vector<char> encodedImage; | 460 Vector<char> encodedImage; |
| 437 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) | 461 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) |
| 438 return "data:,"; | 462 return "data:,"; |
| 439 | 463 |
| 440 Vector<char> base64Data; | 464 Vector<char> base64Data; |
| 441 base64Encode(encodedImage, base64Data); | 465 base64Encode(encodedImage, base64Data); |
| 442 | 466 |
| 443 return "data:" + mimeType + ";base64," + base64Data; | 467 return "data:" + mimeType + ";base64," + base64Data; |
| 444 } | 468 } |
| 445 | 469 |
| 446 } // namespace WebCore | 470 } // namespace WebCore |
| OLD | NEW |