| 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/trace_event/trace_event.h" |   13 #include "base/trace_event/trace_event.h" | 
|   14 #include "cc/playback/raster_source.h" |   14 #include "cc/playback/raster_source.h" | 
|   15 #include "cc/raster/gpu_rasterizer.h" |  | 
|   16 #include "cc/raster/scoped_gpu_raster.h" |   15 #include "cc/raster/scoped_gpu_raster.h" | 
|   17 #include "cc/resources/resource.h" |   16 #include "cc/resources/resource.h" | 
|   18 #include "gpu/command_buffer/client/gles2_interface.h" |   17 #include "gpu/command_buffer/client/gles2_interface.h" | 
|   19 #include "third_party/skia/include/core/SkMultiPictureDraw.h" |   18 #include "third_party/skia/include/core/SkMultiPictureDraw.h" | 
|   20 #include "third_party/skia/include/core/SkPictureRecorder.h" |   19 #include "third_party/skia/include/core/SkPictureRecorder.h" | 
|   21 #include "third_party/skia/include/core/SkSurface.h" |   20 #include "third_party/skia/include/core/SkSurface.h" | 
|   22 #include "third_party/skia/include/gpu/GrContext.h" |   21 #include "third_party/skia/include/gpu/GrContext.h" | 
|   23  |   22  | 
|   24 namespace cc { |   23 namespace cc { | 
|   25 namespace { |   24 namespace { | 
|   26  |   25  | 
|   27 class RasterBufferImpl : public RasterBuffer { |   26 static sk_sp<SkPicture> PlaybackToPicture( | 
|   28  public: |   27     const RasterSource* raster_source, | 
|   29   RasterBufferImpl(GpuRasterizer* rasterizer, |   28     bool resource_has_previous_content, | 
|   30                    const Resource* resource, |   29     const gfx::Size& resource_size, | 
|   31                    uint64_t resource_content_id, |   30     const gfx::Rect& raster_full_rect, | 
|   32                    uint64_t previous_content_id) |   31     const gfx::Rect& raster_dirty_rect, | 
|   33       : rasterizer_(rasterizer), |   32     float scale, | 
|   34         lock_(rasterizer->resource_provider(), resource->id()), |   33     const RasterSource::PlaybackSettings& playback_settings) { | 
|   35         resource_has_previous_content_( |   34   // GPU raster doesn't do low res tiles, so should always include images. | 
|   36             resource_content_id && resource_content_id == previous_content_id) { |   35   DCHECK(!playback_settings.skip_images); | 
 |   36  | 
 |   37   gfx::Rect playback_rect = raster_full_rect; | 
 |   38   if (resource_has_previous_content) { | 
 |   39     playback_rect.Intersect(raster_dirty_rect); | 
|   37   } |   40   } | 
 |   41   DCHECK(!playback_rect.IsEmpty()) | 
 |   42       << "Why are we rastering a tile that's not dirty?"; | 
|   38  |   43  | 
|   39   // Overridden from RasterBuffer: |   44   // Play back raster_source into temp SkPicture. | 
|   40   void Playback( |   45   SkPictureRecorder recorder; | 
|   41       const RasterSource* raster_source, |   46   const int flags = SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag; | 
|   42       const gfx::Rect& raster_full_rect, |   47   sk_sp<SkCanvas> canvas = sk_ref_sp(recorder.beginRecording( | 
|   43       const gfx::Rect& raster_dirty_rect, |   48       resource_size.width(), resource_size.height(), NULL, flags)); | 
|   44       uint64_t new_content_id, |   49   canvas->save(); | 
|   45       float scale, |   50   raster_source->PlaybackToCanvas(canvas.get(), raster_full_rect, playback_rect, | 
|   46       const RasterSource::PlaybackSettings& playback_settings) override { |   51                                   scale, playback_settings); | 
|   47     TRACE_EVENT0("cc", "GpuRasterBuffer::Playback"); |   52   canvas->restore(); | 
|   48     // GPU raster doesn't do low res tiles, so should always include images. |   53   return recorder.finishRecordingAsPicture(); | 
|   49     DCHECK(!playback_settings.skip_images); |   54 } | 
|   50  |   55  | 
|   51     ContextProvider::ScopedContextLock scoped_context( |   56 static void RasterizePicture(SkPicture* picture, | 
|   52         rasterizer_->worker_context_provider()); |   57                              ContextProvider* context_provider, | 
 |   58                              ResourceProvider::ScopedWriteLockGL* resource_lock, | 
 |   59                              bool async_worker_context_enabled, | 
 |   60                              bool use_distance_field_text, | 
 |   61                              bool can_use_lcd_text, | 
 |   62                              int msaa_sample_count) { | 
 |   63   ScopedGpuRaster gpu_raster(context_provider); | 
|   53  |   64  | 
|   54     gfx::Rect playback_rect = raster_full_rect; |   65   ResourceProvider::ScopedSkSurfaceProvider scoped_surface( | 
|   55     if (resource_has_previous_content_) { |   66       context_provider, resource_lock, async_worker_context_enabled, | 
|   56       playback_rect.Intersect(raster_dirty_rect); |   67       use_distance_field_text, can_use_lcd_text, msaa_sample_count); | 
|   57     } |   68   SkSurface* sk_surface = scoped_surface.sk_surface(); | 
|   58     DCHECK(!playback_rect.IsEmpty()) |   69   // Allocating an SkSurface will fail after a lost context.  Pretend we | 
|   59         << "Why are we rastering a tile that's not dirty?"; |   70   // rasterized, as the contents of the resource don't matter anymore. | 
 |   71   if (!sk_surface) | 
 |   72     return; | 
|   60  |   73  | 
|   61     // TODO(danakj): Implement partial raster with raster_dirty_rect. |   74   SkMultiPictureDraw multi_picture_draw; | 
|   62     // Rasterize source into resource. |   75   multi_picture_draw.add(sk_surface->getCanvas(), picture); | 
|   63     rasterizer_->RasterizeSource(&lock_, raster_source, raster_full_rect, |   76   multi_picture_draw.draw(false); | 
|   64                                  playback_rect, scale, playback_settings); |   77 } | 
|   65  |  | 
|   66     gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); |  | 
|   67     const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); |  | 
|   68  |  | 
|   69     // Barrier to sync worker context output to cc context. |  | 
|   70     gl->OrderingBarrierCHROMIUM(); |  | 
|   71  |  | 
|   72     // Generate sync token after the barrier for cross context synchronization. |  | 
|   73     gpu::SyncToken sync_token; |  | 
|   74     gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); |  | 
|   75     lock_.UpdateResourceSyncToken(sync_token); |  | 
|   76   } |  | 
|   77  |  | 
|   78  private: |  | 
|   79   GpuRasterizer* rasterizer_; |  | 
|   80   ResourceProvider::ScopedWriteLockGr lock_; |  | 
|   81   bool resource_has_previous_content_; |  | 
|   82  |  | 
|   83   DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); |  | 
|   84 }; |  | 
|   85  |   78  | 
|   86 }  // namespace |   79 }  // namespace | 
|   87  |   80  | 
 |   81 GpuRasterBufferProvider::RasterBufferImpl::RasterBufferImpl( | 
 |   82     GpuRasterBufferProvider* client, | 
 |   83     ResourceProvider* resource_provider, | 
 |   84     ResourceId resource_id, | 
 |   85     bool async_worker_context_enabled, | 
 |   86     bool resource_has_previous_content) | 
 |   87     : client_(client), | 
 |   88       lock_(resource_provider, resource_id, async_worker_context_enabled), | 
 |   89       resource_has_previous_content_(resource_has_previous_content) { | 
 |   90   client_->pending_raster_buffers_.insert(this); | 
 |   91 } | 
 |   92  | 
 |   93 GpuRasterBufferProvider::RasterBufferImpl::~RasterBufferImpl() { | 
 |   94   client_->pending_raster_buffers_.erase(this); | 
 |   95 } | 
 |   96  | 
 |   97 void GpuRasterBufferProvider::RasterBufferImpl::Playback( | 
 |   98     const RasterSource* raster_source, | 
 |   99     const gfx::Rect& raster_full_rect, | 
 |  100     const gfx::Rect& raster_dirty_rect, | 
 |  101     uint64_t new_content_id, | 
 |  102     float scale, | 
 |  103     const RasterSource::PlaybackSettings& playback_settings) { | 
 |  104   TRACE_EVENT0("cc", "GpuRasterBuffer::Playback"); | 
 |  105   client_->PlaybackOnWorkerThread(&lock_, sync_token_, | 
 |  106                                   resource_has_previous_content_, raster_source, | 
 |  107                                   raster_full_rect, raster_dirty_rect, | 
 |  108                                   new_content_id, scale, playback_settings); | 
 |  109 } | 
 |  110  | 
