Skip to content

Commit

Permalink
Support BufferQueue on Mac
Browse files Browse the repository at this point in the history
This CL does NOT enable BQ on Mac.

- Don't call PrepareRenderPassOverlay for root render passes
- Ignore InUseByWindowServer for root rp overlays
- Don't bother calling DidReceiveReleasedOverlays for root rp overlays
- Also cleanup some render pass backing code for root rps, making logic
  simpler.

Bug: 1322528
Change-Id: I4ae0897a5803ded347d05159ddc1b06031948595
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4089938
Commit-Queue: Kevin Haslett <khaslett@chromium.org>
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1095874}
  • Loading branch information
Kevin Haslett authored and Chromium LUCI CQ committed Jan 23, 2023
1 parent a2a57c4 commit 3427060
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 52 deletions.
5 changes: 4 additions & 1 deletion components/viz/service/display/ca_layer_overlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class VIZ_SERVICE_EXPORT CALayerOverlay {
scoped_refptr<CALayerOverlaySharedState> shared_state;

// Texture that corresponds to an IOSurface to set as the content of the
// CALayer. If this is 0 then the CALayer is a solid color.
// CALayer. If this is 0 then the CALayer is a solid color, or it's the root
// render pass if |is_root_render_pass| = true.
ResourceId contents_resource_id = kInvalidResourceId;
// Mailbox from contents_resource_id. It is used by SkiaRenderer.
gpu::Mailbox mailbox;
Expand All @@ -88,6 +89,8 @@ class VIZ_SERVICE_EXPORT CALayerOverlay {
// If |rpdq| is present, then the renderer must draw the filter effects and
// copy the result into an IOSurface.
const AggregatedRenderPassDrawQuad* rpdq = nullptr;
// Whether this overlay candidate represents the root render pass.
bool is_root_render_pass = false;
};

typedef std::vector<CALayerOverlay> CALayerOverlayList;
Expand Down
43 changes: 24 additions & 19 deletions components/viz/service/display/direct_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/viz_utils.h"
#include "components/viz/service/display/bsp_tree.h"
#include "components/viz/service/display/bsp_walk_action.h"
Expand Down Expand Up @@ -191,23 +192,23 @@ void DirectRenderer::DecideRenderPassAllocationsForFrame(
base::flat_map<AggregatedRenderPassId, RenderPassRequirements>
render_passes_in_frame;
for (const auto& pass : render_passes_in_draw_order) {
// The root render pass doesn't need to be updated here because the backing
// is reused and updated in AllocateRenderPassResourceIfNeeded().
if (pass == root_render_pass) {
continue;
}

// If there's a copy request, we need an explicit renderpass backing so
// only try to draw directly if there are no copy requests.
bool is_root = pass == root_render_pass;
if (!is_root && pass->copy_requests.empty()) {
if (pass->copy_requests.empty()) {
if (const DrawQuad* quad = CanPassBeDrawnDirectly(pass.get())) {
// If the render pass is drawn directly, it will not be drawn from as
// a render pass so it's not added to the map.
render_pass_bypass_quads_[pass->id] = quad;
continue;
}
}
gfx::Size size = pass->output_rect.size();
// We should not change the buffer size for the root render pass.
// The requirement is used for non-root render pass only.
if (!is_root) {
size = CalculateTextureSizeForRenderPass(pass.get());
}
gfx::Size size = CalculateTextureSizeForRenderPass(pass.get());
auto color_space = RenderPassColorSpace(pass.get());
auto format = GetColorSpaceResourceFormat(color_space);

Expand Down Expand Up @@ -784,20 +785,24 @@ void DirectRenderer::UseRenderPass(const AggregatedRenderPass* render_pass) {
return;
}

gfx::Size size = render_pass->output_rect.size();
// We should not change the buffer size for the root render pass.
RenderPassRequirements requirements;
// The root pass will use values from |reshape_params_| so this doesn't
// matter.
if (!is_root) {
size = CalculateTextureSizeForRenderPass(render_pass);
size.Enlarge(enlarge_pass_texture_amount_.width(),
enlarge_pass_texture_amount_.height());
requirements.size = CalculateTextureSizeForRenderPass(render_pass);
requirements.size.Enlarge(enlarge_pass_texture_amount_.width(),
enlarge_pass_texture_amount_.height());
requirements.generate_mipmap = render_pass->generate_mipmap;
requirements.color_space = CurrentRenderPassColorSpace();
requirements.format = GetColorSpaceResourceFormat(requirements.color_space);
} else {
requirements.size = surface_size_for_swap_buffers();
requirements.generate_mipmap = false;
requirements.color_space = reshape_color_space();
requirements.format = GetResourceFormat(reshape_buffer_format());
}

auto color_space = CurrentRenderPassColorSpace();
auto format = GetColorSpaceResourceFormat(color_space);

AllocateRenderPassResourceIfNeeded(
render_pass->id,
{size, render_pass->generate_mipmap, format, color_space});
AllocateRenderPassResourceIfNeeded(render_pass->id, requirements);

// TODO(crbug.com/582554): This change applies only when Vulkan is enabled and
// it will be removed once SkiaRenderer has complete support for Vulkan.
Expand Down
59 changes: 39 additions & 20 deletions components/viz/service/display/skia_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -871,19 +871,24 @@ void SkiaRenderer::FinishDrawingFrame() {
if (!buffer_queue_) {
skia_output_surface_->ScheduleOutputSurfaceAsOverlay(surface_plane);
} else {
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN)
// Windows and Mac have different OverlayList types, but those platforms
// aren't supported by buffer_queue_ yet, so this won't be reached.
#if BUILDFLAG(IS_WIN)
// Windows does not use buffer_queue_ so this won't be reached.
NOTREACHED();
#else
auto root_pass_backing =
render_pass_backings_.find(current_frame()->root_render_pass->id);
// The root pass backing should always exist.
DCHECK(root_pass_backing != render_pass_backings_.end());

#if BUILDFLAG(IS_MAC)
CALayerOverlay surface_candidate;
surface_candidate.shared_state =
base::MakeRefCounted<CALayerOverlaySharedState>();
surface_candidate.shared_state->sorting_context_id = 0;
surface_candidate.shared_state->rounded_corner_bounds =
surface_plane.rounded_corners;
surface_candidate.contents_rect = surface_plane.uv_rect;
surface_candidate.bounds_rect = surface_plane.display_rect;
surface_candidate.opacity = surface_plane.opacity;
surface_candidate.filter = GL_LINEAR;
#else
OverlayCandidate surface_candidate;
surface_candidate.mailbox = root_pass_backing->second.mailbox;
surface_candidate.is_root_render_pass = true;
surface_candidate.transform = surface_plane.transform;
surface_candidate.display_rect = surface_plane.display_rect;
surface_candidate.uv_rect = surface_plane.uv_rect;
Expand All @@ -897,10 +902,19 @@ void SkiaRenderer::FinishDrawingFrame() {
surface_candidate.damage_rect =
gfx::RectF(surface_plane.damage_rect.value_or(
gfx::Rect(surface_plane.resource_size)));
#endif // BUILDFLAG(IS_MAC)

auto root_pass_backing =
render_pass_backings_.find(current_frame()->root_render_pass->id);
// The root pass backing should always exist.
DCHECK(root_pass_backing != render_pass_backings_.end());

surface_candidate.mailbox = root_pass_backing->second.mailbox;
surface_candidate.is_root_render_pass = true;

current_frame()->overlay_list.insert(
current_frame()->overlay_list.begin(), surface_candidate);
#endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN)
#endif // BUILDFLAG(IS_WIN)
}
} else {
#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_MAC)
Expand Down Expand Up @@ -2717,6 +2731,10 @@ void SkiaRenderer::ScheduleOverlays() {
}
#elif BUILDFLAG(IS_APPLE)
for (CALayerOverlay& ca_layer_overlay : current_frame()->overlay_list) {
if (ca_layer_overlay.is_root_render_pass) {
continue;
}

if (ca_layer_overlay.rpdq) {
PrepareRenderPassOverlay(&ca_layer_overlay);
locks.emplace_back(ca_layer_overlay.mailbox);
Expand Down Expand Up @@ -3159,6 +3177,12 @@ void SkiaRenderer::UpdateRenderPassTextures(
render_passes_in_frame) {
std::vector<AggregatedRenderPassId> passes_to_delete;
for (const auto& pair : render_pass_backings_) {
// The single root render pass backing is updated in
// AllocateRenderPassResourceIfNeeded(), so we should never erase it here.
if (pair.second.is_root) {
continue;
}

auto render_pass_it = render_passes_in_frame.find(pair.first);
if (render_pass_it == render_passes_in_frame.end()) {
passes_to_delete.push_back(pair.first);
Expand Down Expand Up @@ -3186,12 +3210,7 @@ void SkiaRenderer::UpdateRenderPassTextures(
for (size_t i = 0; i < passes_to_delete.size(); ++i) {
auto it = render_pass_backings_.find(passes_to_delete[i]);
auto& backing = it->second;
// Buffers for root render pass backings are managed by |buffer_queue_|, not
// DisplayResourceProvider, so we should not destroy them here. This
// reallocation is done in Reshape before drawing the frame
if (!backing.is_root) {
skia_output_surface_->DestroySharedImage(backing.mailbox);
}
skia_output_surface_->DestroySharedImage(backing.mailbox);
render_pass_backings_.erase(it);
}

Expand All @@ -3208,10 +3227,10 @@ void SkiaRenderer::AllocateRenderPassResourceIfNeeded(
auto& root_pass_backing = render_pass_backings_[render_pass_id];
root_pass_backing.is_root = true;
root_pass_backing.mailbox = buffer_queue_->GetCurrentBuffer();
root_pass_backing.generate_mipmap = false;
root_pass_backing.size = surface_size_for_swap_buffers();
root_pass_backing.format = GetResourceFormat(reshape_buffer_format());
root_pass_backing.color_space = reshape_color_space();
root_pass_backing.generate_mipmap = requirements.generate_mipmap;
root_pass_backing.size = requirements.size;
root_pass_backing.format = requirements.format;
root_pass_backing.color_space = requirements.color_space;
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,12 @@ class SkiaOutputDeviceBufferQueue::OverlayData {

OverlayData(std::unique_ptr<gpu::OverlayImageRepresentation> representation,
std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
scoped_read_access)
scoped_read_access,
bool is_root_render_pass)
: representation_(std::move(representation)),
scoped_read_access_(std::move(scoped_read_access)),
ref_(1) {
ref_(1),
is_root_render_pass_(is_root_render_pass) {
DCHECK(representation_);
DCHECK(scoped_read_access_);
}
Expand All @@ -75,21 +77,28 @@ class SkiaOutputDeviceBufferQueue::OverlayData {
~OverlayData() { Reset(); }

OverlayData& operator=(OverlayData&& other) {
DCHECK(!IsInUseByWindowServer());
DCHECK(is_root_render_pass_ || !IsInUseByWindowServer());
DCHECK(!ref_);
DCHECK(!scoped_read_access_);
DCHECK(!representation_);
scoped_read_access_ = std::move(other.scoped_read_access_);
representation_ = std::move(other.representation_);
ref_ = other.ref_;
other.ref_ = 0;
is_root_render_pass_ = other.is_root_render_pass_;
return *this;
}

bool IsInUseByWindowServer() const {
#if BUILDFLAG(IS_MAC)
if (!scoped_read_access_)
if (!scoped_read_access_) {
return false;
}
// The root render pass buffers are managed by SkiaRenderer so we don't care
// if they're in use by the window server.
if (is_root_render_pass_) {
return false;
}
return scoped_read_access_->IsInUseByWindowServer();
#else
return false;
Expand All @@ -103,7 +112,7 @@ class SkiaOutputDeviceBufferQueue::OverlayData {
if (ref_ > 1) {
--ref_;
} else if (ref_ == 1) {
DCHECK(!IsInUseByWindowServer());
DCHECK(is_root_render_pass_ || !IsInUseByWindowServer());
Reset();
}
}
Expand All @@ -117,6 +126,8 @@ class SkiaOutputDeviceBufferQueue::OverlayData {
return scoped_read_access_.get();
}

bool IsRootRenderPass() { return is_root_render_pass_; }

private:
void Reset() {
scoped_read_access_.reset();
Expand All @@ -128,6 +139,7 @@ class SkiaOutputDeviceBufferQueue::OverlayData {
std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess>
scoped_read_access_;
int ref_ = 0;
bool is_root_render_pass_ = false;
};

SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
Expand Down Expand Up @@ -321,6 +333,7 @@ void SkiaOutputDeviceBufferQueue::SchedulePrimaryPlane(

SkiaOutputDeviceBufferQueue::OverlayData*
SkiaOutputDeviceBufferQueue::GetOrCreateOverlayData(const gpu::Mailbox& mailbox,
bool is_root_render_pass,
bool* is_existing) {
if (is_existing)
*is_existing = false;
Expand Down Expand Up @@ -354,8 +367,9 @@ SkiaOutputDeviceBufferQueue::GetOrCreateOverlayData(const gpu::Mailbox& mailbox,
}

bool result;
std::tie(it, result) = overlays_.emplace(std::move(shared_image),
std::move(shared_image_access));
std::tie(it, result) =
overlays_.emplace(std::move(shared_image), std::move(shared_image_access),
is_root_render_pass);
DCHECK(result);
DCHECK(it->unique());

Expand Down Expand Up @@ -394,8 +408,8 @@ void SkiaOutputDeviceBufferQueue::ScheduleOverlays(

OutputPresenter::ScopedOverlayAccess* access = nullptr;
bool overlay_has_been_submitted;
auto* overlay_data =
GetOrCreateOverlayData(mailbox, &overlay_has_been_submitted);
auto* overlay_data = GetOrCreateOverlayData(
mailbox, overlay.is_root_render_pass, &overlay_has_been_submitted);
if (overlay_data) {
access = overlay_data->scoped_read_access();
pending_overlay_mailboxes_.emplace_back(mailbox);
Expand Down Expand Up @@ -589,11 +603,17 @@ void SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers(
// Go through backings of all overlays, and release overlay backings which are
// not used.
base::EraseIf(overlays_, [&on_overlay_release](auto& overlay) {
if (!overlay.unique())
if (!overlay.unique()) {
return false;
if (overlay.IsInUseByWindowServer())
}
if (overlay.IsInUseByWindowServer()) {
return false;
on_overlay_release(overlay);
}
// The root render pass buffers are managed by SkiaRenderer so we don't need
// to explicitly return them via callback.
if (!overlay.IsRootRenderPass()) {
on_overlay_release(overlay);
}
overlay.Unref();
return true;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue : public SkiaOutputDevice {
// Given an overlay mailbox, returns the corresponding OverlayData* from
// |overlays_|. Inserts an OverlayData if mailbox is not in |overlays_|.
OverlayData* GetOrCreateOverlayData(const gpu::Mailbox& mailbox,
bool is_root_render_pass,
bool* is_existing = nullptr);

std::unique_ptr<OutputPresenter> presenter_;
Expand Down

0 comments on commit 3427060

Please sign in to comment.