| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/raster/gpu_raster_buffer_provider.h" | 5 #include "cc/raster/gpu_raster_buffer_provider.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
| 15 #include "cc/base/histograms.h" | 15 #include "cc/base/histograms.h" |
| 16 #include "cc/playback/image_hijack_canvas.h" | 16 #include "cc/playback/image_hijack_canvas.h" |
| 17 #include "cc/playback/raster_source.h" | 17 #include "cc/playback/raster_source.h" |
| 18 #include "cc/raster/scoped_gpu_raster.h" | 18 #include "cc/raster/scoped_gpu_raster.h" |
| 19 #include "cc/resources/resource.h" | 19 #include "cc/resources/resource.h" |
| 20 #include "gpu/command_buffer/client/gles2_interface.h" | 20 #include "gpu/command_buffer/client/gles2_interface.h" |
| 21 #include "third_party/skia/include/core/SkMultiPictureDraw.h" | 21 #include "third_party/skia/include/core/SkMultiPictureDraw.h" |
| 22 #include "third_party/skia/include/core/SkPictureRecorder.h" | 22 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 23 #include "third_party/skia/include/core/SkSurface.h" | 23 #include "third_party/skia/include/core/SkSurface.h" |
| 24 #include "third_party/skia/include/gpu/GrContext.h" | 24 #include "third_party/skia/include/gpu/GrContext.h" |
| 25 | 25 |
| 26 namespace cc { | 26 namespace cc { |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 static sk_sp<SkPicture> PlaybackToPicture( | 29 static void RasterizeSource( |
| 30 const RasterSource* raster_source, | 30 const RasterSource* raster_source, |
| 31 bool resource_has_previous_content, | 31 bool resource_has_previous_content, |
| 32 const gfx::Size& resource_size, | 32 const gfx::Size& resource_size, |
| 33 const gfx::Rect& raster_full_rect, | 33 const gfx::Rect& raster_full_rect, |
| 34 const gfx::Rect& raster_dirty_rect, | 34 const gfx::Rect& raster_dirty_rect, |
| 35 const gfx::SizeF& scales, | 35 const gfx::SizeF& scales, |
| 36 const RasterSource::PlaybackSettings& playback_settings) { | 36 const RasterSource::PlaybackSettings& playback_settings, |
| 37 // GPU raster doesn't do low res tiles, so should always include images. | 37 ContextProvider* context_provider, |
| 38 DCHECK(!playback_settings.skip_images); | 38 ResourceProvider::ScopedWriteLockGL* resource_lock, |
| 39 bool async_worker_context_enabled, |
| 40 bool use_distance_field_text, |
| 41 int msaa_sample_count) { |
| 42 ScopedGpuRaster gpu_raster(context_provider); |
| 39 | 43 |
| 44 ResourceProvider::ScopedSkSurfaceProvider scoped_surface( |
| 45 context_provider, resource_lock, async_worker_context_enabled, |
| 46 use_distance_field_text, raster_source->CanUseLCDText(), |
| 47 raster_source->HasImpliedColorSpace(), msaa_sample_count); |
| 48 SkSurface* sk_surface = scoped_surface.sk_surface(); |
| 49 // Allocating an SkSurface will fail after a lost context. Pretend we |
| 50 // rasterized, as the contents of the resource don't matter anymore. |
| 51 if (!sk_surface) |
| 52 return; |
| 53 |
| 54 // Playback |
| 40 gfx::Rect playback_rect = raster_full_rect; | 55 gfx::Rect playback_rect = raster_full_rect; |
| 41 if (resource_has_previous_content) { | 56 if (resource_has_previous_content) { |
| 42 playback_rect.Intersect(raster_dirty_rect); | 57 playback_rect.Intersect(raster_dirty_rect); |
| 43 } | 58 } |
| 44 DCHECK(!playback_rect.IsEmpty()) | 59 DCHECK(!playback_rect.IsEmpty()) |
| 45 << "Why are we rastering a tile that's not dirty?"; | 60 << "Why are we rastering a tile that's not dirty?"; |
| 46 | 61 |
| 47 // Log a histogram of the percentage of pixels that were saved due to | 62 // Log a histogram of the percentage of pixels that were saved due to |
| 48 // partial raster. | 63 // partial raster. |
| 49 const char* client_name = GetClientNameForMetrics(); | 64 const char* client_name = GetClientNameForMetrics(); |
| 50 float full_rect_size = raster_full_rect.size().GetArea(); | 65 float full_rect_size = raster_full_rect.size().GetArea(); |
| 51 if (full_rect_size > 0 && client_name) { | 66 if (full_rect_size > 0 && client_name) { |
| 52 float fraction_partial_rastered = | 67 float fraction_partial_rastered = |
| 53 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size; | 68 static_cast<float>(playback_rect.size().GetArea()) / full_rect_size; |
| 54 float fraction_saved = 1.0f - fraction_partial_rastered; | 69 float fraction_saved = 1.0f - fraction_partial_rastered; |
| 55 UMA_HISTOGRAM_PERCENTAGE( | 70 UMA_HISTOGRAM_PERCENTAGE( |
| 56 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu", | 71 base::StringPrintf("Renderer4.%s.PartialRasterPercentageSaved.Gpu", |
| 57 client_name), | 72 client_name), |
| 58 100.0f * fraction_saved); | 73 100.0f * fraction_saved); |
| 59 } | 74 } |
| 60 | 75 |
| 61 // Play back raster_source into temp SkPicture. | 76 raster_source->PlaybackToCanvas(sk_surface->getCanvas(), raster_full_rect, |
| 62 SkPictureRecorder recorder; | 77 playback_rect, scales, playback_settings); |
| 63 SkCanvas* canvas = | |
| 64 recorder.beginRecording(resource_size.width(), resource_size.height()); | |
| 65 canvas->save(); | |
| 66 | |
| 67 // The GPU image decode controller assumes that Skia is done with an image | |
| 68 // when playback is complete. However, in this case, where we play back to a | |
| 69 // picture, we don't actually finish with the images until the picture is | |
| 70 // rasterized later. This can cause lifetime issues in the GPU image decode | |
| 71 // controller. To avoid this, we disable the image hijack canvas (and image | |
| 72 // decode controller) for this playback step, instead enabling it for the | |
| 73 // later picture rasterization. | |
| 74 RasterSource::PlaybackSettings settings = playback_settings; | |
| 75 settings.use_image_hijack_canvas = false; | |
| 76 raster_source->PlaybackToCanvas(canvas, raster_full_rect, playback_rect, | |
| 77 scales, settings); | |
| 78 canvas->restore(); | |
| 79 return recorder.finishRecordingAsPicture(); | |
| 80 } | |
| 81 | |
| 82 static void RasterizePicture(SkPicture* picture, | |
| 83 ContextProvider* context_provider, | |
| 84 ResourceProvider::ScopedWriteLockGL* resource_lock, | |
| 85 bool async_worker_context_enabled, | |
| 86 bool use_distance_field_text, | |
| 87 bool can_use_lcd_text, | |
| 88 bool ignore_resource_color_space, | |
| 89 int msaa_sample_count, | |
| 90 ImageDecodeCache* image_decode_cache, | |
| 91 bool use_image_hijack_canvas) { | |
| 92 ScopedGpuRaster gpu_raster(context_provider); | |
| 93 | |
| 94 ResourceProvider::ScopedSkSurfaceProvider scoped_surface( | |
| 95 context_provider, resource_lock, async_worker_context_enabled, | |
| 96 use_distance_field_text, can_use_lcd_text, ignore_resource_color_space, | |
| 97 msaa_sample_count); | |
| 98 SkSurface* sk_surface = scoped_surface.sk_surface(); | |
| 99 // Allocating an SkSurface will fail after a lost context. Pretend we | |
| 100 // rasterized, as the contents of the resource don't matter anymore. | |
| 101 if (!sk_surface) | |
| 102 return; | |
| 103 | |
| 104 // As we did not use the image hijack canvas during the initial playback to | |
| 105 // |picture| (see PlaybackToPicture), we must enable it here if requested. | |
| 106 SkCanvas* canvas = sk_surface->getCanvas(); | |
| 107 std::unique_ptr<ImageHijackCanvas> hijack_canvas; | |
| 108 if (use_image_hijack_canvas) { | |
| 109 DCHECK(image_decode_cache); | |
| 110 const SkImageInfo& info = canvas->imageInfo(); | |
| 111 hijack_canvas.reset( | |
| 112 new ImageHijackCanvas(info.width(), info.height(), image_decode_cache)); | |
| 113 SkIRect raster_bounds; | |
| 114 canvas->getClipDeviceBounds(&raster_bounds); | |
| 115 hijack_canvas->clipRect(SkRect::MakeFromIRect(raster_bounds)); | |
| 116 hijack_canvas->setMatrix(canvas->getTotalMatrix()); | |
| 117 hijack_canvas->addCanvas(canvas); | |
| 118 | |
| 119 // Replace canvas with our ImageHijackCanvas which is wrapping it. | |
| 120 canvas = hijack_canvas.get(); | |
| 121 } | |
| 122 | |
| 123 SkMultiPictureDraw multi_picture_draw; | |
| 124 multi_picture_draw.add(canvas, picture); | |
| 125 multi_picture_draw.draw(false); | |
| 126 } | 78 } |
| 127 | 79 |
| 128 } // namespace | 80 } // namespace |
| 129 | 81 |
| 130 GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( | 82 GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( |
| 131 GpuRasterBufferProvider* client, | 83 GpuRasterBufferProvider* client, |
| 132 ResourceProvider* resource_provider, | 84 ResourceProvider* resource_provider, |
| 133 ResourceId resource_id, | 85 ResourceId resource_id, |
| 134 bool async_worker_context_enabled, | 86 bool async_worker_context_enabled, |
| 135 bool resource_has_previous_content) | 87 bool resource_has_previous_content) |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 | 206 |
| 255 if (async_worker_context_enabled_) { | 207 if (async_worker_context_enabled_) { |
| 256 // Early out if sync token is invalid. This happens if the compositor | 208 // Early out if sync token is invalid. This happens if the compositor |
| 257 // context was lost before ScheduleTasks was called. | 209 // context was lost before ScheduleTasks was called. |
| 258 if (!sync_token.HasData()) | 210 if (!sync_token.HasData()) |
| 259 return; | 211 return; |
| 260 // Synchronize with compositor. | 212 // Synchronize with compositor. |
| 261 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); | 213 gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); |
| 262 } | 214 } |
| 263 | 215 |
| 264 sk_sp<SkPicture> picture = PlaybackToPicture( | |
| 265 raster_source, resource_has_previous_content, resource_lock->size(), | |
| 266 raster_full_rect, raster_dirty_rect, scales, playback_settings); | |
| 267 | |
| 268 // Turn on distance fields for layers that have ever animated. | 216 // Turn on distance fields for layers that have ever animated. |
| 269 bool use_distance_field_text = | 217 bool use_distance_field_text = |
| 270 use_distance_field_text_ || | 218 use_distance_field_text_ || |
| 271 raster_source->ShouldAttemptToUseDistanceFieldText(); | 219 raster_source->ShouldAttemptToUseDistanceFieldText(); |
| 272 | 220 |
| 273 RasterizePicture(picture.get(), worker_context_provider_, resource_lock, | 221 RasterizeSource(raster_source, resource_has_previous_content, |
| 274 async_worker_context_enabled_, use_distance_field_text, | 222 resource_lock->size(), raster_full_rect, raster_dirty_rect, |
| 275 raster_source->CanUseLCDText(), | 223 scales, playback_settings, worker_context_provider_, |
| 276 raster_source->HasImpliedColorSpace(), msaa_sample_count_, | 224 resource_lock, async_worker_context_enabled_, |
| 277 raster_source->image_decode_cache(), | 225 use_distance_field_text, msaa_sample_count_); |
| 278 playback_settings.use_image_hijack_canvas); | |
| 279 | 226 |
| 280 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); | 227 const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); |
| 281 | 228 |
| 282 // Barrier to sync worker context output to cc context. | 229 // Barrier to sync worker context output to cc context. |
| 283 gl->OrderingBarrierCHROMIUM(); | 230 gl->OrderingBarrierCHROMIUM(); |
| 284 | 231 |
| 285 // Generate sync token after the barrier for cross context synchronization. | 232 // Generate sync token after the barrier for cross context synchronization. |
| 286 gpu::SyncToken resource_sync_token; | 233 gpu::SyncToken resource_sync_token; |
| 287 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData()); | 234 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData()); |
| 288 resource_lock->set_sync_token(resource_sync_token); | 235 resource_lock->set_sync_token(resource_sync_token); |
| 289 resource_lock->set_synchronized(!async_worker_context_enabled_); | 236 resource_lock->set_synchronized(!async_worker_context_enabled_); |
| 290 } | 237 } |
| 291 | 238 |
| 292 } // namespace cc | 239 } // namespace cc |
| OLD | NEW |