Commit cadd796f authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Set context lost in Skia Renderer when direct composition swap chain creation fails on Windows

This is to handle the swap chain creation failure in direct composition
and direct composition overlay. By setting context lost, it has a chance
to restart a new GPU command buffer without direct composition/overlay
support.

GL Renderer has already set context lost when SetDrawRectangles() or
PostSubBuffer() fails. But this logic is missing in Skia Renderer.


Bug: 1086750
Change-Id: Ie04c1437271f87b7c9838e79b61cdecb60f787e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2213778
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#773969}
parent 21a06d72
......@@ -26,12 +26,13 @@ enum ContextLostReason {
CONTEXT_LOST_OUT_OF_MEMORY = 10,
CONTEXT_LOST_MAKECURRENT_FAILED = 11,
CONTEXT_LOST_INVALID_GPU_MESSAGE = 12,
// SkiaRenderer marked context as lost because of failed Reshape call
CONTEXT_LOST_RESHAPE_FAILED = 13,
// Update kMaxValue and //tools/metrics/histograms/histograms.xml when adding
// new values.
kMaxValue = CONTEXT_LOST_RESHAPE_FAILED
CONTEXT_LOST_SET_DRAW_RECTANGLE_FAILED = 14,
CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED = 15,
// Update kMaxValue here and <enum name="ContextLostReason"> in
// tools/metrics/histograms/enum.xml when adding new values.
kMaxValue = CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED
};
VIZ_COMMON_EXPORT ContextLostReason
......
......@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind_helpers.h"
#include "components/viz/common/gpu/context_lost_reason.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/feature_info.h"
......@@ -25,8 +26,13 @@
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/gl_version_info.h"
#if defined(OS_WIN)
#include "ui/gl/direct_composition_surface_win.h"
#endif
namespace viz {
SkiaOutputDeviceGL::SkiaOutputDeviceGL(
......@@ -35,13 +41,15 @@ SkiaOutputDeviceGL::SkiaOutputDeviceGL(
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::gles2::FeatureInfo> feature_info,
gpu::MemoryTracker* memory_tracker,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback,
ContextLostOnGpuCallback context_lost_on_gpu_callback)
: SkiaOutputDevice(memory_tracker,
std::move(did_swap_buffer_complete_callback)),
mailbox_manager_(mailbox_manager),
context_state_(context_state),
gl_surface_(std::move(gl_surface)),
supports_async_swap_(gl_surface_->SupportsAsyncSwap()) {
supports_async_swap_(gl_surface_->SupportsAsyncSwap()),
context_lost_on_gpu_callback_(std::move(context_lost_on_gpu_callback)) {
capabilities_.uses_default_gl_framebuffer = true;
capabilities_.output_surface_origin = gl_surface_->GetOrigin();
capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer();
......@@ -61,6 +69,11 @@ SkiaOutputDeviceGL::SkiaOutputDeviceGL(
// This output device is never offscreen.
capabilities_.supports_surfaceless = gl_surface_->IsSurfaceless();
#endif
#if defined(OS_WIN)
supports_overlays_ = gl::AreOverlaysSupportedWin();
supports_direct_composition_ =
gl::DirectCompositionSurfaceWin::IsDirectCompositionSupported();
#endif
DCHECK(context_state_->gr_context());
DCHECK(context_state_->context());
......@@ -192,9 +205,16 @@ void SkiaOutputDeviceGL::SwapBuffers(
std::move(latency_info));
gl_surface_->SwapBuffersAsync(std::move(callback), std::move(feedback));
} else {
FinishSwapBuffers(gfx::SwapCompletionResult(
gl_surface_->SwapBuffers(std::move(feedback))),
surface_size, std::move(latency_info));
gfx::SwapResult result = gl_surface_->SwapBuffers(std::move(feedback));
FinishSwapBuffers(gfx::SwapCompletionResult(result), surface_size,
std::move(latency_info));
#if defined(OS_WIN)
if (result == gfx::SwapResult::SWAP_FAILED && supports_overlays_ &&
context_lost_on_gpu_callback_) {
std::move(context_lost_on_gpu_callback_)
.Run(CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED);
}
#endif
}
}
......@@ -214,12 +234,18 @@ void SkiaOutputDeviceGL::PostSubBuffer(
gl_surface_->PostSubBufferAsync(rect.x(), rect.y(), rect.width(),
rect.height(), std::move(callback),
std::move(feedback));
} else {
FinishSwapBuffers(gfx::SwapCompletionResult(gl_surface_->PostSubBuffer(
rect.x(), rect.y(), rect.width(), rect.height(),
std::move(feedback))),
surface_size, std::move(latency_info));
gfx::SwapResult result = gl_surface_->PostSubBuffer(
rect.x(), rect.y(), rect.width(), rect.height(), std::move(feedback));
FinishSwapBuffers(gfx::SwapCompletionResult(result), surface_size,
std::move(latency_info));
#if defined(OS_WIN)
if (result == gfx::SwapResult::SWAP_FAILED && supports_overlays_ &&
context_lost_on_gpu_callback_) {
std::move(context_lost_on_gpu_callback_)
.Run(CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED);
}
#endif
}
}
......@@ -254,7 +280,15 @@ void SkiaOutputDeviceGL::DoFinishSwapBuffers(
}
void SkiaOutputDeviceGL::SetDrawRectangle(const gfx::Rect& draw_rectangle) {
#if defined(OS_WIN)
if (!gl_surface_->SetDrawRectangle(draw_rectangle) &&
supports_direct_composition_ && context_lost_on_gpu_callback_) {
std::move(context_lost_on_gpu_callback_)
.Run(CONTEXT_LOST_SET_DRAW_RECTANGLE_FAILED);
}
#else
gl_surface_->SetDrawRectangle(draw_rectangle);
#endif
}
void SkiaOutputDeviceGL::SetGpuVSyncEnabled(bool enabled) {
......
......@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/viz/common/gpu/context_lost_reason.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/common/mailbox.h"
......@@ -33,13 +34,17 @@ namespace viz {
class SkiaOutputDeviceGL final : public SkiaOutputDevice {
public:
using ContextLostOnGpuCallback =
base::OnceCallback<void(ContextLostReason reason)>;
SkiaOutputDeviceGL(
gpu::MailboxManager* mailbox_manager,
gpu::SharedContextState* context_state,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::gles2::FeatureInfo> feature_info,
gpu::MemoryTracker* memory_tracker,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback,
ContextLostOnGpuCallback context_lost_on_gpu_callback);
~SkiaOutputDeviceGL() override;
bool supports_alpha() {
......@@ -91,6 +96,12 @@ class SkiaOutputDeviceGL final : public SkiaOutputDevice {
bool supports_alpha_ = false;
uint64_t backbuffer_estimated_size_ = 0;
#if defined(OS_WIN)
bool supports_overlays_ = false;
bool supports_direct_composition_ = false;
#endif
ContextLostOnGpuCallback context_lost_on_gpu_callback_;
base::WeakPtrFactory<SkiaOutputDeviceGL> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceGL);
......
......@@ -1532,11 +1532,17 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
supports_alpha_ = onscreen_device->supports_alpha();
output_device_ = std::move(onscreen_device);
} else {
SkiaOutputDeviceGL::ContextLostOnGpuCallback
context_lost_on_gpu_callback =
base::BindOnce(&SkiaOutputSurfaceImplOnGpu::MarkContextLost,
weak_ptr_factory_.GetWeakPtr());
std::unique_ptr<SkiaOutputDeviceGL> onscreen_device =
std::make_unique<SkiaOutputDeviceGL>(
dependency_->GetMailboxManager(), context_state_.get(),
gl_surface_, feature_info_, memory_tracker_.get(),
did_swap_buffer_complete_callback_);
did_swap_buffer_complete_callback_,
std::move(context_lost_on_gpu_callback));
supports_alpha_ = onscreen_device->supports_alpha();
output_device_ = std::move(onscreen_device);
}
......
......@@ -11235,6 +11235,8 @@ Called by update_net_error_codes.py.-->
<int value="11" label="CONTEXT_LOST_MAKECURRENT_FAILED"/>
<int value="12" label="CONTEXT_LOST_INVALID_GPU_MESSAGE"/>
<int value="13" label="CONTEXT_LOST_RESHAPE_FAILED"/>
<int value="14" label="CONTEXT_LOST_SET_DRAW_RECTANGLE_FAILED"/>
<int value="15" label="CONTEXT_LOST_DIRECT_COMPOSITION_OVERLAY_FAILED"/>
</enum>
<enum name="ContextMenuDelayedElementDetails">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment