prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "cc/raster/zero_copy_raster_buffer_provider.h" |
| 6 | |
| 7 | #include <stdint.h> |
| 8 | |
| 9 | #include <algorithm> |
| 10 | |
| 11 | #include "base/macros.h" |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 12 | #include "base/trace_event/process_memory_dump.h" |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 13 | #include "base/trace_event/trace_event.h" |
David 'Digit' Turner | 59a8748 | 2018-10-29 13:27:16 | [diff] [blame] | 14 | #include "base/trace_event/traced_value.h" |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 15 | #include "cc/resources/resource_pool.h" |
danakj | 57baa77 | 2018-05-29 15:59:14 | [diff] [blame] | 16 | #include "components/viz/client/client_resource_provider.h" |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 17 | #include "components/viz/common/gpu/context_provider.h" |
Fady Samuel | 555c8d1 | 2017-07-07 23:14:09 | [diff] [blame] | 18 | #include "components/viz/common/resources/platform_color.h" |
danakj | bf124ca | 2018-01-04 16:35:51 | [diff] [blame] | 19 | #include "components/viz/common/resources/resource_format_utils.h" |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 20 | #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 21 | #include "gpu/command_buffer/client/shared_image_interface.h" |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 22 | #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 23 | #include "gpu/command_buffer/common/shared_image_trace_utils.h" |
| 24 | #include "gpu/command_buffer/common/shared_image_usage.h" |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 25 | #include "ui/gfx/buffer_format_util.h" |
| 26 | #include "ui/gfx/gpu_memory_buffer.h" |
| 27 | |
| 28 | namespace cc { |
| 29 | namespace { |
| 30 | |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 31 | constexpr static auto kBufferUsage = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE; |
| 32 | |
| 33 | // Subclass for InUsePoolResource that holds ownership of a zero-copy backing |
| 34 | // and does cleanup of the backing when destroyed. |
| 35 | class ZeroCopyGpuBacking : public ResourcePool::GpuBacking { |
| 36 | public: |
| 37 | ~ZeroCopyGpuBacking() override { |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 38 | if (mailbox.IsZero()) |
| 39 | return; |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 40 | if (returned_sync_token.HasData()) |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 41 | shared_image_interface->DestroySharedImage(returned_sync_token, mailbox); |
| 42 | else if (mailbox_sync_token.HasData()) |
| 43 | shared_image_interface->DestroySharedImage(mailbox_sync_token, mailbox); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 44 | } |
| 45 | |
Alexandr Ilin | 0443a8f | 2018-07-20 20:14:50 | [diff] [blame] | 46 | void OnMemoryDump( |
| 47 | base::trace_event::ProcessMemoryDump* pmd, |
| 48 | const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, |
| 49 | uint64_t tracing_process_id, |
| 50 | int importance) const override { |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 51 | if (!gpu_memory_buffer) |
Alexandr Ilin | 0443a8f | 2018-07-20 20:14:50 | [diff] [blame] | 52 | return; |
| 53 | gpu_memory_buffer->OnMemoryDump(pmd, buffer_dump_guid, tracing_process_id, |
| 54 | importance); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 55 | } |
| 56 | |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 57 | // The SharedImageInterface used to clean up the shared image. |
| 58 | gpu::SharedImageInterface* shared_image_interface = nullptr; |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 59 | // The backing for zero-copy gpu resources. The |texture_id| is bound to |
| 60 | // this. |
| 61 | std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer; |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 62 | }; |
| 63 | |
| 64 | // RasterBuffer for the zero copy upload, which is given to the raster worker |
| 65 | // threads for raster/upload. |
Daniel Bratell | 1bddcb33 | 2017-11-21 11:08:29 | [diff] [blame] | 66 | class ZeroCopyRasterBufferImpl : public RasterBuffer { |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 67 | public: |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 68 | ZeroCopyRasterBufferImpl( |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 69 | gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, |
| 70 | const ResourcePool::InUsePoolResource& in_use_resource, |
| 71 | ZeroCopyGpuBacking* backing) |
| 72 | : backing_(backing), |
| 73 | gpu_memory_buffer_manager_(gpu_memory_buffer_manager), |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 74 | resource_size_(in_use_resource.size()), |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 75 | resource_format_(in_use_resource.format()), |
| 76 | resource_color_space_(in_use_resource.color_space()), |
| 77 | gpu_memory_buffer_(std::move(backing_->gpu_memory_buffer)) {} |
| 78 | |
| 79 | ~ZeroCopyRasterBufferImpl() override { |
Antoine Labour | 6363d820 | 2018-10-29 22:36:01 | [diff] [blame] | 80 | // If GpuMemoryBuffer allocation failed (https://crbug.com/554541), then |
| 81 | // we don't have anything to give to the display compositor, so we report a |
| 82 | // zero mailbox that will result in checkerboarding. |
| 83 | if (!gpu_memory_buffer_) { |
| 84 | DCHECK(backing_->mailbox.IsZero()); |
| 85 | return; |
| 86 | } |
| 87 | |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 88 | // This is destroyed on the compositor thread when raster is complete, but |
| 89 | // before the backing is prepared for export to the display compositor. So |
| 90 | // we can set up the texture and SyncToken here. |
| 91 | // TODO(danakj): This could be done with the worker context in Playback. Do |
| 92 | // we need to do things in IsResourceReadyToDraw() and OrderingBarrier then? |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 93 | gpu::SharedImageInterface* sii = backing_->shared_image_interface; |
| 94 | if (backing_->mailbox.IsZero()) { |
| 95 | uint32_t usage = |
| 96 | gpu::SHARED_IMAGE_USAGE_DISPLAY | gpu::SHARED_IMAGE_USAGE_SCANOUT; |
| 97 | // Make a mailbox for export of the GpuMemoryBuffer to the display |
| 98 | // compositor. |
| 99 | backing_->mailbox = sii->CreateSharedImage(gpu_memory_buffer_.get(), |
| 100 | gpu_memory_buffer_manager_, |
| 101 | resource_color_space_, usage); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 102 | } else { |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 103 | sii->UpdateSharedImage(backing_->returned_sync_token, backing_->mailbox); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 104 | } |
| 105 | |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 106 | backing_->mailbox_sync_token = sii->GenUnverifiedSyncToken(); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 107 | backing_->gpu_memory_buffer = std::move(gpu_memory_buffer_); |
| 108 | } |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 109 | |
| 110 | // Overridden from RasterBuffer: |
Khushal | 49836ab | 2018-07-25 02:08:45 | [diff] [blame] | 111 | void Playback(const RasterSource* raster_source, |
| 112 | const gfx::Rect& raster_full_rect, |
| 113 | const gfx::Rect& raster_dirty_rect, |
| 114 | uint64_t new_content_id, |
| 115 | const gfx::AxisTransform2d& transform, |
| 116 | const RasterSource::PlaybackSettings& playback_settings, |
| 117 | const GURL& url) override { |
prashant.n | 60e135b0 | 2016-06-08 04:12:23 | [diff] [blame] | 118 | TRACE_EVENT0("cc", "ZeroCopyRasterBuffer::Playback"); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 119 | |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 120 | if (!gpu_memory_buffer_) { |
| 121 | gpu_memory_buffer_ = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer( |
| 122 | resource_size_, viz::BufferFormat(resource_format_), kBufferUsage, |
| 123 | gpu::kNullSurfaceHandle); |
Christopher Cameron | 79358bd | 2018-08-02 04:31:44 | [diff] [blame] | 124 | // Note that GpuMemoryBuffer allocation can fail. |
| 125 | // https://crbug.com/554541 |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 126 | if (!gpu_memory_buffer_) |
| 127 | return; |
| 128 | } |
| 129 | |
| 130 | DCHECK_EQ(1u, gfx::NumberOfPlanesForBufferFormat( |
| 131 | gpu_memory_buffer_->GetFormat())); |
| 132 | bool rv = gpu_memory_buffer_->Map(); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 133 | DCHECK(rv); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 134 | DCHECK(gpu_memory_buffer_->memory(0)); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 135 | // RasterBufferProvider::PlaybackToMemory only supports unsigned strides. |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 136 | DCHECK_GE(gpu_memory_buffer_->stride(0), 0); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 137 | |
| 138 | // TODO(danakj): Implement partial raster with raster_dirty_rect. |
| 139 | RasterBufferProvider::PlaybackToMemory( |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 140 | gpu_memory_buffer_->memory(0), resource_format_, resource_size_, |
| 141 | gpu_memory_buffer_->stride(0), raster_source, raster_full_rect, |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 142 | raster_full_rect, transform, resource_color_space_, |
| 143 | /*gpu_compositing=*/true, playback_settings); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 144 | gpu_memory_buffer_->Unmap(); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | private: |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 148 | // This field may only be used on the compositor thread. |
| 149 | ZeroCopyGpuBacking* backing_; |
| 150 | |
| 151 | // These fields are for use on the worker thread. |
| 152 | gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_; |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 153 | gfx::Size resource_size_; |
| 154 | viz::ResourceFormat resource_format_; |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 155 | gfx::ColorSpace resource_color_space_; |
| 156 | std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 157 | |
Daniel Bratell | 1bddcb33 | 2017-11-21 11:08:29 | [diff] [blame] | 158 | DISALLOW_COPY_AND_ASSIGN(ZeroCopyRasterBufferImpl); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 159 | }; |
| 160 | |
| 161 | } // namespace |
| 162 | |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 163 | ZeroCopyRasterBufferProvider::ZeroCopyRasterBufferProvider( |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 164 | gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, |
| 165 | viz::ContextProvider* compositor_context_provider, |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 166 | viz::ResourceFormat tile_format) |
| 167 | : gpu_memory_buffer_manager_(gpu_memory_buffer_manager), |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 168 | compositor_context_provider_(compositor_context_provider), |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 169 | tile_format_(tile_format) {} |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 170 | |
Chris Watkins | f635329 | 2017-12-04 02:36:05 | [diff] [blame] | 171 | ZeroCopyRasterBufferProvider::~ZeroCopyRasterBufferProvider() = default; |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 172 | |
| 173 | std::unique_ptr<RasterBuffer> |
| 174 | ZeroCopyRasterBufferProvider::AcquireBufferForRaster( |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 175 | const ResourcePool::InUsePoolResource& resource, |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 176 | uint64_t resource_content_id, |
| 177 | uint64_t previous_content_id) { |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 178 | if (!resource.gpu_backing()) { |
| 179 | auto backing = std::make_unique<ZeroCopyGpuBacking>(); |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 180 | const gpu::Capabilities& caps = |
| 181 | compositor_context_provider_->ContextCapabilities(); |
| 182 | backing->texture_target = gpu::GetBufferTextureTarget( |
| 183 | gfx::BufferUsage::SCANOUT, BufferFormat(resource.format()), caps); |
| 184 | backing->overlay_candidate = true; |
| 185 | // This RasterBufferProvider will modify the resource outside of the |
| 186 | // GL command stream. So resources should not become available for reuse |
| 187 | // until they are not in use by the gpu anymore, which a fence is used |
| 188 | // to determine. |
| 189 | backing->wait_on_fence_required = true; |
| 190 | backing->shared_image_interface = |
| 191 | compositor_context_provider_->SharedImageInterface(); |
danakj | bd63605 | 2018-02-06 18:28:49 | [diff] [blame] | 192 | resource.set_gpu_backing(std::move(backing)); |
| 193 | } |
| 194 | ZeroCopyGpuBacking* backing = |
| 195 | static_cast<ZeroCopyGpuBacking*>(resource.gpu_backing()); |
| 196 | |
Antoine Labour | e5a2101a | 2018-11-07 23:36:27 | [diff] [blame^] | 197 | return std::make_unique<ZeroCopyRasterBufferImpl>(gpu_memory_buffer_manager_, |
| 198 | resource, backing); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 199 | } |
| 200 | |
Sunny Sachanandani | 5f5419e2 | 2017-05-12 20:35:30 | [diff] [blame] | 201 | void ZeroCopyRasterBufferProvider::Flush() {} |
| 202 | |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 203 | viz::ResourceFormat ZeroCopyRasterBufferProvider::GetResourceFormat() const { |
| 204 | return tile_format_; |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 205 | } |
| 206 | |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 207 | bool ZeroCopyRasterBufferProvider::IsResourceSwizzleRequired() const { |
| 208 | return !viz::PlatformColor::SameComponentOrder(GetResourceFormat()); |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 209 | } |
| 210 | |
danakj | a32578c | 2018-04-25 21:18:36 | [diff] [blame] | 211 | bool ZeroCopyRasterBufferProvider::IsResourcePremultiplied() const { |
Eric Karl | 247f09c | 2018-03-15 02:06:36 | [diff] [blame] | 212 | return true; |
| 213 | } |
| 214 | |
ericrk | 5ac42f32 | 2016-07-14 01:06:51 | [diff] [blame] | 215 | bool ZeroCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource() |
| 216 | const { |
ericrk | eeda5899 | 2016-07-07 02:34:27 | [diff] [blame] | 217 | return false; |
| 218 | } |
| 219 | |
ericrk | 7f6a27f | 2017-01-31 22:34:32 | [diff] [blame] | 220 | bool ZeroCopyRasterBufferProvider::IsResourceReadyToDraw( |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 221 | const ResourcePool::InUsePoolResource& resource) const { |
ericrk | 7f6a27f | 2017-01-31 22:34:32 | [diff] [blame] | 222 | // Zero-copy resources are immediately ready to draw. |
| 223 | return true; |
| 224 | } |
| 225 | |
| 226 | uint64_t ZeroCopyRasterBufferProvider::SetReadyToDrawCallback( |
danakj | 4e871d8 | 2018-01-18 21:56:57 | [diff] [blame] | 227 | const std::vector<const ResourcePool::InUsePoolResource*>& resources, |
ericrk | 7f6a27f | 2017-01-31 22:34:32 | [diff] [blame] | 228 | const base::Closure& callback, |
| 229 | uint64_t pending_callback_id) const { |
| 230 | // Zero-copy resources are immediately ready to draw. |
| 231 | return 0; |
| 232 | } |
| 233 | |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 234 | void ZeroCopyRasterBufferProvider::Shutdown() {} |
| 235 | |
Khushal | cd8fbb77 | 2018-10-16 22:46:14 | [diff] [blame] | 236 | bool ZeroCopyRasterBufferProvider::CheckRasterFinishedQueries() { |
| 237 | return false; |
| 238 | } |
| 239 | |
prashant.n | b4d4f49 | 2016-04-29 12:51:28 | [diff] [blame] | 240 | } // namespace cc |