|   88 GpuRasterBufferProvider::GpuRasterBufferProvider( |  111 GpuRasterBufferProvider::GpuRasterBufferProvider( | 
|   89     ContextProvider* compositor_context_provider, |  112     ContextProvider* compositor_context_provider, | 
|   90     ContextProvider* worker_context_provider, |  113     ContextProvider* worker_context_provider, | 
|   91     ResourceProvider* resource_provider, |  114     ResourceProvider* resource_provider, | 
|   92     bool use_distance_field_text, |  115     bool use_distance_field_text, | 
|   93     int gpu_rasterization_msaa_sample_count) |  116     int gpu_rasterization_msaa_sample_count, | 
 |  117     bool async_worker_context_enabled) | 
|   94     : compositor_context_provider_(compositor_context_provider), |  118     : compositor_context_provider_(compositor_context_provider), | 
|   95       rasterizer_(new GpuRasterizer(worker_context_provider, |  119       worker_context_provider_(worker_context_provider), | 
|   96                                     resource_provider, |  120       resource_provider_(resource_provider), | 
|   97                                     use_distance_field_text, |  121       use_distance_field_text_(use_distance_field_text), | 
|   98                                     gpu_rasterization_msaa_sample_count)) { |  122       msaa_sample_count_(gpu_rasterization_msaa_sample_count), | 
|   99   DCHECK(compositor_context_provider_); |  123       async_worker_context_enabled_(async_worker_context_enabled) { | 
 |  124   DCHECK(compositor_context_provider); | 
 |  125   DCHECK(worker_context_provider); | 
|  100 } |  126 } | 
|  101  |  127  | 
|  102 GpuRasterBufferProvider::~GpuRasterBufferProvider() {} |  128 GpuRasterBufferProvider::~GpuRasterBufferProvider() { | 
 |  129   DCHECK(pending_raster_buffers_.empty()); | 
 |  130 } | 
