1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/raster/zero_copy_raster_buffer_provider.h"
#include <stdint.h>
#include <algorithm>
#include <utility>
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "cc/base/features.h"
#include "cc/resources/resource_pool.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/shared_image_format_utils.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_trace_utils.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "ui/gfx/buffer_format_util.h"
#include "url/gurl.h"
namespace cc {
namespace {
constexpr static auto kBufferUsage = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
}
ZeroCopyRasterBufferImpl::ZeroCopyRasterBufferImpl(
const ResourcePool::InUsePoolResource& in_use_resource,
scoped_refptr<gpu::SharedImageInterface> sii,
bool resource_has_previous_content,
bool is_software)
: sii_(sii),
resource_has_previous_content_(resource_has_previous_content),
is_software_(is_software) {
if (!in_use_resource.backing()) {
if (is_software) {
in_use_resource.InstallSoftwareBacking(
sii, "ZeroCopyRasterBufferProviderSoftware");
in_use_resource.backing()->mailbox_sync_token =
sii->GenVerifiedSyncToken();
} else {
auto backing = std::make_unique<ResourcePool::Backing>(
in_use_resource.size(), in_use_resource.format(),
in_use_resource.color_space());
// This RasterBufferProvider will modify the resource outside of the
// GL command stream. So resources should not become available for reuse
// until they are not in use by the gpu anymore, which a fence is used
// to determine.
backing->wait_on_fence_required = true;
in_use_resource.set_backing(std::move(backing));
}
}
backing_ = in_use_resource.backing();
if (!backing_->shared_image()) {
// The backing's SharedImage will be created on a worker thread during the
// execution of this raster; to avoid data races during taking of memory
// dumps on the compositor thread, mark the backing's SharedImage as
// unavailable for access on the compositor thread for the duration of the
// raster.
backing_->can_access_shared_image_on_compositor_thread = false;
}
}
ZeroCopyRasterBufferImpl::~ZeroCopyRasterBufferImpl() {
// This raster task is complete, so if the backing's SharedImage was created
// on a worker thread during the raster work that has now happened.
backing_->can_access_shared_image_on_compositor_thread = true;
// Drop the SharedImage if it was not possible to map it.
if (failed_to_map_shared_image_) {
backing_->shared_image()->UpdateDestructionSyncToken(gpu::SyncToken());
backing_->clear_shared_image();
}
if (is_software_) {
// The below work is specific to GPU compositing.
return;
}
// If it was not possible to allocate the SharedImage
// (https://crbug.com/554541) or it was not possible to map it, then we
// don't have anything to give to the display compositor, so we report a
// zero mailbox that will result in checkerboarding.
if (!backing_->shared_image()) {
return;
}
// This is destroyed on the compositor thread when raster is complete, but
// before the backing is prepared for export to the display compositor. So
// we can set up the texture and SyncToken here.
// TODO(danakj): This could be done with the worker context in Playback. Do
// we need to do things in IsResourceReadyToDraw() and OrderingBarrier then?
sii_->UpdateSharedImage(backing_->returned_sync_token,
backing_->shared_image()->mailbox());
backing_->mailbox_sync_token = sii_->GenUnverifiedSyncToken();
}
void ZeroCopyRasterBufferImpl::Playback(
const RasterSource* raster_source,
const gfx::Rect& raster_full_rect,
const gfx::Rect& raster_dirty_rect,
uint64_t new_content_id,
const gfx::AxisTransform2d& transform,
const RasterSource::PlaybackSettings& playback_settings,
const GURL& url) {
TRACE_EVENT0("cc", "ZeroCopyRasterBuffer::Playback");
gfx::Rect playback_rect = raster_full_rect;
if (resource_has_previous_content_) {
playback_rect.Intersect(raster_dirty_rect);
}
DCHECK(!playback_rect.IsEmpty())
<< "Why are we rastering a tile that's not dirty?";
// Create a MappableSI if necessary.
if (is_software_) {
// WHen used with the software compositor, the SharedImage is created in the
// constructor.
CHECK(backing_->shared_image());
} else if (!backing_->shared_image()) {
gpu::SharedImageUsageSet usage =
gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_SCANOUT;
if (!backing_->CreateSharedImage(sii_.get(), usage, "ZeroCopyRasterTile",
kBufferUsage)) {
LOG(ERROR) << "Creation of MappableSharedImage failed.";
return;
}
}
std::unique_ptr<gpu::ClientSharedImage::ScopedMapping> mapping =
backing_->shared_image()->Map();
if (!mapping) {
LOG(ERROR) << "MapSharedImage Failed.";
// NOTE: It is not safe to clear the SharedImage here as it might be being
// read on the compositor thread as part of memory dump generation.
// Instead, save the fact that mapping failed so that the SharedImage can
// be cleared in the destructor of this object.
failed_to_map_shared_image_ = true;
return;
}
// TODO(danakj): Implement partial raster with raster_dirty_rect for GPU
// compositing.
RasterBufferProvider::PlaybackToMemory(
mapping->GetMemoryForPlane(0).data(), backing_->format(),
backing_->size(), mapping->Stride(0), raster_source, raster_full_rect,
playback_rect, transform, backing_->color_space(), playback_settings);
}
bool ZeroCopyRasterBufferImpl::SupportsBackgroundThreadPriority() const {
return true;
}
ZeroCopyRasterBufferProvider::ZeroCopyRasterBufferProvider(
const scoped_refptr<gpu::SharedImageInterface>& shared_image_interface,
bool is_software)
: is_software_(is_software),
shared_image_interface_(shared_image_interface) {
CHECK(shared_image_interface_)
<< "SharedImageInterface is null in ZeroCopyRasterBufferProvider ctor!";
}
ZeroCopyRasterBufferProvider::~ZeroCopyRasterBufferProvider() = default;
std::unique_ptr<RasterBuffer>
ZeroCopyRasterBufferProvider::AcquireBufferForRaster(
const ResourcePool::InUsePoolResource& resource,
uint64_t resource_content_id,
uint64_t previous_content_id,
bool depends_on_at_raster_decodes,
bool depends_on_hardware_accelerated_jpeg_candidates,
bool depends_on_hardware_accelerated_webp_candidates) {
bool resource_has_previous_content = false;
if (is_software_ ||
base::FeatureList::IsEnabled(
features::kZeroCopyRBPPartialRasterWithGpuCompositor)) {
resource_has_previous_content =
resource_content_id && resource_content_id == previous_content_id;
}
return std::make_unique<ZeroCopyRasterBufferImpl>(
resource, shared_image_interface_, resource_has_previous_content,
is_software_);
}
void ZeroCopyRasterBufferProvider::Flush() {}
bool ZeroCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource()
const {
return is_software_ ||
base::FeatureList::IsEnabled(
features::kZeroCopyRBPPartialRasterWithGpuCompositor);
}
bool ZeroCopyRasterBufferProvider::IsResourceReadyToDraw(
const ResourcePool::InUsePoolResource& resource) {
// Zero-copy resources are immediately ready to draw.
return true;
}
uint64_t ZeroCopyRasterBufferProvider::SetReadyToDrawCallback(
const std::vector<const ResourcePool::InUsePoolResource*>& resources,
base::OnceClosure callback,
uint64_t pending_callback_id) {
// Zero-copy resources are immediately ready to draw.
return 0;
}
void ZeroCopyRasterBufferProvider::Shutdown() {}
} // namespace cc
|