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

Side by Side Diff: chrome/browser/android/thumbnail/thumbnail_impl.cc

Issue 262543002: android: add ThumbnailCache (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@codec
Patch Set: separate into multiple files Created 6 years, 6 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
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/thumbnail/thumbnail_impl.h"
6
7 #include "base/files/file.h"
8 #include "base/files/file_path.h"
9 #include "cc/resources/ui_resource_bitmap.h"
10 #include "chrome/browser/android/thumbnail/thumbnail_cache.h"
11 #include "third_party/android_opengl/etc1/etc1.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkData.h"
15 #include "third_party/skia/include/core/SkMallocPixelRef.h"
16 #include "third_party/skia/include/core/SkPixelRef.h"
17 #include "ui/gfx/geometry/size_conversions.h"
18
19 namespace {
20
21 const int kCompressedKey = 0xABABABAB;
22 const int kDecompressedKey = 0xCDCDCDCD;
23
24 // ETC1 texture sizes are multiples of four.
25 size_t NextETC1Size(size_t s) {
26 return (s / 4 + (s % 4 ? 1 : 0)) * 4;
27 }
28
29 gfx::Size GetEncodedSize(gfx::Size bitmap_size) {
David Trainor- moved to gerrit 2014/06/17 08:12:11 const gfx::Size&
powei 2014/06/19 23:05:59 Done.
30 return gfx::Size(NextETC1Size(bitmap_size.width()),
31 NextETC1Size(bitmap_size.height()));
32 }
33
34 } // namespace
35
36 ThumbnailImpl::ThumbnailImpl(TabId tab_id,
37 const SkBitmap& bitmap,
38 float scale,
39 ThumbnailImplManager* thumbnail_impl_manager,
40 content::UIResourceProvider* ui_resource_provider)
41 : tab_id_(tab_id),
42 ui_resource_id_(0),
43 thumbnail_impl_manager_(thumbnail_impl_manager),
44 ui_resource_provider_(ui_resource_provider) {
45 DCHECK(ui_resource_provider);
46 SetRawData(bitmap, scale);
47 }
48
49 ThumbnailImpl::~ThumbnailImpl() {
50 CleanupUIResource();
51 }
52
53 void ThumbnailImpl::CleanupUIResource() {
54 DCHECK(ui_resource_provider_);
55 if (ui_resource_id_)
56 ui_resource_provider_->DeleteUIResource(ui_resource_id_);
57 ui_resource_id_ = 0;
58 }
59
60 void ThumbnailImpl::BuildUIResource() {
61 CleanupUIResource();
62 if (raw_data_.empty() && !compressed_data_)
63 return;
64 ui_resource_id_ = ui_resource_provider_->CreateUIResource(this);
65 }
66
67 bool ThumbnailImpl::IsValid() const {
68 return ui_resource_provider_ && scale_ > 0 && !data_size_.IsEmpty() &&
69 !content_size_.IsEmpty();
70 }
71
72 gfx::Size ThumbnailImpl::GetScaledContentSize() const {
73 return gfx::ToRoundedSize(gfx::ScaleSize(content_size_, 1.f / scale_));
74 }
75
76 gfx::SizeF ThumbnailImpl::GetScaledDataSize() const {
77 return gfx::ScaleSize(data_size_, 1.f / scale_);
78 }
79
80 void ThumbnailImpl::Compress(scoped_refptr<ThumbnailImpl> in_thumbnail,
David Trainor- moved to gerrit 2014/06/17 08:12:11 I reviewed this before the actual cache, but why h
powei 2014/06/19 23:05:59 This is just to make this method be more functiona
David Trainor- moved to gerrit 2014/06/25 07:40:16 Could it still act on the same class that's passed
81 scoped_refptr<ThumbnailImpl> out_thumbnail) {
82 SkBitmap raw_data = in_thumbnail->raw_data_;
83 if (raw_data.empty())
84 return;
85
86 SkAutoLockPixels raw_data_lock(raw_data);
87 gfx::Size raw_data_size(raw_data.width(), raw_data.height());
88 DCHECK_EQ(raw_data.config(), SkBitmap::kARGB_8888_Config);
89 size_t pixel_size = 4; // Pixel size is 4 bytes for kARGB_8888_Config.
90 size_t stride = pixel_size * raw_data_size.width();
91
92 gfx::Size encoded_size = GetEncodedSize(raw_data_size);
93 size_t encoded_bytes =
94 etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height());
95 SkImageInfo info = {encoded_size.width(),
96 encoded_size.height(),
97 kUnknown_SkColorType,
98 kUnpremul_SkAlphaType};
99 skia::RefPtr<SkData> etc1_pixel_data = skia::AdoptRef(
100 SkData::NewFromMalloc(new uint8_t[encoded_bytes], encoded_bytes));
101 skia::RefPtr<SkMallocPixelRef> etc1_pixel_ref = skia::AdoptRef(
102 SkMallocPixelRef::NewWithData(info, 0, NULL, etc1_pixel_data.get()));
103
104 etc1_pixel_ref->lockPixels();
105 bool success = etc1_encode_image(
106 reinterpret_cast<unsigned char*>(raw_data.getPixels()),
107 raw_data_size.width(),
108 raw_data_size.height(),
109 pixel_size,
110 stride,
111 reinterpret_cast<unsigned char*>(etc1_pixel_ref->pixels()),
112 encoded_size.width(),
113 encoded_size.height());
114 etc1_pixel_ref->setImmutable();
115 etc1_pixel_ref->unlockPixels();
116 if (success) {
117 out_thumbnail->SetCompressedData(
118 etc1_pixel_ref, in_thumbnail->scale_, raw_data_size);
119 }
120 }
121
122 bool ThumbnailImpl::WriteToFile(scoped_refptr<ThumbnailImpl> thumbnail,
123 base::File& file) {
124 // We assume caller has already initialized the file and will also close it.
125 DCHECK(file.IsValid());
126 DCHECK(thumbnail);
127 DCHECK(thumbnail->compressed_data_);
128
129 thumbnail->compressed_data_->lockPixels();
130 bool success = true;
131 int content_width = thumbnail->content_size_.width();
132 int content_height = thumbnail->content_size_.height();
133 int data_width = thumbnail->data_size_.width();
134 int data_height = thumbnail->data_size_.height();
135
136 if (file.WriteAtCurrentPos(reinterpret_cast<const char*>(&kCompressedKey),
137 sizeof(int)) < 0 ||
138 file.WriteAtCurrentPos(reinterpret_cast<const char*>(&content_width),
139 sizeof(int)) < 0 ||
140 file.WriteAtCurrentPos(reinterpret_cast<const char*>(&content_height),
141 sizeof(int)) < 0 ||
142 file.WriteAtCurrentPos(reinterpret_cast<const char*>(&data_width),
143 sizeof(int)) < 0 ||
144 file.WriteAtCurrentPos(reinterpret_cast<const char*>(&data_height),
145 sizeof(int)) < 0 ||
146 file.WriteAtCurrentPos(reinterpret_cast<const char*>(&thumbnail->scale_),
147 sizeof(float)) < 0) {
148 success = false;
149 }
150
151 size_t compressed_bytes = etc1_get_encoded_data_size(
152 thumbnail->data_size_.width(), thumbnail->data_size_.height());
153
154 if (file.WriteAtCurrentPos(
155 reinterpret_cast<char*>(thumbnail->compressed_data_->pixels()),
156 compressed_bytes) < 0)
157 success = false;
158
159 thumbnail->compressed_data_->unlockPixels();
160 return success;
161 }
162
163 bool ThumbnailImpl::ReadFromFile(base::File& file,
164 scoped_refptr<ThumbnailImpl> thumbnail) {
165 // We assume caller has already initialized the file and will also close it.
166 DCHECK(file.IsValid());
167
168 int key;
169 bool success = true;
170 if (file.ReadAtCurrentPos(reinterpret_cast<char*>(&key), sizeof(int)) < 0 ||
171 key != kCompressedKey)
172 success = false;
173
174 int width, height;
175 if (file.ReadAtCurrentPos(reinterpret_cast<char*>(&width), sizeof(int)) < 0 ||
176 file.ReadAtCurrentPos(reinterpret_cast<char*>(&height), sizeof(int)) < 0)
177 success = false;
178 gfx::Size content_size = gfx::Size(width, height);
David Trainor- moved to gerrit 2014/06/17 08:12:11 gfx::Size content_size(width, height); Same for b
powei 2014/06/19 23:05:59 Done.
179
180 if (file.ReadAtCurrentPos(reinterpret_cast<char*>(&width), sizeof(int)) < 0 ||
181 file.ReadAtCurrentPos(reinterpret_cast<char*>(&height), sizeof(int)) < 0)
182 success = false;
183 gfx::Size data_size = gfx::Size(width, height);
184
185 float scale = 0.f;
186 if (file.ReadAtCurrentPos(reinterpret_cast<char*>(&scale), sizeof(float)) < 0)
187 success = false;
188
189 size_t compressed_bytes =
190 etc1_get_encoded_data_size(data_size.width(), data_size.height());
191
192 SkImageInfo info = {data_size.width(),
193 data_size.height(),
194 kUnknown_SkColorType,
195 kUnpremul_SkAlphaType};
196
197 scoped_ptr<uint8_t[]> data(new uint8_t[compressed_bytes]);
198 if (file.ReadAtCurrentPos(reinterpret_cast<char*>(data.get()),
199 compressed_bytes) < 0)
200 success = false;
201
202 skia::RefPtr<SkData> etc1_pixel_data =
203 skia::AdoptRef(SkData::NewFromMalloc(data.release(), compressed_bytes));
204 skia::RefPtr<SkPixelRef> compressed_data = skia::AdoptRef(
205 SkMallocPixelRef::NewWithData(info, 0, NULL, etc1_pixel_data.get()));
206
207 if (success)
208 thumbnail->SetCompressedData(compressed_data, scale, content_size);
209 return success;
210 }
211
212 scoped_refptr<ThumbnailImpl> ThumbnailImpl::PassDataToNewThumbnail() {
213 scoped_refptr<ThumbnailImpl> new_thumbnail =
214 make_scoped_refptr(new ThumbnailImpl(tab_id_,
215 SkBitmap(),
216 0.f,
217 thumbnail_impl_manager_,
218 ui_resource_provider_));
219 new_thumbnail->raw_data_ = raw_data_;
220 new_thumbnail->compressed_data_ = compressed_data_;
221 new_thumbnail->scale_ = scale_;
222 new_thumbnail->data_size_ = data_size_;
223 new_thumbnail->content_size_ = content_size_;
224
225 // Release this Thumbnail's reference to the data.
226 raw_data_ = SkBitmap();
227 compressed_data_.clear();
228 return new_thumbnail;
229 }
230
231 cc::UIResourceBitmap ThumbnailImpl::GetBitmap(cc::UIResourceId uid,
232 bool resource_lost) {
233 if (!raw_data_.empty()) {
234 DCHECK(!compressed_data_);
235 return cc::UIResourceBitmap(raw_data_);
236 } else if (compressed_data_) {
237 DCHECK(raw_data_.empty());
238 return cc::UIResourceBitmap(compressed_data_, data_size_);
239 }
240
241 // Return a place holder for all other calls to GetBitmap.
242 SkBitmap tiny_bitmap;
243 SkCanvas canvas(tiny_bitmap);
244 tiny_bitmap.setConfig(
245 SkBitmap::kARGB_8888_Config, 1, 1, 0, kOpaque_SkAlphaType);
246 tiny_bitmap.allocPixels();
247 canvas.drawColor(SK_ColorWHITE);
248 tiny_bitmap.setImmutable();
249 return cc::UIResourceBitmap(tiny_bitmap);
250 }
251
252 void ThumbnailImpl::UIResourceIsInvalid() {
253 ui_resource_id_ = 0;
254 if (thumbnail_impl_manager_) {
255 scoped_refptr<ThumbnailImpl> this_thumbnail(this);
256 thumbnail_impl_manager_->InvalidateCachedThumbnail(this_thumbnail);
257 }
258 }
259
260 void ThumbnailImpl::SetCompressedData(skia::RefPtr<SkPixelRef> compressed_data,
261 float scale,
262 const gfx::Size& content_size) {
263 DCHECK(compressed_data);
264 compressed_data_ = compressed_data;
265 raw_data_ = SkBitmap();
266 scale_ = scale;
267 content_size_ = content_size;
268 data_size_ = gfx::Size(compressed_data_->info().width(),
269 compressed_data_->info().height());
270 BuildUIResource();
powei 2014/06/19 23:05:59 Just realized this can be called on the wrong thre
David Trainor- moved to gerrit 2014/06/25 07:40:16 Won't this defeat the purpose of using the UI reso
271 }
272
273 void ThumbnailImpl::SetRawData(SkBitmap bitmap, float scale) {
274 raw_data_ = bitmap;
275 compressed_data_.clear();
276 data_size_ = gfx::Size(bitmap.width(), bitmap.height());
277 content_size_ = data_size_;
278 scale_ = scale;
279 BuildUIResource();
280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698