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

Side by Side Diff: chrome/browser/tab_contents/thumbnail_generator.cc

Issue 144006: Add Linux support for getting the thumbnail and wire into the switcher. (Closed)
Patch Set: For checkin Created 11 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
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/tab_contents/thumbnail_generator.h" 5 #include "chrome/browser/tab_contents/thumbnail_generator.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/histogram.h" 9 #include "base/histogram.h"
10 #include "base/time.h" 10 #include "base/time.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 // Indicates the time that the RWH must be visible for us to update the 52 // Indicates the time that the RWH must be visible for us to update the
53 // thumbnail on it. If the user holds down control enter, there will be a lot 53 // thumbnail on it. If the user holds down control enter, there will be a lot
54 // of backing stores created and destroyed. WE don't want to interfere with 54 // of backing stores created and destroyed. WE don't want to interfere with
55 // that. 55 // that.
56 // 56 //
57 // Any operation that happens within this time of being shown is ignored. 57 // Any operation that happens within this time of being shown is ignored.
58 // This means we won't throw the thumbnail away when the backing store is 58 // This means we won't throw the thumbnail away when the backing store is
59 // painted in this time. 59 // painted in this time.
60 static const int kVisibilitySlopMS = 3000; 60 static const int kVisibilitySlopMS = 3000;
61 61
62 static const char kThumbnailHistogramName[] = "Thumbnail.ComputeMS";
63
62 struct WidgetThumbnail { 64 struct WidgetThumbnail {
63 SkBitmap thumbnail; 65 SkBitmap thumbnail;
64 66
65 // Indicates the last time the RWH was shown and hidden. 67 // Indicates the last time the RWH was shown and hidden.
66 base::TimeTicks last_shown; 68 base::TimeTicks last_shown;
67 base::TimeTicks last_hidden; 69 base::TimeTicks last_hidden;
68 }; 70 };
69 71
70 PropertyAccessor<WidgetThumbnail>* GetThumbnailAccessor() { 72 PropertyAccessor<WidgetThumbnail>* GetThumbnailAccessor() {
71 static PropertyAccessor<WidgetThumbnail> accessor; 73 static PropertyAccessor<WidgetThumbnail> accessor;
72 return &accessor; 74 return &accessor;
73 } 75 }
74 76
75 // Returns the existing WidgetThumbnail for a RVH, or creates a new one and 77 // Returns the existing WidgetThumbnail for a RVH, or creates a new one and
76 // returns that if none exists. 78 // returns that if none exists.
77 WidgetThumbnail* GetDataForHost(RenderWidgetHost* host) { 79 WidgetThumbnail* GetDataForHost(RenderWidgetHost* host) {
78 WidgetThumbnail* wt = GetThumbnailAccessor()->GetProperty( 80 WidgetThumbnail* wt = GetThumbnailAccessor()->GetProperty(
79 host->property_bag()); 81 host->property_bag());
80 if (wt) 82 if (wt)
81 return wt; 83 return wt;
82 84
83 GetThumbnailAccessor()->SetProperty(host->property_bag(), 85 GetThumbnailAccessor()->SetProperty(host->property_bag(),
84 WidgetThumbnail()); 86 WidgetThumbnail());
85 return GetThumbnailAccessor()->GetProperty(host->property_bag()); 87 return GetThumbnailAccessor()->GetProperty(host->property_bag());
86 } 88 }
87 89
90 #if defined(OS_WIN)
91
92 // PlatformDevices/Canvases can't be copied like a regular SkBitmap (at least
93 // on Windows). So the second parameter is the canvas to draw into. It should
94 // be sized to the size of the backing store.
95 void GetBitmapForBackingStore(BackingStore* backing_store,
96 skia::PlatformCanvas* canvas) {
97 HDC dc = canvas->beginPlatformPaint();
98 BitBlt(dc, 0, 0,
99 backing_store->size().width(), backing_store->size().height(),
100 backing_store->hdc(), 0, 0, SRCCOPY);
101 canvas->endPlatformPaint();
102 }
103
104 #endif
105
88 // Creates a downsampled thumbnail for the given backing store. The returned 106 // Creates a downsampled thumbnail for the given backing store. The returned
89 // bitmap will be isNull if there was an error creating it. 107 // bitmap will be isNull if there was an error creating it.
90 SkBitmap GetThumbnailForBackingStore(BackingStore* backing_store) { 108 SkBitmap GetThumbnailForBackingStore(BackingStore* backing_store) {
109 base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now();
110
91 SkBitmap result; 111 SkBitmap result;
92 112
93 // TODO(brettw) write this for other platforms. If you enable this, be sure 113 // TODO(brettw) write this for other platforms. If you enable this, be sure
94 // to also enable the unit tests for the same platform in 114 // to also enable the unit tests for the same platform in
95 // thumbnail_generator_unittest.cc 115 // thumbnail_generator_unittest.cc
96 #if defined(OS_WIN) 116 #if defined(OS_WIN)
97 // Get the bitmap as a Skia object so we can resample it. This is a large 117 // Get the bitmap as a Skia object so we can resample it. This is a large
98 // allocation and we can tolerate failure here, so give up if the allocation 118 // allocation and we can tolerate failure here, so give up if the allocation
99 // fails. 119 // fails.
100 base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now();
101
102 skia::PlatformCanvas temp_canvas; 120 skia::PlatformCanvas temp_canvas;
103 if (!temp_canvas.initialize(backing_store->size().width(), 121 if (!temp_canvas.initialize(backing_store->size().width(),
104 backing_store->size().height(), true)) 122 backing_store->size().height(), true))
105 return SkBitmap(); 123 return result;
106 HDC temp_dc = temp_canvas.beginPlatformPaint(); 124 GetBitmapForBackingStore(backing_store, &temp_canvas);
107 BitBlt(temp_dc,
108 0, 0, backing_store->size().width(), backing_store->size().height(),
109 backing_store->hdc(), 0, 0, SRCCOPY);
110 temp_canvas.endPlatformPaint();
111 125
112 // Get the bitmap out of the canvas and resample it. 126 // Get the bitmap out of the canvas and resample it. It would be nice if this
127 // whole Windows-specific block could be put into a function, but the memory
128 // management wouldn't work out because the bitmap is a PlatformDevice which
129 // can't actually be copied.
113 const SkBitmap& bmp = temp_canvas.getTopPlatformDevice().accessBitmap(false); 130 const SkBitmap& bmp = temp_canvas.getTopPlatformDevice().accessBitmap(false);
131
132 #elif defined(OS_LINUX)
133 SkBitmap bmp = backing_store->PaintRectToBitmap(
134 gfx::Rect(0, 0,
135 backing_store->size().width(), backing_store->size().height()));
136 #endif
137
114 result = skia::ImageOperations::DownsampleByTwoUntilSize( 138 result = skia::ImageOperations::DownsampleByTwoUntilSize(
115 bmp, 139 bmp,
116 kThumbnailWidth, kThumbnailHeight); 140 kThumbnailWidth, kThumbnailHeight);
117 if (bmp.width() == result.width() && bmp.height() == result.height()) { 141
118 // This is a bit subtle. SkBitmaps are refcounted, but the magic ones in 142 #if defined(OS_WIN)
119 // PlatformCanvas can't be ssigned to SkBitmap with proper refcounting. 143 // This is a bit subtle. SkBitmaps are refcounted, but the magic ones in
120 // If the bitmap doesn't change, then the downsampler will return the input 144 // PlatformCanvas on Windows can't be ssigned to SkBitmap with proper
121 // bitmap, which will be the reference to the weird PlatformCanvas one 145 // refcounting. If the bitmap doesn't change, then the downsampler will
122 // insetad of a regular one. To get a regular refcounted bitmap, we need to 146 // return the input bitmap, which will be the reference to the weird
123 // copy it. 147 // PlatformCanvas one insetad of a regular one. To get a regular refcounted
148 // bitmap, we need to copy it.
149 if (bmp.width() == result.width() && bmp.height() == result.height())
124 bmp.copyTo(&result, SkBitmap::kARGB_8888_Config); 150 bmp.copyTo(&result, SkBitmap::kARGB_8888_Config);
125 }
126
127 HISTOGRAM_TIMES("Thumbnail.ComputeOnDestroyMS",
128 base::TimeTicks::Now() - begin_compute_thumbnail);
129 #endif 151 #endif
130 152
153 HISTOGRAM_TIMES(kThumbnailHistogramName,
154 base::TimeTicks::Now() - begin_compute_thumbnail);
131 return result; 155 return result;
132 } 156 }
133 157
134 } // namespace 158 } // namespace
135 159
136 ThumbnailGenerator::ThumbnailGenerator() 160 ThumbnailGenerator::ThumbnailGenerator()
137 : no_timeout_(false) { 161 : no_timeout_(false) {
138 // The BrowserProcessImpl creates this non-lazily. If you add nontrivial 162 // The BrowserProcessImpl creates this non-lazily. If you add nontrivial
139 // stuff here, be sure to convert it to being lazily created. 163 // stuff here, be sure to convert it to being lazily created.
140 // 164 //
(...skipping 17 matching lines...) Expand all
158 NotificationService::AllSources()); 182 NotificationService::AllSources());
159 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED, 183 registrar_.Add(this, NotificationType::RENDER_WIDGET_HOST_DESTROYED,
160 NotificationService::AllSources()); 184 NotificationService::AllSources());
161 } 185 }
162 } 186 }
163 187
164 SkBitmap ThumbnailGenerator::GetThumbnailForRenderer( 188 SkBitmap ThumbnailGenerator::GetThumbnailForRenderer(
165 RenderWidgetHost* renderer) const { 189 RenderWidgetHost* renderer) const {
166 // Return a cached one if we have it and it's still valid. This will only be 190 // Return a cached one if we have it and it's still valid. This will only be
167 // valid when there used to be a backing store, but there isn't now. 191 // valid when there used to be a backing store, but there isn't now.
168 WidgetThumbnail* wt = GetThumbnailAccessor()->GetProperty( 192 WidgetThumbnail* wt = GetDataForHost(renderer);
169 renderer->property_bag()); 193 if (!wt->thumbnail.isNull() &&
170 if (wt && !wt->thumbnail.isNull() &&
171 (no_timeout_ || 194 (no_timeout_ ||
172 base::TimeTicks::Now() - 195 base::TimeTicks::Now() -
173 base::TimeDelta::FromMilliseconds(kVisibilitySlopMS) < wt->last_shown)) 196 base::TimeDelta::FromMilliseconds(kVisibilitySlopMS) < wt->last_shown))
174 return wt->thumbnail; 197 return wt->thumbnail;
175 198
176 BackingStore* backing_store = renderer->GetBackingStore(false); 199 BackingStore* backing_store = renderer->GetBackingStore(false);
177 if (!backing_store) 200 if (!backing_store)
178 return SkBitmap(); 201 return SkBitmap();
179 202
180 // Save this thumbnail in case we need to use it again soon. It will be 203 // Save this thumbnail in case we need to use it again soon. It will be
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 &ThumbnailGenerator::ShownDelayHandler); 345 &ThumbnailGenerator::ShownDelayHandler);
323 } 346 }
324 } 347 }
325 348
326 void ThumbnailGenerator::EraseHostFromShownList(RenderWidgetHost* widget) { 349 void ThumbnailGenerator::EraseHostFromShownList(RenderWidgetHost* widget) {
327 std::vector<RenderWidgetHost*>::iterator found = 350 std::vector<RenderWidgetHost*>::iterator found =
328 std::find(shown_hosts_.begin(), shown_hosts_.end(), widget); 351 std::find(shown_hosts_.begin(), shown_hosts_.end(), widget);
329 if (found != shown_hosts_.end()) 352 if (found != shown_hosts_.end())
330 shown_hosts_.erase(found); 353 shown_hosts_.erase(found);
331 } 354 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/backing_store_x.cc ('k') | chrome/browser/views/tabs/tab_overview_cell.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698