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 20 matching lines...) Expand all Loading... |
31 */ | 31 */ |
32 | 32 |
33 #include "config.h" | 33 #include "config.h" |
34 #include "platform/graphics/ImageBuffer.h" | 34 #include "platform/graphics/ImageBuffer.h" |
35 | 35 |
36 #include "platform/MIMETypeRegistry.h" | 36 #include "platform/MIMETypeRegistry.h" |
37 #include "platform/geometry/IntRect.h" | 37 #include "platform/geometry/IntRect.h" |
38 #include "platform/graphics/BitmapImage.h" | 38 #include "platform/graphics/BitmapImage.h" |
39 #include "platform/graphics/GraphicsContext.h" | 39 #include "platform/graphics/GraphicsContext.h" |
40 #include "platform/graphics/GraphicsTypes3D.h" | 40 #include "platform/graphics/GraphicsTypes3D.h" |
| 41 #include "platform/graphics/ImageBufferClient.h" |
41 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | 42 #include "platform/graphics/UnacceleratedImageBufferSurface.h" |
42 #include "platform/graphics/gpu/DrawingBuffer.h" | 43 #include "platform/graphics/gpu/DrawingBuffer.h" |
43 #include "platform/graphics/gpu/Extensions3DUtil.h" | 44 #include "platform/graphics/gpu/Extensions3DUtil.h" |
44 #include "platform/graphics/skia/NativeImageSkia.h" | 45 #include "platform/graphics/skia/NativeImageSkia.h" |
45 #include "platform/graphics/skia/SkiaUtils.h" | 46 #include "platform/graphics/skia/SkiaUtils.h" |
46 #include "platform/image-encoders/skia/JPEGImageEncoder.h" | 47 #include "platform/image-encoders/skia/JPEGImageEncoder.h" |
47 #include "platform/image-encoders/skia/PNGImageEncoder.h" | 48 #include "platform/image-encoders/skia/PNGImageEncoder.h" |
48 #include "platform/image-encoders/skia/WEBPImageEncoder.h" | 49 #include "platform/image-encoders/skia/WEBPImageEncoder.h" |
49 #include "public/platform/Platform.h" | 50 #include "public/platform/Platform.h" |
50 #include "public/platform/WebExternalTextureMailbox.h" | 51 #include "public/platform/WebExternalTextureMailbox.h" |
(...skipping 18 matching lines...) Expand all Loading... |
69 PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
cityMode) | 70 PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
cityMode) |
70 { | 71 { |
71 OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSu
rface(size, opacityMode)); | 72 OwnPtr<ImageBufferSurface> surface = adoptPtr(new UnacceleratedImageBufferSu
rface(size, opacityMode)); |
72 if (!surface->isValid()) | 73 if (!surface->isValid()) |
73 return nullptr; | 74 return nullptr; |
74 return adoptPtr(new ImageBuffer(surface.release())); | 75 return adoptPtr(new ImageBuffer(surface.release())); |
75 } | 76 } |
76 | 77 |
77 ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface) | 78 ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface) |
78 : m_surface(surface) | 79 : m_surface(surface) |
| 80 , m_client(0) |
79 { | 81 { |
| 82 m_surface->setImageBuffer(this); |
80 if (m_surface->canvas()) { | 83 if (m_surface->canvas()) { |
81 m_context = adoptPtr(new GraphicsContext(m_surface->canvas())); | 84 m_context = adoptPtr(new GraphicsContext(m_surface->canvas())); |
82 m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque); | 85 m_context->setCertainlyOpaque(m_surface->opacityMode() == Opaque); |
83 m_context->setAccelerated(m_surface->isAccelerated()); | 86 m_context->setAccelerated(m_surface->isAccelerated()); |
84 } | 87 } |
85 } | 88 } |
86 | 89 |
87 ImageBuffer::~ImageBuffer() | 90 ImageBuffer::~ImageBuffer() |
88 { | 91 { |
89 } | 92 } |
90 | 93 |
91 GraphicsContext* ImageBuffer::context() const | 94 GraphicsContext* ImageBuffer::context() const |
92 { | 95 { |
| 96 if (!isSurfaceValid()) |
| 97 return 0; |
93 m_surface->willUse(); | 98 m_surface->willUse(); |
94 ASSERT(m_context.get()); | 99 ASSERT(m_context.get()); |
95 return m_context.get(); | 100 return m_context.get(); |
96 } | 101 } |
97 | 102 |
98 const SkBitmap& ImageBuffer::bitmap() const | 103 const SkBitmap& ImageBuffer::bitmap() const |
99 { | 104 { |
100 m_surface->willUse(); | 105 m_surface->willUse(); |
101 return m_surface->bitmap(); | 106 return m_surface->bitmap(); |
102 } | 107 } |
103 | 108 |
104 bool ImageBuffer::isValid() const | 109 bool ImageBuffer::isSurfaceValid() const |
105 { | 110 { |
106 return m_surface->isValid(); | 111 return m_surface->isValid(); |
107 } | 112 } |
108 | 113 |
| 114 bool ImageBuffer::restoreSurface() const |
| 115 { |
| 116 return m_surface->isValid() || m_surface->restore(); |
| 117 } |
| 118 |
| 119 void ImageBuffer::notifySurfaceInvalid() |
| 120 { |
| 121 if (m_client) |
| 122 m_client->notifySurfaceInvalid(); |
| 123 } |
| 124 |
109 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) | 125 static SkBitmap deepSkBitmapCopy(const SkBitmap& bitmap) |
110 { | 126 { |
111 SkBitmap tmp; | 127 SkBitmap tmp; |
112 if (!bitmap.deepCopyTo(&tmp)) | 128 if (!bitmap.deepCopyTo(&tmp)) |
113 bitmap.copyTo(&tmp, bitmap.colorType()); | 129 bitmap.copyTo(&tmp, bitmap.colorType()); |
114 | 130 |
115 return tmp; | 131 return tmp; |
116 } | 132 } |
117 | 133 |
118 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh
avior) const | 134 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior, ScaleBeh
avior) const |
119 { | 135 { |
120 if (!isValid()) | 136 if (!isSurfaceValid()) |
121 return BitmapImage::create(NativeImageSkia::create()); | 137 return BitmapImage::create(NativeImageSkia::create()); |
122 | 138 |
123 const SkBitmap& bitmap = m_surface->bitmap(); | 139 const SkBitmap& bitmap = m_surface->bitmap(); |
124 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki
ngStore ? deepSkBitmapCopy(bitmap) : bitmap)); | 140 return BitmapImage::create(NativeImageSkia::create(copyBehavior == CopyBacki
ngStore ? deepSkBitmapCopy(bitmap) : bitmap)); |
125 } | 141 } |
126 | 142 |
127 BackingStoreCopy ImageBuffer::fastCopyImageMode() | 143 BackingStoreCopy ImageBuffer::fastCopyImageMode() |
128 { | 144 { |
129 return DontCopyBackingStore; | 145 return DontCopyBackingStore; |
130 } | 146 } |
131 | 147 |
132 blink::WebLayer* ImageBuffer::platformLayer() const | 148 blink::WebLayer* ImageBuffer::platformLayer() const |
133 { | 149 { |
134 return m_surface->layer(); | 150 return m_surface->layer(); |
135 } | 151 } |
136 | 152 |
137 bool ImageBuffer::copyToPlatformTexture(blink::WebGraphicsContext3D* context, Pl
atform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, boo
l premultiplyAlpha, bool flipY) | 153 bool ImageBuffer::copyToPlatformTexture(blink::WebGraphicsContext3D* context, Pl
atform3DObject texture, GLenum internalFormat, GLenum destType, GLint level, boo
l premultiplyAlpha, bool flipY) |
138 { | 154 { |
139 if (!m_surface->isAccelerated() || !platformLayer() || !isValid()) | 155 if (!m_surface->isAccelerated() || !platformLayer() || !isSurfaceValid()) |
140 return false; | 156 return false; |
141 | 157 |
142 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, l
evel)) | 158 if (!Extensions3DUtil::canUseCopyTextureCHROMIUM(internalFormat, destType, l
evel)) |
143 return false; | 159 return false; |
144 | 160 |
145 OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platf
orm::current()->createSharedOffscreenGraphicsContext3DProvider()); | 161 OwnPtr<blink::WebGraphicsContext3DProvider> provider = adoptPtr(blink::Platf
orm::current()->createSharedOffscreenGraphicsContext3DProvider()); |
146 if (!provider) | 162 if (!provider) |
147 return false; | 163 return false; |
148 blink::WebGraphicsContext3D* sharedContext = provider->context3d(); | 164 blink::WebGraphicsContext3D* sharedContext = provider->context3d(); |
149 if (!sharedContext || !sharedContext->makeContextCurrent()) | 165 if (!sharedContext || !sharedContext->makeContextCurrent()) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 Platform3DObject tex = m_surface->getBackingTexture(); | 226 Platform3DObject tex = m_surface->getBackingTexture(); |
211 if (!context3D || !tex) | 227 if (!context3D || !tex) |
212 return false; | 228 return false; |
213 m_surface->invalidateCachedBitmap(); | 229 m_surface->invalidateCachedBitmap(); |
214 return drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA, | 230 return drawingBuffer->copyToPlatformTexture(context3D, tex, GL_RGBA, |
215 GL_UNSIGNED_BYTE, 0, true, false); | 231 GL_UNSIGNED_BYTE, 0, true, false); |
216 } | 232 } |
217 | 233 |
218 void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, cons
t FloatRect& srcRect, CompositeOperator op, blink::WebBlendMode blendMode) | 234 void ImageBuffer::draw(GraphicsContext* context, const FloatRect& destRect, cons
t FloatRect& srcRect, CompositeOperator op, blink::WebBlendMode blendMode) |
219 { | 235 { |
220 if (!isValid()) | 236 if (!isSurfaceValid()) |
221 return; | 237 return; |
222 | 238 |
223 SkBitmap bitmap = m_surface->bitmap(); | 239 SkBitmap bitmap = m_surface->bitmap(); |
224 // For ImageBufferSurface that enables cachedBitmap, Use the cached Bitmap f
or CPU side usage | 240 // For ImageBufferSurface that enables cachedBitmap, Use the cached Bitmap f
or CPU side usage |
225 // if it is available, otherwise generate and use it. | 241 // if it is available, otherwise generate and use it. |
226 if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->ca
chedBitmapEnabled() && m_surface->isValid()) { | 242 if (!context->isAccelerated() && m_surface->isAccelerated() && m_surface->ca
chedBitmapEnabled() && isSurfaceValid()) { |
227 m_surface->updateCachedBitmapIfNeeded(); | 243 m_surface->updateCachedBitmapIfNeeded(); |
228 bitmap = m_surface->cachedBitmap(); | 244 bitmap = m_surface->cachedBitmap(); |
229 } | 245 } |
230 | 246 |
231 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 247 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
232 | 248 |
233 context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespe
ctImageOrientation); | 249 context->drawImage(image.get(), destRect, srcRect, op, blendMode, DoNotRespe
ctImageOrientation); |
234 } | 250 } |
235 | 251 |
236 void ImageBuffer::flush() | 252 void ImageBuffer::flush() |
237 { | 253 { |
238 if (m_surface->canvas()) { | 254 if (m_surface->canvas()) { |
239 m_surface->canvas()->flush(); | 255 m_surface->canvas()->flush(); |
240 } | 256 } |
241 } | 257 } |
242 | 258 |
243 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
, const FloatSize& scale, | 259 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect
, const FloatSize& scale, |
244 const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, bl
ink::WebBlendMode blendMode, const IntSize& repeatSpacing) | 260 const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, bl
ink::WebBlendMode blendMode, const IntSize& repeatSpacing) |
245 { | 261 { |
246 if (!isValid()) | 262 if (!isSurfaceValid()) |
247 return; | 263 return; |
248 | 264 |
249 const SkBitmap& bitmap = m_surface->bitmap(); | 265 const SkBitmap& bitmap = m_surface->bitmap(); |
250 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); | 266 RefPtr<Image> image = BitmapImage::create(NativeImageSkia::create(drawNeedsC
opy(m_context.get(), context) ? deepSkBitmapCopy(bitmap) : bitmap)); |
251 image->drawPattern(context, srcRect, scale, phase, op, destRect, blendMode,
repeatSpacing); | 267 image->drawPattern(context, srcRect, scale, phase, op, destRect, blendMode,
repeatSpacing); |
252 } | 268 } |
253 | 269 |
254 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
lorSpace) | 270 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
lorSpace) |
255 { | 271 { |
256 const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorS
pace, srcColorSpace); | 272 const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorS
pace, srcColorSpace); |
257 if (!lookUpTable) | 273 if (!lookUpTable) |
258 return; | 274 return; |
259 | 275 |
260 // FIXME: Disable color space conversions on accelerated canvases (for now). | 276 // FIXME: Disable color space conversions on accelerated canvases (for now). |
261 if (context()->isAccelerated() || !isValid()) | 277 if (context()->isAccelerated() || !isSurfaceValid()) |
262 return; | 278 return; |
263 | 279 |
264 const SkBitmap& bitmap = m_surface->bitmap(); | 280 const SkBitmap& bitmap = m_surface->bitmap(); |
265 if (bitmap.isNull()) | 281 if (bitmap.isNull()) |
266 return; | 282 return; |
267 | 283 |
268 ASSERT(bitmap.colorType() == kPMColor_SkColorType); | 284 ASSERT(bitmap.colorType() == kPMColor_SkColorType); |
269 IntSize size = m_surface->size(); | 285 IntSize size = m_surface->size(); |
270 SkAutoLockPixels bitmapLock(bitmap); | 286 SkAutoLockPixels bitmapLock(bitmap); |
271 for (int y = 0; y < size.height(); ++y) { | 287 for (int y = 0; y < size.height(); ++y) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 | 324 |
309 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType
: kUnpremul_SkAlphaType; | 325 SkAlphaType alphaType = (multiplied == Premultiplied) ? kPremul_SkAlphaType
: kUnpremul_SkAlphaType; |
310 SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888
_SkColorType, alphaType); | 326 SkImageInfo info = SkImageInfo::Make(rect.width(), rect.height(), kRGBA_8888
_SkColorType, alphaType); |
311 | 327 |
312 context->readPixels(info, result->data(), 4 * rect.width(), rect.x(), rect.y
()); | 328 context->readPixels(info, result->data(), 4 * rect.width(), rect.x(), rect.y
()); |
313 return result.release(); | 329 return result.release(); |
314 } | 330 } |
315 | 331 |
316 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec
t& rect) const | 332 PassRefPtr<Uint8ClampedArray> ImageBuffer::getUnmultipliedImageData(const IntRec
t& rect) const |
317 { | 333 { |
318 if (!isValid()) | 334 if (!isSurfaceValid()) |
319 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); | 335 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); |
320 return getImageData<Unmultiplied>(rect, context(), m_surface->size()); | 336 return getImageData<Unmultiplied>(rect, context(), m_surface->size()); |
321 } | 337 } |
322 | 338 |
323 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe
ct& rect) const | 339 PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe
ct& rect) const |
324 { | 340 { |
325 if (!isValid()) | 341 if (!isSurfaceValid()) |
326 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); | 342 return Uint8ClampedArray::create(rect.width() * rect.height() * 4); |
327 return getImageData<Premultiplied>(rect, context(), m_surface->size()); | 343 return getImageData<Premultiplied>(rect, context(), m_surface->size()); |
328 } | 344 } |
329 | 345 |
330 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) | 346 void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c
onst IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) |
331 { | 347 { |
332 if (!isValid()) | 348 if (!isSurfaceValid()) |
333 return; | 349 return; |
334 | 350 |
335 ASSERT(sourceRect.width() > 0); | 351 ASSERT(sourceRect.width() > 0); |
336 ASSERT(sourceRect.height() > 0); | 352 ASSERT(sourceRect.height() > 0); |
337 | 353 |
338 int originX = sourceRect.x(); | 354 int originX = sourceRect.x(); |
339 int destX = destPoint.x() + sourceRect.x(); | 355 int destX = destPoint.x() + sourceRect.x(); |
340 ASSERT(destX >= 0); | 356 ASSERT(destX >= 0); |
341 ASSERT(destX < m_surface->size().width()); | 357 ASSERT(destX < m_surface->size().width()); |
342 ASSERT(originX >= 0); | 358 ASSERT(originX >= 0); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 } | 397 } |
382 | 398 |
383 return true; | 399 return true; |
384 } | 400 } |
385 | 401 |
386 String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
st | 402 String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
st |
387 { | 403 { |
388 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 404 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
389 | 405 |
390 Vector<char> encodedImage; | 406 Vector<char> encodedImage; |
391 if (!isValid() || !encodeImage(m_surface->bitmap(), mimeType, quality, &enco
dedImage)) | 407 if (!isSurfaceValid() || !encodeImage(m_surface->bitmap(), mimeType, quality
, &encodedImage)) |
392 return "data:,"; | 408 return "data:,"; |
393 Vector<char> base64Data; | 409 Vector<char> base64Data; |
394 base64Encode(encodedImage, base64Data); | 410 base64Encode(encodedImage, base64Data); |
395 | 411 |
396 return "data:" + mimeType + ";base64," + base64Data; | 412 return "data:" + mimeType + ";base64," + base64Data; |
397 } | 413 } |
398 | 414 |
399 String ImageDataToDataURL(const ImageDataBuffer& imageData, const String& mimeTy
pe, const double* quality) | 415 String ImageDataToDataURL(const ImageDataBuffer& imageData, const String& mimeTy
pe, const double* quality) |
400 { | 416 { |
401 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); | 417 ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); |
402 | 418 |
403 Vector<char> encodedImage; | 419 Vector<char> encodedImage; |
404 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) | 420 if (!encodeImage(imageData, mimeType, quality, &encodedImage)) |
405 return "data:,"; | 421 return "data:,"; |
406 | 422 |
407 Vector<char> base64Data; | 423 Vector<char> base64Data; |
408 base64Encode(encodedImage, base64Data); | 424 base64Encode(encodedImage, base64Data); |
409 | 425 |
410 return "data:" + mimeType + ";base64," + base64Data; | 426 return "data:" + mimeType + ";base64," + base64Data; |
411 } | 427 } |
412 | 428 |
413 } // namespace WebCore | 429 } // namespace WebCore |
OLD | NEW |