Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: Source/core/platform/graphics/skia/ImageBufferSkia.cpp

Issue 16032003: Fixing Canvas2DLayerBridge to handle lost graphics contexts (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Response to senorblanco feedback Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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);
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
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
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
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 RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::create(rect.width( ) * rect.height() * 4);
340 return result.release();
Stephen White 2013/05/28 14:23:10 Nit: I think you could just return the result of U
341 }
335 return getImageData<Unmultiplied>(rect, context(), m_size); 342 return getImageData<Unmultiplied>(rect, context(), m_size);
336 } 343 }
337 344
338 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const 345 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe ct& rect, CoordinateSystem) const
339 { 346 {
347 if (!isValid()) {
348 RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::create(rect.width( ) * rect.height() * 4);
Stephen White 2013/05/28 14:23:10 Same here.
349 return result.release();
350 }
340 return getImageData<Premultiplied>(rect, context(), m_size); 351 return getImageData<Premultiplied>(rect, context(), m_size);
341 } 352 }
342 353
343 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) 354 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
344 { 355 {
356 if (!isValid())
357 return;
358
345 ASSERT(sourceRect.width() > 0); 359 ASSERT(sourceRect.width() > 0);
346 ASSERT(sourceRect.height() > 0); 360 ASSERT(sourceRect.height() > 0);
347 361
348 int originX = sourceRect.x(); 362 int originX = sourceRect.x();
349 int destX = destPoint.x() + sourceRect.x(); 363 int destX = destPoint.x() + sourceRect.x();
350 ASSERT(destX >= 0); 364 ASSERT(destX >= 0);
351 ASSERT(destX < m_size.width()); 365 ASSERT(destX < m_size.width());
352 ASSERT(originX >= 0); 366 ASSERT(originX >= 0);
353 ASSERT(originX < sourceRect.maxX()); 367 ASSERT(originX < sourceRect.maxX());
354 368
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 ASSERT(mimeType == "image/png"); 419 ASSERT(mimeType == "image/png");
406 } 420 }
407 421
408 return true; 422 return true;
409 } 423 }
410 424
411 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const 425 String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo rdinateSystem) const
412 { 426 {
413 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); 427 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
414 428
415 Vector<char> encodedImage;
416 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage))
417 return "data:,";
418
419 Vector<char> base64Data; 429 Vector<char> base64Data;
420 base64Encode(encodedImage, base64Data); 430 if (isValid()) {
431 Vector<char> encodedImage;
432 if (!encodeImage(*context()->bitmap(), mimeType, quality, &encodedImage) )
433 return "data:,";
434 base64Encode(encodedImage, base64Data);
435 }
421 436
422 return "data:" + mimeType + ";base64," + base64Data; 437 return "data:" + mimeType + ";base64," + base64Data;
423 } 438 }
424 439
425 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t 440 void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) cons t
426 { 441 {
427 MemoryClassInfo info(memoryObjectInfo, this); 442 MemoryClassInfo info(memoryObjectInfo, this);
428 info.addMember(m_canvas, "canvas"); 443 info.addMember(m_canvas, "canvas");
429 info.addMember(m_layerBridge, "layerBridge"); 444 info.addMember(m_layerBridge, "layerBridge");
430 } 445 }
431 446
432 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality) 447 String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, co nst double* quality)
433 { 448 {
434 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); 449 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
435 450
436 Vector<char> encodedImage; 451 Vector<char> encodedImage;
437 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) 452 if (!encodeImage(imageData, mimeType, quality, &encodedImage))
438 return "data:,"; 453 return "data:,";
439 454
440 Vector<char> base64Data; 455 Vector<char> base64Data;
441 base64Encode(encodedImage, base64Data); 456 base64Encode(encodedImage, base64Data);
442 457
443 return "data:" + mimeType + ";base64," + base64Data; 458 return "data:" + mimeType + ";base64," + base64Data;
444 } 459 }
445 460
446 } // namespace WebCore 461 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698