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

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: cleanup. tableChanged was wrong - do proper check. Created 5 years, 1 month 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 componentSizes[2].set(size.width(), size.height()); 96 componentSizes[2].set(size.width(), size.height());
97 return true; 97 return true;
98 } 98 }
99 99
100 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame) 100 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame)
101 : m_fullSize(fullSize) 101 : m_fullSize(fullSize)
102 , m_isMultiFrame(isMultiFrame) 102 , m_isMultiFrame(isMultiFrame)
103 , m_decodeFailedAndEmpty(false) 103 , m_decodeFailedAndEmpty(false)
104 , m_decodeCount(0) 104 , m_decodeCount(0)
105 , m_frameCount(0) 105 , m_frameCount(0)
106 , m_decoderCanDecodeToIndex8(false)
106 { 107 {
107 setData(data.get(), allDataReceived); 108 setData(data.get(), allDataReceived);
108 } 109 }
109 110
110 ImageFrameGenerator::~ImageFrameGenerator() 111 ImageFrameGenerator::~ImageFrameGenerator()
111 { 112 {
112 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this); 113 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
113 } 114 }
114 115
115 void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataRec eived) 116 void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataRec eived)
116 { 117 {
117 m_data.setData(data.get(), allDataReceived); 118 m_data.setData(data.get(), allDataReceived);
118 } 119 }
119 120
120 void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataRece ived) 121 void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataRece ived)
121 { 122 {
122 SharedBuffer* buffer = 0; 123 SharedBuffer* buffer = 0;
123 m_data.data(&buffer, allDataReceived); 124 m_data.data(&buffer, allDataReceived);
124 if (buffer) 125 if (buffer)
125 *data = buffer->copy(); 126 *data = buffer->copy();
126 } 127 }
127 128
128 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) 129 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes, SkPMColor ctable[], int* ctableCount)
129 { 130 {
130 // This method is called to populate a discardable memory owned by Skia. 131 // This method is called to populate a discardable memory owned by Skia.
131 132
132 // Prevents concurrent decode or scale operations on the same image data. 133 // Prevents concurrent decode or scale operations on the same image data.
133 MutexLocker lock(m_decodeMutex); 134 MutexLocker lock(m_decodeMutex);
134 135
135 // This implementation does not support scaling so check the requested size. 136 // This implementation does not support scaling so check the requested size.
136 SkISize scaledSize = SkISize::Make(info.width(), info.height()); 137 SkISize scaledSize = SkISize::Make(info.width(), info.height());
137 ASSERT(m_fullSize == scaledSize); 138 ASSERT(m_fullSize == scaledSize);
138 139
139 if (m_decodeFailedAndEmpty) 140 if (m_decodeFailedAndEmpty)
140 return false; 141 return false;
141 142
142 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount); 143 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount);
143 144
144 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes)); 145 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
145 146
146 SkBitmap bitmap = tryToResumeDecode(scaledSize, index); 147 SkBitmap bitmap = tryToResumeDecode(scaledSize, index, info.colorType());
147 if (bitmap.isNull()) 148 if (bitmap.isNull())
148 return false; 149 return false;
149 150
150 // Don't keep the allocator because it contains a pointer to memory 151 // Don't keep the allocator because it contains a pointer to memory
151 // that we do not own. 152 // that we do not own.
152 m_externalAllocator.clear(); 153 m_externalAllocator.clear();
153 154
154 ASSERT(bitmap.width() == scaledSize.width()); 155 ASSERT(bitmap.width() == scaledSize.width());
155 ASSERT(bitmap.height() == scaledSize.height()); 156 ASSERT(bitmap.height() == scaledSize.height());
156 157
158 // If decoder cannot produce requested color type, return false.
159 if (bitmap.colorType() != info.colorType())
160 return false;
161
157 bool result = true; 162 bool result = true;
158 SkAutoLockPixels bitmapLock(bitmap); 163 SkAutoLockPixels bitmapLock(bitmap);
159 // Check to see if decoder has written directly to the memory provided 164 // Check to see if decoder has written directly to the memory provided
160 // by Skia. If not make a copy. 165 // by Skia. If not make a copy.
161 if (bitmap.getPixels() != pixels) 166 if (bitmap.getPixels() != pixels)
162 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ; 167 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ;
168 if (bitmap.colorType() == kIndex_8_SkColorType && ctable && bitmap.getColorT able()) {
169 memcpy(ctable, bitmap.getColorTable()->readColors(), bitmap.getColorTabl e()->count() * sizeof(SkPMColor));
170 }
171 if (ctableCount) {
172 // Based on SkImageGenerator API spec, ctableCount needs to be set ot 0 for other types.
173 *ctableCount = (bitmap.colorType() == kIndex_8_SkColorType && bitmap.get ColorTable())
174 ? bitmap.getColorTable()->count()
175 : 0;
176 }
163 return result; 177 return result;
164 } 178 }
165 179
166 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] , size_t rowBytes[3]) 180 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] , size_t rowBytes[3])
167 { 181 {
168 // This method is called to populate a discardable memory owned by Skia. 182 // This method is called to populate a discardable memory owned by Skia.
169 183
170 // Prevents concurrent decode or scale operations on the same image data. 184 // Prevents concurrent decode or scale operations on the same image data.
171 MutexLocker lock(m_decodeMutex); 185 MutexLocker lock(m_decodeMutex);
172 186
(...skipping 25 matching lines...) Expand all
198 212
199 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize); 213 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize);
200 RELEASE_ASSERT(sizeUpdated); 214 RELEASE_ASSERT(sizeUpdated);
201 215
202 bool yuvDecoded = decoder->decodeToYUV(); 216 bool yuvDecoded = decoder->decodeToYUV();
203 if (yuvDecoded) 217 if (yuvDecoded)
204 setHasAlpha(0, false); // YUV is always opaque 218 setHasAlpha(0, false); // YUV is always opaque
205 return yuvDecoded; 219 return yuvDecoded;
206 } 220 }
207 221
208 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index) 222 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index, SkColorType outputColor)
209 { 223 {
210 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index)); 224 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index));
211 225
212 ImageDecoder* decoder = 0; 226 ImageDecoder* decoder = 0;
213 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); 227 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
214 ASSERT(!resumeDecoding || decoder); 228 ASSERT(!resumeDecoding || decoder);
215 229
216 SkBitmap fullSizeImage; 230 SkBitmap fullSizeImage;
217 bool complete = decode(index, &decoder, &fullSizeImage); 231 bool complete = decode(index, &decoder, &fullSizeImage, outputColor);
218 232
219 if (!decoder) 233 if (!decoder)
220 return SkBitmap(); 234 return SkBitmap();
221 if (index >= m_frameComplete.size()) 235 if (index >= m_frameComplete.size())
222 m_frameComplete.resize(index + 1); 236 m_frameComplete.resize(index + 1);
223 m_frameComplete[index] = complete; 237 m_frameComplete[index] = complete;
224 238
225 // If we are not resuming decoding that means the decoder is freshly 239 // If we are not resuming decoding that means the decoder is freshly
226 // created and we have ownership. If we are resuming decoding then 240 // created and we have ownership. If we are resuming decoding then
227 // the decoder is owned by ImageDecodingStore. 241 // the decoder is owned by ImageDecodingStore.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 MutexLocker lock(m_alphaMutex); 287 MutexLocker lock(m_alphaMutex);
274 if (index >= m_hasAlpha.size()) { 288 if (index >= m_hasAlpha.size()) {
275 const size_t oldSize = m_hasAlpha.size(); 289 const size_t oldSize = m_hasAlpha.size();
276 m_hasAlpha.resize(index + 1); 290 m_hasAlpha.resize(index + 1);
277 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i) 291 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
278 m_hasAlpha[i] = true; 292 m_hasAlpha[i] = true;
279 } 293 }
280 m_hasAlpha[index] = hasAlpha; 294 m_hasAlpha[index] = hasAlpha;
281 } 295 }
282 296
283 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap) 297 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap, SkColorType outputColor)
284 { 298 {
285 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height()); 299 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height());
286 300
287 ASSERT(decoder); 301 ASSERT(decoder);
288 SharedBuffer* data = 0; 302 SharedBuffer* data = 0;
289 bool allDataReceived = false; 303 bool allDataReceived = false;
290 bool newDecoder = false; 304 bool newDecoder = false;
291 m_data.data(&data, &allDataReceived); 305 m_data.data(&data, &allDataReceived);
292 306
293 // Try to create an ImageDecoder if we are not given one. 307 // Try to create an ImageDecoder if we are not given one.
(...skipping 10 matching lines...) Expand all
304 } 318 }
305 319
306 if (!m_isMultiFrame && newDecoder && allDataReceived) { 320 if (!m_isMultiFrame && newDecoder && allDataReceived) {
307 // If we're using an external memory allocator that means we're decoding 321 // If we're using an external memory allocator that means we're decoding
308 // directly into the output memory and we can save one memcpy. 322 // directly into the output memory and we can save one memcpy.
309 ASSERT(m_externalAllocator.get()); 323 ASSERT(m_externalAllocator.get());
310 (*decoder)->setMemoryAllocator(m_externalAllocator.get()); 324 (*decoder)->setMemoryAllocator(m_externalAllocator.get());
311 } 325 }
312 (*decoder)->setData(data, allDataReceived); 326 (*decoder)->setData(data, allDataReceived);
313 327
314 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index); 328 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index, static_cast<ImageF rame::ColorType>(outputColor));
315 // For multi-frame image decoders, we need to know how many frames are 329 // For multi-frame image decoders, we need to know how many frames are
316 // in that image in order to release the decoder when all frames are 330 // in that image in order to release the decoder when all frames are
317 // decoded. frameCount() is reliable only if all data is received and set in 331 // decoded. frameCount() is reliable only if all data is received and set in
318 // decoder, particularly with GIF. 332 // decoder, particularly with GIF.
319 if (allDataReceived) 333 if (allDataReceived)
320 m_frameCount = (*decoder)->frameCount(); 334 m_frameCount = (*decoder)->frameCount();
321 335
322 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder. 336 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
323 (*decoder)->clearCacheExceptFrame(index); 337 (*decoder)->clearCacheExceptFrame(index);
324 (*decoder)->setMemoryAllocator(0); 338 (*decoder)->setMemoryAllocator(0);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 return false; 386 return false;
373 387
374 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. 388 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
375 decoder->setData(data, allDataReceived); 389 decoder->setData(data, allDataReceived);
376 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes); 390 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
377 decoder->setImagePlanes(dummyImagePlanes.release()); 391 decoder->setImagePlanes(dummyImagePlanes.release());
378 392
379 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation); 393 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation);
380 } 394 }
381 395
396 bool ImageFrameGenerator::canDecodeTo(size_t index, SkColorType outputType)
397 {
398 // Skip decoding to get this information but return default.
399 return (outputType == kIndex_8_SkColorType && m_decoderCanDecodeToIndex8) || outputType == kN32_SkColorType;
400 }
401
402
382 } // namespace blink 403 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698