OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "cc/resources/raster_worker_pool.h" | 5 #include "cc/resources/raster_worker_pool.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/debug/trace_event_synthetic_delay.h" | 9 #include "base/debug/trace_event_synthetic_delay.h" |
10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "cc/debug/devtools_instrumentation.h" | 15 #include "cc/debug/devtools_instrumentation.h" |
16 #include "cc/debug/traced_value.h" | 16 #include "cc/debug/traced_value.h" |
17 #include "cc/resources/picture_pile_impl.h" | 17 #include "cc/resources/picture_pile_impl.h" |
18 #include "cc/resources/resource.h" | 18 #include "cc/resources/resource.h" |
19 #include "cc/resources/resource_provider.h" | 19 #include "cc/resources/resource_provider.h" |
20 #include "gpu/command_buffer/client/gles2_interface.h" | 20 #include "gpu/command_buffer/client/gles2_interface.h" |
21 #include "skia/ext/paint_simplifier.h" | 21 #include "skia/ext/paint_simplifier.h" |
22 #include "third_party/skia/include/core/SkBitmap.h" | 22 #include "third_party/skia/include/core/SkBitmap.h" |
23 #include "third_party/skia/include/core/SkPixelRef.h" | 23 #include "third_party/skia/include/core/SkPixelRef.h" |
24 #include "third_party/skia/include/gpu/GrContext.h" | 24 #include "third_party/skia/include/gpu/GrContext.h" |
25 #include "third_party/skia/include/gpu/SkGpuDevice.h" | |
26 | 25 |
27 namespace cc { | 26 namespace cc { |
28 namespace { | 27 namespace { |
29 | 28 |
30 // Subclass of Allocator that takes a suitably allocated pointer and uses | 29 // Subclass of Allocator that takes a suitably allocated pointer and uses |
31 // it as the pixel memory for the bitmap. | 30 // it as the pixel memory for the bitmap. |
32 class IdentityAllocator : public SkBitmap::Allocator { | 31 class IdentityAllocator : public SkBitmap::Allocator { |
33 public: | 32 public: |
34 explicit IdentityAllocator(void* buffer) : buffer_(buffer) {} | 33 explicit IdentityAllocator(void* buffer) : buffer_(buffer) {} |
35 virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE { | 34 virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 picture_pile_(picture_pile), | 88 picture_pile_(picture_pile), |
90 content_rect_(content_rect), | 89 content_rect_(content_rect), |
91 contents_scale_(contents_scale), | 90 contents_scale_(contents_scale), |
92 raster_mode_(raster_mode), | 91 raster_mode_(raster_mode), |
93 tile_resolution_(tile_resolution), | 92 tile_resolution_(tile_resolution), |
94 layer_id_(layer_id), | 93 layer_id_(layer_id), |
95 tile_id_(tile_id), | 94 tile_id_(tile_id), |
96 source_frame_number_(source_frame_number), | 95 source_frame_number_(source_frame_number), |
97 rendering_stats_(rendering_stats), | 96 rendering_stats_(rendering_stats), |
98 reply_(reply), | 97 reply_(reply), |
99 buffer_(NULL), | 98 canvas_(NULL) {} |
100 stride_(0) {} | |
101 | 99 |
102 void RunAnalysisOnThread(unsigned thread_index) { | 100 void RunAnalysisOnThread(unsigned thread_index) { |
103 TRACE_EVENT1("cc", | 101 TRACE_EVENT1("cc", |
104 "RasterWorkerPoolTaskImpl::RunAnalysisOnThread", | 102 "RasterWorkerPoolTaskImpl::RunAnalysisOnThread", |
105 "data", | 103 "data", |
106 TracedValue::FromValue(DataAsValue().release())); | 104 TracedValue::FromValue(DataAsValue().release())); |
107 | 105 |
108 DCHECK(picture_pile_.get()); | 106 DCHECK(picture_pile_.get()); |
109 DCHECK(rendering_stats_); | 107 DCHECK(rendering_stats_); |
110 | 108 |
111 PicturePileImpl* picture_clone = | 109 PicturePileImpl* picture_clone = |
112 picture_pile_->GetCloneForDrawingOnThread(thread_index); | 110 picture_pile_->GetCloneForDrawingOnThread(thread_index); |
113 | 111 |
114 DCHECK(picture_clone); | 112 DCHECK(picture_clone); |
115 | 113 |
116 picture_clone->AnalyzeInRect( | 114 picture_clone->AnalyzeInRect( |
117 content_rect_, contents_scale_, &analysis_, rendering_stats_); | 115 content_rect_, contents_scale_, &analysis_, rendering_stats_); |
118 | 116 |
119 // Record the solid color prediction. | 117 // Record the solid color prediction. |
120 UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed", | 118 UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed", |
121 analysis_.is_solid_color); | 119 analysis_.is_solid_color); |
122 | 120 |
123 // Clear the flag if we're not using the estimator. | 121 // Clear the flag if we're not using the estimator. |
124 analysis_.is_solid_color &= kUseColorEstimator; | 122 analysis_.is_solid_color &= kUseColorEstimator; |
125 } | 123 } |
126 | 124 |
127 void RunRasterOnThread(unsigned thread_index, | 125 void RunRasterOnThread(unsigned thread_index) { |
128 void* buffer, | |
129 const gfx::Size& size, | |
130 int stride) { | |
131 TRACE_EVENT2( | 126 TRACE_EVENT2( |
132 "cc", | 127 "cc", |
133 "RasterWorkerPoolTaskImpl::RunRasterOnThread", | 128 "RasterWorkerPoolTaskImpl::RunRasterOnThread", |
134 "data", | 129 "data", |
135 TracedValue::FromValue(DataAsValue().release()), | 130 TracedValue::FromValue(DataAsValue().release()), |
136 "raster_mode", | 131 "raster_mode", |
137 TracedValue::FromValue(RasterModeAsValue(raster_mode_).release())); | 132 TracedValue::FromValue(RasterModeAsValue(raster_mode_).release())); |
138 | 133 |
139 devtools_instrumentation::ScopedLayerTask raster_task( | 134 devtools_instrumentation::ScopedLayerTask raster_task( |
140 devtools_instrumentation::kRasterTask, layer_id_); | 135 devtools_instrumentation::kRasterTask, layer_id_); |
141 | 136 |
142 DCHECK(picture_pile_.get()); | 137 DCHECK(picture_pile_.get()); |
143 DCHECK(buffer); | 138 Raster(picture_pile_->GetCloneForDrawingOnThread(thread_index)); |
144 | |
145 SkBitmap bitmap; | |
146 switch (resource()->format()) { | |
147 case RGBA_4444: | |
148 // Use the default stride if we will eventually convert this | |
149 // bitmap to 4444. | |
150 bitmap.setConfig( | |
151 SkBitmap::kARGB_8888_Config, size.width(), size.height()); | |
152 bitmap.allocPixels(); | |
153 break; | |
154 case RGBA_8888: | |
155 case BGRA_8888: | |
156 bitmap.setConfig( | |
157 SkBitmap::kARGB_8888_Config, size.width(), size.height(), stride); | |
158 bitmap.setPixels(buffer); | |
159 break; | |
160 case LUMINANCE_8: | |
161 case RGB_565: | |
162 case ETC1: | |
163 NOTREACHED(); | |
164 break; | |
165 } | |
166 | |
167 SkBitmapDevice device(bitmap); | |
168 SkCanvas canvas(&device); | |
169 Raster(picture_pile_->GetCloneForDrawingOnThread(thread_index), &canvas); | |
170 ChangeBitmapConfigIfNeeded(bitmap, buffer); | |
171 } | 139 } |
172 | 140 |
173 // Overridden from internal::Task: | 141 // Overridden from internal::Task: |
174 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE { | 142 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE { |
175 // TODO(alokp): For now run-on-worker-thread implies software rasterization. | 143 // TODO(alokp): For now run-on-worker-thread implies software rasterization. |
176 DCHECK(!use_gpu_rasterization()); | 144 DCHECK(!use_gpu_rasterization()); |
177 RunAnalysisOnThread(thread_index); | 145 RunAnalysisOnThread(thread_index); |
178 if (buffer_ && !analysis_.is_solid_color) | 146 if (canvas_ && !analysis_.is_solid_color) |
179 RunRasterOnThread(thread_index, buffer_, resource()->size(), stride_); | 147 RunRasterOnThread(thread_index); |
180 } | 148 } |
181 | 149 |
182 // Overridden from internal::WorkerPoolTask: | 150 // Overridden from internal::WorkerPoolTask: |
183 virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client) | 151 virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client) |
184 OVERRIDE { | 152 OVERRIDE { |
185 if (use_gpu_rasterization()) | 153 DCHECK(!canvas_); |
186 return; | 154 canvas_ = client->AcquireCanvasForRaster(this); |
187 DCHECK(!buffer_); | |
188 buffer_ = client->AcquireBufferForRaster(this, &stride_); | |
189 } | 155 } |
190 virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client) | 156 virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client) |
191 OVERRIDE { | 157 OVERRIDE { |
192 if (use_gpu_rasterization()) | 158 canvas_ = NULL; |
193 return; | |
194 buffer_ = NULL; | |
195 client->OnRasterCompleted(this, analysis_); | 159 client->OnRasterCompleted(this, analysis_); |
196 } | 160 } |
197 virtual void RunReplyOnOriginThread() OVERRIDE { | 161 virtual void RunReplyOnOriginThread() OVERRIDE { |
198 DCHECK(!buffer_); | 162 DCHECK(!canvas_); |
199 reply_.Run(analysis_, !HasFinishedRunning()); | 163 reply_.Run(analysis_, !HasFinishedRunning()); |
200 } | 164 } |
201 | 165 |
202 // Overridden from internal::RasterWorkerPoolTask: | 166 // Overridden from internal::RasterWorkerPoolTask: |
203 virtual void RunOnOriginThread(ResourceProvider* resource_provider, | 167 virtual void RunOnOriginThread(ResourceProvider* resource_provider, |
204 ContextProvider* context_provider) OVERRIDE { | 168 ContextProvider* context_provider) OVERRIDE { |
205 // TODO(alokp): Use a trace macro to push/pop markers. | 169 // TODO(alokp): Use a trace macro to push/pop markers. |
206 // Using push/pop functions directly incurs cost to evaluate function | 170 // Using push/pop functions directly incurs cost to evaluate function |
207 // arguments even when tracing is disabled. | 171 // arguments even when tracing is disabled. |
208 context_provider->ContextGL()->PushGroupMarkerEXT( | 172 context_provider->ContextGL()->PushGroupMarkerEXT( |
209 0, | 173 0, |
210 base::StringPrintf( | 174 base::StringPrintf( |
211 "Raster-%d-%d-%p", source_frame_number_, layer_id_, tile_id_) | 175 "Raster-%d-%d-%p", source_frame_number_, layer_id_, tile_id_) |
212 .c_str()); | 176 .c_str()); |
213 // TODO(alokp): For now run-on-origin-thread implies gpu rasterization. | 177 // TODO(alokp): For now run-on-origin-thread implies gpu rasterization. |
214 DCHECK(use_gpu_rasterization()); | 178 DCHECK(use_gpu_rasterization()); |
215 ResourceProvider::ScopedWriteLockGL lock(resource_provider, | 179 Raster(picture_pile_); |
216 resource()->id()); | |
217 DCHECK_NE(lock.texture_id(), 0u); | |
218 | |
219 GrBackendTextureDesc desc; | |
220 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | |
221 desc.fWidth = content_rect_.width(); | |
222 desc.fHeight = content_rect_.height(); | |
223 desc.fConfig = ToGrFormat(resource()->format()); | |
224 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | |
225 desc.fTextureHandle = lock.texture_id(); | |
226 | |
227 GrContext* gr_context = context_provider->GrContext(); | |
228 skia::RefPtr<GrTexture> texture = | |
229 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); | |
230 skia::RefPtr<SkGpuDevice> device = | |
231 skia::AdoptRef(SkGpuDevice::Create(texture.get())); | |
232 skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(new SkCanvas(device.get())); | |
233 | |
234 Raster(picture_pile_, canvas.get()); | |
235 context_provider->ContextGL()->PopGroupMarkerEXT(); | 180 context_provider->ContextGL()->PopGroupMarkerEXT(); |
236 } | 181 } |
237 | 182 |
238 protected: | 183 protected: |
239 virtual ~RasterWorkerPoolTaskImpl() { DCHECK(!buffer_); } | 184 virtual ~RasterWorkerPoolTaskImpl() { DCHECK(!canvas_); } |
240 | 185 |
241 private: | 186 private: |
242 scoped_ptr<base::Value> DataAsValue() const { | 187 scoped_ptr<base::Value> DataAsValue() const { |
243 scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); | 188 scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue()); |
244 res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release()); | 189 res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release()); |
245 res->Set("resolution", TileResolutionAsValue(tile_resolution_).release()); | 190 res->Set("resolution", TileResolutionAsValue(tile_resolution_).release()); |
246 res->SetInteger("source_frame_number", source_frame_number_); | 191 res->SetInteger("source_frame_number", source_frame_number_); |
247 res->SetInteger("layer_id", layer_id_); | 192 res->SetInteger("layer_id", layer_id_); |
248 return res.PassAs<base::Value>(); | 193 return res.PassAs<base::Value>(); |
249 } | 194 } |
250 | 195 |
251 static GrPixelConfig ToGrFormat(ResourceFormat format) { | 196 void Raster(PicturePileImpl* picture_pile) { |
252 switch (format) { | |
253 case RGBA_8888: | |
254 return kRGBA_8888_GrPixelConfig; | |
255 case BGRA_8888: | |
256 return kBGRA_8888_GrPixelConfig; | |
257 case RGBA_4444: | |
258 return kRGBA_4444_GrPixelConfig; | |
259 default: | |
260 break; | |
261 } | |
262 DCHECK(false) << "Unsupported resource format."; | |
263 return kSkia8888_GrPixelConfig; | |
264 } | |
265 | |
266 void Raster(PicturePileImpl* picture_pile, SkCanvas* canvas) { | |
267 skia::RefPtr<SkDrawFilter> draw_filter; | 197 skia::RefPtr<SkDrawFilter> draw_filter; |
268 switch (raster_mode_) { | 198 switch (raster_mode_) { |
269 case LOW_QUALITY_RASTER_MODE: | 199 case LOW_QUALITY_RASTER_MODE: |
270 draw_filter = skia::AdoptRef(new skia::PaintSimplifier); | 200 draw_filter = skia::AdoptRef(new skia::PaintSimplifier); |
271 break; | 201 break; |
272 case HIGH_QUALITY_NO_LCD_RASTER_MODE: | 202 case HIGH_QUALITY_NO_LCD_RASTER_MODE: |
273 draw_filter = skia::AdoptRef(new DisableLCDTextFilter); | 203 draw_filter = skia::AdoptRef(new DisableLCDTextFilter); |
274 break; | 204 break; |
275 case HIGH_QUALITY_RASTER_MODE: | 205 case HIGH_QUALITY_RASTER_MODE: |
276 break; | 206 break; |
277 case NUM_RASTER_MODES: | 207 case NUM_RASTER_MODES: |
278 default: | 208 default: |
279 NOTREACHED(); | 209 NOTREACHED(); |
280 } | 210 } |
281 canvas->setDrawFilter(draw_filter.get()); | 211 canvas_->setDrawFilter(draw_filter.get()); |
282 | 212 |
283 base::TimeDelta prev_rasterize_time = | 213 base::TimeDelta prev_rasterize_time = |
284 rendering_stats_->impl_thread_rendering_stats().rasterize_time; | 214 rendering_stats_->impl_thread_rendering_stats().rasterize_time; |
285 | 215 |
286 // Only record rasterization time for highres tiles, because | 216 // Only record rasterization time for highres tiles, because |
287 // lowres tiles are not required for activation and therefore | 217 // lowres tiles are not required for activation and therefore |
288 // introduce noise in the measurement (sometimes they get rasterized | 218 // introduce noise in the measurement (sometimes they get rasterized |
289 // before we draw and sometimes they aren't) | 219 // before we draw and sometimes they aren't) |
290 RenderingStatsInstrumentation* stats = | 220 RenderingStatsInstrumentation* stats = |
291 tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL; | 221 tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL; |
292 picture_pile->RasterToBitmap(canvas, content_rect_, contents_scale_, stats); | 222 picture_pile->RasterToBitmap( |
| 223 canvas_, content_rect_, contents_scale_, stats); |
293 | 224 |
294 if (rendering_stats_->record_rendering_stats()) { | 225 if (rendering_stats_->record_rendering_stats()) { |
295 base::TimeDelta current_rasterize_time = | 226 base::TimeDelta current_rasterize_time = |
296 rendering_stats_->impl_thread_rendering_stats().rasterize_time; | 227 rendering_stats_->impl_thread_rendering_stats().rasterize_time; |
297 HISTOGRAM_CUSTOM_COUNTS( | 228 HISTOGRAM_CUSTOM_COUNTS( |
298 "Renderer4.PictureRasterTimeUS", | 229 "Renderer4.PictureRasterTimeUS", |
299 (current_rasterize_time - prev_rasterize_time).InMicroseconds(), | 230 (current_rasterize_time - prev_rasterize_time).InMicroseconds(), |
300 0, | 231 0, |
301 100000, | 232 100000, |
302 100); | 233 100); |
303 } | 234 } |
304 } | 235 } |
305 | 236 |
306 void ChangeBitmapConfigIfNeeded(const SkBitmap& bitmap, void* buffer) { | |
307 TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::ChangeBitmapConfigIfNeeded"); | |
308 SkBitmap::Config config = SkBitmapConfig(resource()->format()); | |
309 if (bitmap.getConfig() != config) { | |
310 SkBitmap bitmap_dest; | |
311 IdentityAllocator allocator(buffer); | |
312 bitmap.copyTo(&bitmap_dest, config, &allocator); | |
313 // TODO(kaanb): The GL pipeline assumes a 4-byte alignment for the | |
314 // bitmap data. This check will be removed once crbug.com/293728 is fixed. | |
315 CHECK_EQ(0u, bitmap_dest.rowBytes() % 4); | |
316 } | |
317 } | |
318 | |
319 PicturePileImpl::Analysis analysis_; | 237 PicturePileImpl::Analysis analysis_; |
320 scoped_refptr<PicturePileImpl> picture_pile_; | 238 scoped_refptr<PicturePileImpl> picture_pile_; |
321 gfx::Rect content_rect_; | 239 gfx::Rect content_rect_; |
322 float contents_scale_; | 240 float contents_scale_; |
323 RasterMode raster_mode_; | 241 RasterMode raster_mode_; |
324 TileResolution tile_resolution_; | 242 TileResolution tile_resolution_; |
325 int layer_id_; | 243 int layer_id_; |
326 const void* tile_id_; | 244 const void* tile_id_; |
327 int source_frame_number_; | 245 int source_frame_number_; |
328 RenderingStatsInstrumentation* rendering_stats_; | 246 RenderingStatsInstrumentation* rendering_stats_; |
329 const RasterWorkerPool::RasterTask::Reply reply_; | 247 const RasterWorkerPool::RasterTask::Reply reply_; |
330 void* buffer_; | 248 SkCanvas* canvas_; |
331 int stride_; | |
332 | 249 |
333 DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl); | 250 DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl); |
334 }; | 251 }; |
335 | 252 |
336 class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask { | 253 class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask { |
337 public: | 254 public: |
338 ImageDecodeWorkerPoolTaskImpl(SkPixelRef* pixel_ref, | 255 ImageDecodeWorkerPoolTaskImpl(SkPixelRef* pixel_ref, |
339 int layer_id, | 256 int layer_id, |
340 RenderingStatsInstrumentation* rendering_stats, | 257 RenderingStatsInstrumentation* rendering_stats, |
341 const RasterWorkerPool::Task::Reply& reply) | 258 const RasterWorkerPool::Task::Reply& reply) |
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
811 if (decode_it == graph->nodes.end()) | 728 if (decode_it == graph->nodes.end()) |
812 InsertNodeForTask(graph, decode_task, priority, 0u); | 729 InsertNodeForTask(graph, decode_task, priority, 0u); |
813 | 730 |
814 graph->edges.push_back(internal::TaskGraph::Edge(decode_task, raster_task)); | 731 graph->edges.push_back(internal::TaskGraph::Edge(decode_task, raster_task)); |
815 } | 732 } |
816 | 733 |
817 InsertNodeForTask(graph, raster_task, priority, dependencies); | 734 InsertNodeForTask(graph, raster_task, priority, dependencies); |
818 } | 735 } |
819 | 736 |
820 } // namespace cc | 737 } // namespace cc |
OLD | NEW |