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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp

Issue 1460523002: GIF decoding to Index8, unit tests and misusing unit test as benchmark (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Skia:onGetColorType related implementation. Fix part of Leon's review comments. Created 5 years 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 componentSizes[2].set(size.width(), size.height()); 98 componentSizes[2].set(size.width(), size.height());
99 return true; 99 return true;
100 } 100 }
101 101
102 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame) 102 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame)
103 : m_fullSize(fullSize) 103 : m_fullSize(fullSize)
104 , m_isMultiFrame(isMultiFrame) 104 , m_isMultiFrame(isMultiFrame)
105 , m_decodeFailedAndEmpty(false) 105 , m_decodeFailedAndEmpty(false)
106 , m_decodeCount(0) 106 , m_decodeCount(0)
107 , m_frameCount(0) 107 , m_frameCount(0)
108 , m_decoderCanDecodeToIndex8(false)
108 { 109 {
109 setData(data.get(), allDataReceived); 110 setData(data.get(), allDataReceived);
110 } 111 }
111 112
112 ImageFrameGenerator::~ImageFrameGenerator() 113 ImageFrameGenerator::~ImageFrameGenerator()
113 { 114 {
114 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this); 115 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
115 } 116 }
116 117
117 void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataRec eived) 118 void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataRec eived)
118 { 119 {
119 m_data.setData(data.get(), allDataReceived); 120 m_data.setData(data.get(), allDataReceived);
120 } 121 }
121 122
122 void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataRece ived) 123 void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataRece ived)
123 { 124 {
124 SharedBuffer* buffer = 0; 125 SharedBuffer* buffer = 0;
125 m_data.data(&buffer, allDataReceived); 126 m_data.data(&buffer, allDataReceived);
126 if (buffer) 127 if (buffer)
127 *data = buffer->copy(); 128 *data = buffer->copy();
128 } 129 }
129 130
130 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) 131 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount)
131 { 132 {
132 // This method is called to populate a discardable memory owned by Skia. 133 // This method is called to populate a discardable memory owned by Skia.
133 134
134 // Prevents concurrent decode or scale operations on the same image data. 135 // Prevents concurrent decode or scale operations on the same image data.
135 MutexLocker lock(m_decodeMutex); 136 MutexLocker lock(m_decodeMutex);
136 137
137 // This implementation does not support scaling so check the requested size. 138 // This implementation does not support scaling so check the requested size.
138 SkISize scaledSize = SkISize::Make(info.width(), info.height()); 139 SkISize scaledSize = SkISize::Make(info.width(), info.height());
139 ASSERT(m_fullSize == scaledSize); 140 ASSERT(m_fullSize == scaledSize);
140 141
141 if (m_decodeFailedAndEmpty) 142 if (m_decodeFailedAndEmpty)
142 return false; 143 return false;
143 144
144 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount); 145 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount);
145 146
146 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes)); 147 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
147 148
148 SkBitmap bitmap = tryToResumeDecode(scaledSize, index); 149 SkBitmap bitmap = tryToResumeDecode(scaledSize, index, info.colorType());
149 if (bitmap.isNull()) 150 if (bitmap.isNull())
150 return false; 151 return false;
151 152
152 // Don't keep the allocator because it contains a pointer to memory 153 // Don't keep the allocator because it contains a pointer to memory
153 // that we do not own. 154 // that we do not own.
154 m_externalAllocator.clear(); 155 m_externalAllocator.clear();
155 156
156 ASSERT(bitmap.width() == scaledSize.width()); 157 ASSERT(bitmap.width() == scaledSize.width());
157 ASSERT(bitmap.height() == scaledSize.height()); 158 ASSERT(bitmap.height() == scaledSize.height());
158 159
160 // If decoder cannot produce requested color type, return false.
161 if (bitmap.colorType() != info.colorType())
162 return false;
163
159 bool result = true; 164 bool result = true;
160 SkAutoLockPixels bitmapLock(bitmap); 165 SkAutoLockPixels bitmapLock(bitmap);
161 // Check to see if decoder has written directly to the memory provided 166 // Check to see if decoder has written directly to the memory provided
162 // by Skia. If not make a copy. 167 // by Skia. If not make a copy.
163 if (bitmap.getPixels() != pixels) 168 if (bitmap.getPixels() != pixels)
164 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ; 169 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ;
170 if (bitmap.colorType() == kIndex_8_SkColorType && ctable && bitmap.getColorT able()) {
171 memcpy(ctable, bitmap.getColorTable()->readColors(), bitmap.getColorTabl e()->count() * sizeof(SkPMColor));
172 }
173 if (ctableCount) {
174 // Based on SkImageGenerator API spec, ctableCount needs to be set ot 0 for other types.
175 *ctableCount = (bitmap.colorType() == kIndex_8_SkColorType && bitmap.get ColorTable())
176 ? bitmap.getColorTable()->count()
177 : 0;
178 }
165 return result; 179 return result;
166 } 180 }
167 181
168 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] , size_t rowBytes[3]) 182 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] , size_t rowBytes[3])
169 { 183 {
170 // This method is called to populate a discardable memory owned by Skia. 184 // This method is called to populate a discardable memory owned by Skia.
171 185
172 // Prevents concurrent decode or scale operations on the same image data. 186 // Prevents concurrent decode or scale operations on the same image data.
173 MutexLocker lock(m_decodeMutex); 187 MutexLocker lock(m_decodeMutex);
174 188
(...skipping 25 matching lines...) Expand all
200 214
201 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize); 215 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize);
202 RELEASE_ASSERT(sizeUpdated); 216 RELEASE_ASSERT(sizeUpdated);
203 217
204 bool yuvDecoded = decoder->decodeToYUV(); 218 bool yuvDecoded = decoder->decodeToYUV();
205 if (yuvDecoded) 219 if (yuvDecoded)
206 setHasAlpha(0, false); // YUV is always opaque 220 setHasAlpha(0, false); // YUV is always opaque
207 return yuvDecoded; 221 return yuvDecoded;
208 } 222 }
209 223
210 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index) 224 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index, SkColorType outputColor)
211 { 225 {
212 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index)); 226 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index));
213 227
214 ImageDecoder* decoder = 0; 228 ImageDecoder* decoder = 0;
215 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); 229 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
216 ASSERT(!resumeDecoding || decoder); 230 ASSERT(!resumeDecoding || decoder);
217 231
218 SkBitmap fullSizeImage; 232 SkBitmap fullSizeImage;
219 bool complete = decode(index, &decoder, &fullSizeImage); 233 bool complete = decode(index, &decoder, &fullSizeImage, outputColor);
220 234
221 if (!decoder) 235 if (!decoder)
222 return SkBitmap(); 236 return SkBitmap();
223 if (index >= m_frameComplete.size()) 237 if (index >= m_frameComplete.size())
224 m_frameComplete.resize(index + 1); 238 m_frameComplete.resize(index + 1);
225 m_frameComplete[index] = complete; 239 m_frameComplete[index] = complete;
226 240
227 // If we are not resuming decoding that means the decoder is freshly 241 // If we are not resuming decoding that means the decoder is freshly
228 // created and we have ownership. If we are resuming decoding then 242 // created and we have ownership. If we are resuming decoding then
229 // the decoder is owned by ImageDecodingStore. 243 // the decoder is owned by ImageDecodingStore.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 MutexLocker lock(m_alphaMutex); 289 MutexLocker lock(m_alphaMutex);
276 if (index >= m_hasAlpha.size()) { 290 if (index >= m_hasAlpha.size()) {
277 const size_t oldSize = m_hasAlpha.size(); 291 const size_t oldSize = m_hasAlpha.size();
278 m_hasAlpha.resize(index + 1); 292 m_hasAlpha.resize(index + 1);
279 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i) 293 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
280 m_hasAlpha[i] = true; 294 m_hasAlpha[i] = true;
281 } 295 }
282 m_hasAlpha[index] = hasAlpha; 296 m_hasAlpha[index] = hasAlpha;
283 } 297 }
284 298
285 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap) 299 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap, SkColorType outputColor)
286 { 300 {
287 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height()); 301 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height());
288 302
289 ASSERT(decoder); 303 ASSERT(decoder);
290 SharedBuffer* data = 0; 304 SharedBuffer* data = 0;
291 bool allDataReceived = false; 305 bool allDataReceived = false;
292 bool newDecoder = false; 306 bool newDecoder = false;
293 m_data.data(&data, &allDataReceived); 307 m_data.data(&data, &allDataReceived);
294 308
295 // Try to create an ImageDecoder if we are not given one. 309 // Try to create an ImageDecoder if we are not given one.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 return false; 388 return false;
375 389
376 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. 390 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
377 decoder->setData(data, allDataReceived); 391 decoder->setData(data, allDataReceived);
378 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes); 392 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
379 decoder->setImagePlanes(dummyImagePlanes.release()); 393 decoder->setImagePlanes(dummyImagePlanes.release());
380 394
381 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation); 395 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation);
382 } 396 }
383 397
398 bool ImageFrameGenerator::canDecodeTo(size_t index, SkColorType outputType)
399 {
400 if (m_decoderCanDecodeToIndex8) {
401 // Prevents concurrent decode or scale operations on the same image data .
402 MutexLocker lock(m_decodeMutex);
403 ImageDecoder* decoder = 0;
404 const bool decoderExist = ImageDecodingStore::instance().lockDecoder(thi s, m_fullSize, &decoder);
405 ASSERT(!decoderExist || decoder);
406 SharedBuffer* data = 0;
407 bool allDataReceived = false;
408 m_data.data(&data, &allDataReceived);
409 if (!decoderExist) {
410 if (m_imageDecoderFactory)
411 decoder = m_imageDecoderFactory->create().leakPtr();
412 if (!decoder)
413 decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremult iplied, ImageDecoder::GammaAndColorProfileApplied).leakPtr();
414 if (!decoder)
415 return (outputType == kIndex_8_SkColorType);
416 }
417 decoder->setData(data, allDataReceived);
418 bool canDecodeToIndex8 = decoder->canDecodeTo(index, static_cast<ImageFr ame::ColorType>(outputType));
419 decoder->setData(0, false); // Unref SharedBuffer from ImageDecoder.
420 if (decoderExist) {
421 ImageDecodingStore::instance().unlockDecoder(this, decoder);
422 } else {
423 ImageDecodingStore::instance().insertDecoder(this, PassOwnPtr<blink: :ImageDecoder>(adoptPtr(decoder)));
424 }
425 return (canDecodeToIndex8 && (outputType == kIndex_8_SkColorType));
426 }
427 return (outputType == kN32_SkColorType);
428 }
429
430
384 } // namespace blink 431 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698