|  103  |  131  | 
|  104 std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster( |  132 std::unique_ptr<RasterBuffer> GpuRasterBufferProvider::AcquireBufferForRaster( | 
|  105     const Resource* resource, |  133     const Resource* resource, | 
|  106     uint64_t resource_content_id, |  134     uint64_t resource_content_id, | 
|  107     uint64_t previous_content_id) { |  135     uint64_t previous_content_id) { | 
|  108   return std::unique_ptr<RasterBuffer>(new RasterBufferImpl( |  136   bool resource_has_previous_content = | 
|  109       rasterizer_.get(), resource, resource_content_id, previous_content_id)); |  137       resource_content_id && resource_content_id == previous_content_id; | 
 |  138   return base::WrapUnique(new RasterBufferImpl( | 
 |  139       this, resource_provider_, resource->id(), async_worker_context_enabled_, | 
 |  140       resource_has_previous_content)); | 
|  110 } |  141 } | 
|  111  |  142  | 
|  112 void GpuRasterBufferProvider::ReleaseBufferForRaster( |  143 void GpuRasterBufferProvider::ReleaseBufferForRaster( | 
|  113     std::unique_ptr<RasterBuffer> buffer) { |  144     std::unique_ptr<RasterBuffer> buffer) { | 
|  114   // Nothing to do here. RasterBufferImpl destructor cleans up after itself. |  145   // Nothing to do here. RasterBufferImpl destructor cleans up after itself. | 
|  115 } |  146 } | 
|  116  |  147  | 
|  117 void GpuRasterBufferProvider::OrderingBarrier() { |  148 bool GpuRasterBufferProvider::OrderingBarrier() { | 
|  118   TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier"); |  149   TRACE_EVENT0("cc", "GpuRasterBufferProvider::OrderingBarrier"); | 
|  119   compositor_context_provider_->ContextGL()->OrderingBarrierCHROMIUM(); |  150  | 
 |  151   gpu::gles2::GLES2Interface* gl = compositor_context_provider_->ContextGL(); | 
 |  152   GLuint64 fence = gl->InsertFenceSyncCHROMIUM(); | 
 |  153   gl->OrderingBarrierCHROMIUM(); | 
 |  154  | 
 |  155   gpu::SyncToken sync_token; | 
 |  156   gl->GenUnverifiedSyncTokenCHROMIUM(fence, sync_token.GetData()); | 
 |  157  | 
 |  158   for (RasterBufferImpl* buffer : pending_raster_buffers_) | 
 |  159     buffer->set_sync_token(sync_token); | 
 |  160   pending_raster_buffers_.clear(); | 
 |  161  | 
 |  162   DCHECK(sync_token.HasData() || | 
 |  163          gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR); | 
 |  164   // Do not proceed with ScheduleTasks if sync token was invalid. | 
 |  165   return sync_token.HasData(); | 
|  120 } |  166 } | 
|  121  |  167  | 
|  122 ResourceFormat GpuRasterBufferProvider::GetResourceFormat( |  168 ResourceFormat GpuRasterBufferProvider::GetResourceFormat( | 
|  123     bool must_support_alpha) const { |  169     bool must_support_alpha) const { | 
|  124   return rasterizer_->resource_provider()->best_render_buffer_format(); |  170   return resource_provider_->best_render_buffer_format(); | 
|  125 } |  171 } | 
|  126  |  172  | 
|  127 bool GpuRasterBufferProvider::GetResourceRequiresSwizzle( |  173 bool GpuRasterBufferProvider::GetResourceRequiresSwizzle( | 
|  128     bool must_support_alpha) const { |  174     bool must_support_alpha) const { | 
|  129   // This doesn't require a swizzle because we rasterize to the correct format. |  175   // This doesn't require a swizzle because we rasterize to the correct format. | 
|  130   return false; |  176   return false; | 
|  131 } |  177 } | 
|  132  |  178  | 
|  133 void GpuRasterBufferProvider::Shutdown() {} |  179 void GpuRasterBufferProvider::Shutdown() { | 
 |  180   pending_raster_buffers_.clear(); | 
 |  181 } | 
 |  182  | 
 |  183 void GpuRasterBufferProvider::PlaybackOnWorkerThread( | 
 |  184     ResourceProvider::ScopedWriteLockGL* resource_lock, | 
 |  185     const gpu::SyncToken& sync_token, | 
 |  186     bool resource_has_previous_content, | 
 |  187     const RasterSource* raster_source, | 
 |  188     const gfx::Rect& raster_full_rect, | 
 |  189     const gfx::Rect& raster_dirty_rect, | 
 |  190     uint64_t new_content_id, | 
 |  191     float scale, | 
 |  192     const RasterSource::PlaybackSettings& playback_settings) { | 
 |  193   ContextProvider::ScopedContextLock scoped_context(worker_context_provider_); | 
 |  194   gpu::gles2::GLES2Interface* gl = scoped_context.ContextGL(); | 
 |  195  | 
 |  196   // Synchronize with compositor. | 
 |  197   DCHECK(sync_token.HasData()); | 
 |  198   gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); | 
 |  199  | 
 |  200   sk_sp<SkPicture> picture = PlaybackToPicture( | 
 |  201       raster_source, resource_has_previous_content, resource_lock->size(), | 
 |  202       raster_full_rect, raster_dirty_rect, scale, playback_settings); | 
 |  203  | 
 |  204   // Turn on distance fields for layers that have ever animated. | 
 |  205   bool use_distance_field_text = | 
 |  206       use_distance_field_text_ || | 
 |  207       raster_source->ShouldAttemptToUseDistanceFieldText(); | 
 |  208  | 
 |  209   RasterizePicture(picture.get(), worker_context_provider_, resource_lock, | 
 |  210                    async_worker_context_enabled_, use_distance_field_text, | 
 |  211                    raster_source->CanUseLCDText(), msaa_sample_count_); | 
 |  212  | 
 |  213   const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); | 
 |  214  | 
 |  215   // Barrier to sync worker context output to cc context. | 
 |  216   gl->OrderingBarrierCHROMIUM(); | 
 |  217  | 
 |  218   // Generate sync token after the barrier for cross context synchronization. | 
 |  219   gpu::SyncToken resource_sync_token; | 
 |  220   gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, resource_sync_token.GetData()); | 
 |  221   resource_lock->set_sync_token(resource_sync_token); | 
 |  222   resource_lock->set_synchronized(!async_worker_context_enabled_); | 
 |  223 } | 
|  134  |  224  | 
|  135 }  // namespace cc |  225 }  // namespace cc | 
| OLD | NEW |