Commit c9afe77b authored by sievers's avatar sievers Committed by Commit bot

Android: Second attempt at freeing GLHelper ashmem

This tears down the GLHelperHolder in RenderWidgetHostViewAndroid
when all activities get stopped.

But it only does this if there are no more readback
requests in flight.

BUG=641962,636630

Review-Url: https://codereview.chromium.org/2383613005
Cr-Commit-Position: refs/heads/master@{#423045}
parent 45c001dc
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <utility> #include <utility>
#include "base/android/application_status_listener.h"
#include "base/android/build_info.h" #include "base/android/build_info.h"
#include "base/android/context_utils.h" #include "base/android/context_utils.h"
#include "base/bind.h" #include "base/bind.h"
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
...@@ -100,6 +102,29 @@ const int kUndefinedCompositorFrameSinkId = -1; ...@@ -100,6 +102,29 @@ const int kUndefinedCompositorFrameSinkId = -1;
static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime"; static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
class PendingReadbackLock;
PendingReadbackLock* g_pending_readback_lock = nullptr;
class PendingReadbackLock : public base::RefCounted<PendingReadbackLock> {
public:
PendingReadbackLock() {
DCHECK_EQ(g_pending_readback_lock, nullptr);
g_pending_readback_lock = this;
}
private:
friend class base::RefCounted<PendingReadbackLock>;
~PendingReadbackLock() {
DCHECK_EQ(g_pending_readback_lock, this);
g_pending_readback_lock = nullptr;
}
};
using base::android::ApplicationState;
using base::android::ApplicationStatusListener;
class GLHelperHolder { class GLHelperHolder {
public: public:
static GLHelperHolder* Create(); static GLHelperHolder* Create();
...@@ -111,17 +136,32 @@ class GLHelperHolder { ...@@ -111,17 +136,32 @@ class GLHelperHolder {
return provider_->ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR; return provider_->ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
} }
void ReleaseIfPossible();
private: private:
GLHelperHolder() = default; GLHelperHolder();
void Initialize(); void Initialize();
void OnContextLost(); void OnContextLost();
void OnApplicationStatusChanged(ApplicationState new_state);
scoped_refptr<ContextProviderCommandBuffer> provider_; scoped_refptr<ContextProviderCommandBuffer> provider_;
std::unique_ptr<display_compositor::GLHelper> gl_helper_; std::unique_ptr<display_compositor::GLHelper> gl_helper_;
// Set to |false| if there are only stopped activities (or none).
bool has_running_or_paused_activities_;
std::unique_ptr<ApplicationStatusListener> app_status_listener_;
DISALLOW_COPY_AND_ASSIGN(GLHelperHolder); DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
}; };
GLHelperHolder::GLHelperHolder()
: has_running_or_paused_activities_(
(ApplicationStatusListener::GetState() ==
base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) ||
(ApplicationStatusListener::GetState() ==
base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES)) {}
GLHelperHolder* GLHelperHolder::Create() { GLHelperHolder* GLHelperHolder::Create() {
GLHelperHolder* holder = new GLHelperHolder; GLHelperHolder* holder = new GLHelperHolder;
holder->Initialize(); holder->Initialize();
...@@ -184,20 +224,43 @@ void GLHelperHolder::Initialize() { ...@@ -184,20 +224,43 @@ void GLHelperHolder::Initialize() {
base::Bind(&GLHelperHolder::OnContextLost, base::Unretained(this))); base::Bind(&GLHelperHolder::OnContextLost, base::Unretained(this)));
gl_helper_.reset(new display_compositor::GLHelper( gl_helper_.reset(new display_compositor::GLHelper(
provider_->ContextGL(), provider_->ContextSupport())); provider_->ContextGL(), provider_->ContextSupport()));
// Unretained() is safe because |this| owns the following two callbacks.
app_status_listener_.reset(new ApplicationStatusListener(base::Bind(
&GLHelperHolder::OnApplicationStatusChanged, base::Unretained(this))));
}
void GLHelperHolder::ReleaseIfPossible() {
if (!has_running_or_paused_activities_ && !g_pending_readback_lock) {
gl_helper_.reset();
provider_ = nullptr;
// Make sure this will get recreated on next use.
DCHECK(IsLost());
}
} }
void GLHelperHolder::OnContextLost() { void GLHelperHolder::OnContextLost() {
app_status_listener_.reset();
gl_helper_.reset();
// Need to post a task because the command buffer client cannot be deleted // Need to post a task because the command buffer client cannot be deleted
// from within this callback. // from within this callback.
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&RenderWidgetHostViewAndroid::OnContextLost)); FROM_HERE, base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
} }
// This can only be used for readback postprocessing. It may return null if the void GLHelperHolder::OnApplicationStatusChanged(ApplicationState new_state) {
// channel was lost and not reestablished yet. has_running_or_paused_activities_ =
display_compositor::GLHelper* GetPostReadbackGLHelper() { new_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES ||
new_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES;
ReleaseIfPossible();
}
GLHelperHolder* GetPostReadbackGLHelperHolder(bool create_if_necessary) {
static GLHelperHolder* g_readback_helper_holder = nullptr; static GLHelperHolder* g_readback_helper_holder = nullptr;
if (!create_if_necessary && !g_readback_helper_holder)
return nullptr;
if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) { if (g_readback_helper_holder && g_readback_helper_holder->IsLost()) {
delete g_readback_helper_holder; delete g_readback_helper_holder;
g_readback_helper_holder = nullptr; g_readback_helper_holder = nullptr;
...@@ -206,7 +269,21 @@ display_compositor::GLHelper* GetPostReadbackGLHelper() { ...@@ -206,7 +269,21 @@ display_compositor::GLHelper* GetPostReadbackGLHelper() {
if (!g_readback_helper_holder) if (!g_readback_helper_holder)
g_readback_helper_holder = GLHelperHolder::Create(); g_readback_helper_holder = GLHelperHolder::Create();
return g_readback_helper_holder->gl_helper(); return g_readback_helper_holder;
}
display_compositor::GLHelper* GetPostReadbackGLHelper() {
bool create_if_necessary = true;
return GetPostReadbackGLHelperHolder(create_if_necessary)->gl_helper();
}
void ReleaseGLHelper() {
bool create_if_necessary = false;
GLHelperHolder* holder = GetPostReadbackGLHelperHolder(create_if_necessary);
if (holder) {
holder->ReleaseIfPossible();
}
} }
void CopyFromCompositingSurfaceFinished( void CopyFromCompositingSurfaceFinished(
...@@ -215,6 +292,7 @@ void CopyFromCompositingSurfaceFinished( ...@@ -215,6 +292,7 @@ void CopyFromCompositingSurfaceFinished(
std::unique_ptr<SkBitmap> bitmap, std::unique_ptr<SkBitmap> bitmap,
const base::TimeTicks& start_time, const base::TimeTicks& start_time,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock, std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock,
scoped_refptr<PendingReadbackLock> readback_lock,
bool result) { bool result) {
TRACE_EVENT0( TRACE_EVENT0(
"cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished"); "cc", "RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceFinished");
...@@ -225,6 +303,12 @@ void CopyFromCompositingSurfaceFinished( ...@@ -225,6 +303,12 @@ void CopyFromCompositingSurfaceFinished(
if (gl_helper) if (gl_helper)
gl_helper->GenerateSyncToken(&sync_token); gl_helper->GenerateSyncToken(&sync_token);
} }
// PostTask() to make sure the |readback_lock| is released. Also do this
// synchronous GPU operation in a clean callstack.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&ReleaseGLHelper));
const bool lost_resource = !sync_token.HasData(); const bool lost_resource = !sync_token.HasData();
release_callback->Run(sync_token, lost_resource); release_callback->Run(sync_token, lost_resource);
UMA_HISTOGRAM_TIMES(kAsyncReadBackString, UMA_HISTOGRAM_TIMES(kAsyncReadBackString,
...@@ -268,7 +352,67 @@ gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) { ...@@ -268,7 +352,67 @@ gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) {
return rect; return rect;
} }
} // anonymous namespace // TODO(wjmaclean): There is significant overlap between
// PrepareTextureCopyOutputResult and CopyFromCompositingSurfaceFinished in
// this file, and the versions in surface_utils.cc. They should
// be merged. See https://crbug.com/582955
void PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
SkColorType color_type,
const base::TimeTicks& start_time,
const ReadbackRequestCallback& callback,
scoped_refptr<PendingReadbackLock> readback_lock,
std::unique_ptr<cc::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, SkBitmap(), READBACK_FAILED));
TRACE_EVENT0("cc",
"RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
return;
cc::TextureMailbox texture_mailbox;
std::unique_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture())
return;
display_compositor::GLHelper* gl_helper = GetPostReadbackGLHelper();
if (!gl_helper)
return;
if (!gl_helper->IsReadbackConfigSupported(color_type))
color_type = kRGBA_8888_SkColorType;
gfx::Size output_size_in_pixel;
if (dst_size_in_pixel.IsEmpty())
output_size_in_pixel = result->size();
else
output_size_in_pixel = dst_size_in_pixel;
std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
output_size_in_pixel.height(),
color_type,
kOpaque_SkAlphaType))) {
scoped_callback_runner.ReplaceClosure(
base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
return;
}
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*bitmap));
uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
gfx::Rect(result->size()), output_size_in_pixel, pixels, color_type,
base::Bind(&CopyFromCompositingSurfaceFinished, callback,
base::Passed(&release_callback), base::Passed(&bitmap),
start_time, base::Passed(&bitmap_pixels_lock), readback_lock),
display_compositor::GLHelper::SCALER_QUALITY_GOOD);
}
} // namespace
RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo(
uint32_t compositor_frame_sink_id, uint32_t compositor_frame_sink_id,
...@@ -864,10 +1008,13 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface( ...@@ -864,10 +1008,13 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
content_view_core_->GetWindowAndroid()->GetCompositor(); content_view_core_->GetWindowAndroid()->GetCompositor();
DCHECK(compositor); DCHECK(compositor);
DCHECK(delegated_frame_host_); DCHECK(delegated_frame_host_);
scoped_refptr<PendingReadbackLock> readback_lock(
g_pending_readback_lock ? g_pending_readback_lock
: new PendingReadbackLock);
delegated_frame_host_->RequestCopyOfSurface( delegated_frame_host_->RequestCopyOfSurface(
compositor, src_subrect_in_pixel, compositor, src_subrect_in_pixel,
base::Bind(&PrepareTextureCopyOutputResult, dst_size_in_pixel, base::Bind(&PrepareTextureCopyOutputResult, dst_size_in_pixel,
preferred_color_type, start_time, callback)); preferred_color_type, start_time, callback, readback_lock));
} }
void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame( void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
...@@ -1791,67 +1938,6 @@ void RenderWidgetHostViewAndroid::OnLostResources() { ...@@ -1791,67 +1938,6 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
DCHECK(ack_callbacks_.empty()); DCHECK(ack_callbacks_.empty());
} }
// TODO(wjmaclean): There is significant overlap between
// PrepareTextureCopyOutputResult and CopyFromCompositingSurfaceFinished in
// this file, and the versions in surface_utils.cc. They should
// be merged. See https://crbug.com/582955
// static
void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
SkColorType color_type,
const base::TimeTicks& start_time,
const ReadbackRequestCallback& callback,
std::unique_ptr<cc::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, SkBitmap(), READBACK_FAILED));
TRACE_EVENT0("cc",
"RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult");
if (!result->HasTexture() || result->IsEmpty() || result->size().IsEmpty())
return;
cc::TextureMailbox texture_mailbox;
std::unique_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture())
return;
display_compositor::GLHelper* gl_helper = GetPostReadbackGLHelper();
if (!gl_helper)
return;
if (!gl_helper->IsReadbackConfigSupported(color_type))
color_type = kRGBA_8888_SkColorType;
gfx::Size output_size_in_pixel;
if (dst_size_in_pixel.IsEmpty())
output_size_in_pixel = result->size();
else
output_size_in_pixel = dst_size_in_pixel;
std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(),
output_size_in_pixel.height(),
color_type,
kOpaque_SkAlphaType))) {
scoped_callback_runner.ReplaceClosure(
base::Bind(callback, SkBitmap(), READBACK_BITMAP_ALLOCATION_FAILURE));
return;
}
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*bitmap));
uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
gfx::Rect(result->size()), output_size_in_pixel, pixels, color_type,
base::Bind(&CopyFromCompositingSurfaceFinished, callback,
base::Passed(&release_callback), base::Passed(&bitmap),
start_time, base::Passed(&bitmap_pixels_lock)),
display_compositor::GLHelper::SCALER_QUALITY_GOOD);
}
void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0, void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0,
float y0, float y0,
float x1, float x1,
......
...@@ -262,15 +262,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid ...@@ -262,15 +262,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void UpdateBackgroundColor(SkColor color); void UpdateBackgroundColor(SkColor color);
// Called after async screenshot task completes. Scales and crops the result
// of the copy.
static void PrepareTextureCopyOutputResult(
const gfx::Size& dst_size_in_pixel,
SkColorType color_type,
const base::TimeTicks& start_time,
const ReadbackRequestCallback& callback,
std::unique_ptr<cc::CopyOutputResult> result);
// DevTools ScreenCast support for Android WebView. // DevTools ScreenCast support for Android WebView.
void SynchronousCopyContents(const gfx::Rect& src_subrect_in_pixel, void SynchronousCopyContents(const gfx::Rect& src_subrect_in_pixel,
const gfx::Size& dst_size_in_pixel, const gfx::Size& dst_size_in_pixel,
......
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