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

Side by Side Diff: Source/core/platform/graphics/ImageBuffer.cpp

Issue 16032003: Fixing Canvas2DLayerBridge to handle lost graphics contexts (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixing gpu_test Canvas2DAllowed Created 7 years, 5 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698