summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-05 18:50:12 +0000
committerccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-05 18:50:12 +0000
commit30ca75e25a30803e11bfa0673556dcb6731adeca (patch)
treec9dfefd740749e98893f7603c6ff908b8f7b0b6c
parentb9c26780e3d0637b920de98a0a7b6d2bad544fbc (diff)
downloadchromium_src-30ca75e25a30803e11bfa0673556dcb6731adeca.zip
chromium_src-30ca75e25a30803e11bfa0673556dcb6731adeca.tar.gz
chromium_src-30ca75e25a30803e11bfa0673556dcb6731adeca.tar.bz2
Merge 265842 "CoreAnimation: Evict IOSurfaces after use"
> CoreAnimation: Evict IOSurfaces after use > > CoreAnimation stores contents in CALayers, so it is > not necessary to keep around IOSurfaces after they > have been drawn (except in the case of being > backgrounded and then made visible again). > > Discard these IOSurfaces if we have more than 8 of > them around. Only discard surfaces when they have > been drawn and the have no pending copy requests. > > This relieves an increase in virtual address space used > by CoreAnimation. > > Also move where size and scale factor are assigned so > that the size of the IOSurface can be un-set when it > is freed. > > BUG=364808 > > Review URL: https://codereview.chromium.org/243133008 TBR=ccameron@chromium.org Review URL: https://codereview.chromium.org/266273002 git-svn-id: svn://svn.chromium.org/chrome/branches/1916/src@268233 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/compositing_iosurface_layer_mac.mm3
-rw-r--r--content/browser/renderer_host/compositing_iosurface_mac.h24
-rw-r--r--content/browser/renderer_host/compositing_iosurface_mac.mm105
-rw-r--r--content/browser/renderer_host/render_widget_host_view_mac.mm4
4 files changed, 123 insertions, 13 deletions
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
index 08d3d4d..eaa8bbb 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
@@ -116,7 +116,8 @@
if (!context_ ||
(context_ && context_->cgl_context() != glContext) ||
!renderWidgetHostView_ ||
- !renderWidgetHostView_->compositing_iosurface_) {
+ !renderWidgetHostView_->compositing_iosurface_ ||
+ !renderWidgetHostView_->compositing_iosurface_->HasIOSurface()) {
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
return;
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index 78401ab..db228089 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -6,12 +6,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITING_IOSURFACE_MAC_H_
#include <deque>
+#include <list>
#include <vector>
#import <Cocoa/Cocoa.h>
#include <QuartzCore/QuartzCore.h>
#include "base/callback.h"
+#include "base/lazy_instance.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
@@ -213,6 +215,8 @@ class CompositingIOSurfaceMac {
// Returns true if IOSurface is ready to render. False otherwise.
bool MapIOSurfaceToTextureWithContextCurrent(
const scoped_refptr<CompositingIOSurfaceContext>& current_context,
+ const gfx::Size pixel_size,
+ float scale_factor,
uint64 io_surface_handle) WARN_UNUSED_RESULT;
void UnrefIOSurfaceWithContextCurrent();
@@ -303,6 +307,26 @@ class CompositingIOSurfaceMac {
// Error saved by GetAndSaveGLError
GLint gl_error_;
+
+ // Aggressive IOSurface eviction logic. When using CoreAnimation, IOSurfaces
+ // are used only transiently to transfer from the GPU process to the browser
+ // process. Once the IOSurface has been drawn to its CALayer, the CALayer
+ // will not need updating again until its view is hidden and re-shown.
+ // Aggressively evict surfaces when more than 8 (the number allowed by the
+ // memory manager for fast tab switching) are allocated.
+ enum {
+ kMaximumUnevictedSurfaces = 8,
+ };
+ typedef std::list<CompositingIOSurfaceMac*> EvictionQueue;
+ void EvictionMarkUpdated();
+ void EvictionMarkEvicted();
+ EvictionQueue::iterator eviction_queue_iterator_;
+ bool eviction_has_been_drawn_since_updated_;
+
+ static void EvictionScheduleDoEvict();
+ static void EvictionDoEvict();
+ static base::LazyInstance<EvictionQueue> eviction_queue_;
+ static bool eviction_scheduled_;
};
} // namespace content
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index 45f4758..d3574c7 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -253,7 +253,9 @@ CompositingIOSurfaceMac::CompositingIOSurfaceMac(
base::Unretained(this),
false),
true),
- gl_error_(GL_NO_ERROR) {
+ gl_error_(GL_NO_ERROR),
+ eviction_queue_iterator_(eviction_queue_.Get().end()),
+ eviction_has_been_drawn_since_updated_(false) {
CHECK(offscreen_context_);
}
@@ -266,6 +268,7 @@ CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
UnrefIOSurfaceWithContextCurrent();
}
offscreen_context_ = NULL;
+ DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
}
bool CompositingIOSurfaceMac::SetIOSurfaceWithContextCurrent(
@@ -273,12 +276,9 @@ bool CompositingIOSurfaceMac::SetIOSurfaceWithContextCurrent(
uint64 io_surface_handle,
const gfx::Size& size,
float scale_factor) {
- pixel_io_surface_size_ = size;
- scale_factor_ = scale_factor;
- dip_io_surface_size_ = gfx::ToFlooredSize(
- gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_));
bool result = MapIOSurfaceToTextureWithContextCurrent(
- current_context, io_surface_handle);
+ current_context, size, scale_factor, io_surface_handle);
+ EvictionMarkUpdated();
return result;
}
@@ -401,6 +401,7 @@ bool CompositingIOSurfaceMac::DrawIOSurface(
glGetError();
}
+ eviction_has_been_drawn_since_updated_ = true;
return result;
}
@@ -475,12 +476,24 @@ base::Closure CompositingIOSurfaceMac::CopyToVideoFrameWithinContext(
bool CompositingIOSurfaceMac::MapIOSurfaceToTextureWithContextCurrent(
const scoped_refptr<CompositingIOSurfaceContext>& current_context,
+ const gfx::Size pixel_size,
+ float scale_factor,
uint64 io_surface_handle) {
- if (io_surface_.get() && io_surface_handle == io_surface_handle_)
- return true;
-
TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
- UnrefIOSurfaceWithContextCurrent();
+
+ if (!io_surface_ || io_surface_handle != io_surface_handle_)
+ UnrefIOSurfaceWithContextCurrent();
+
+ pixel_io_surface_size_ = pixel_size;
+ scale_factor_ = scale_factor;
+ dip_io_surface_size_ = gfx::ToFlooredSize(
+ gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_));
+
+ // Early-out if the IOSurface has not changed. Note that because IOSurface
+ // sizes are rounded, the same IOSurface may have two different sizes
+ // associated with it.
+ if (io_surface_ && io_surface_handle == io_surface_handle_)
+ return true;
io_surface_.reset(io_surface_support_->IOSurfaceLookup(
static_cast<uint32>(io_surface_handle)));
@@ -555,13 +568,17 @@ void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() {
glDeleteTextures(1, &texture_);
texture_ = 0;
}
-
+ pixel_io_surface_size_ = gfx::Size();
+ scale_factor_ = 1;
+ dip_io_surface_size_ = gfx::Size();
io_surface_.reset();
// Forget the ID, because even if it is still around when we want to use it
// again, OSX may have reused the same ID for a new tab and we don't want to
// blit random tab contents.
io_surface_handle_ = 0;
+
+ EvictionMarkEvicted();
}
bool CompositingIOSurfaceMac::IsAsynchronousReadbackSupported() {
@@ -918,4 +935,70 @@ GLenum CompositingIOSurfaceMac::GetAndSaveGLError() {
return gl_error;
}
+void CompositingIOSurfaceMac::EvictionMarkUpdated() {
+ EvictionMarkEvicted();
+ eviction_queue_.Get().push_back(this);
+ eviction_queue_iterator_ = --eviction_queue_.Get().end();
+ eviction_has_been_drawn_since_updated_ = false;
+ EvictionScheduleDoEvict();
+}
+
+void CompositingIOSurfaceMac::EvictionMarkEvicted() {
+ if (eviction_queue_iterator_ == eviction_queue_.Get().end())
+ return;
+ eviction_queue_.Get().erase(eviction_queue_iterator_);
+ eviction_queue_iterator_ = eviction_queue_.Get().end();
+ eviction_has_been_drawn_since_updated_ = false;
+}
+
+// static
+void CompositingIOSurfaceMac::EvictionScheduleDoEvict() {
+ if (GetCoreAnimationStatus() == CORE_ANIMATION_DISABLED)
+ return;
+ if (eviction_scheduled_)
+ return;
+ if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
+ return;
+
+ eviction_scheduled_ = true;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&CompositingIOSurfaceMac::EvictionDoEvict));
+}
+
+// static
+void CompositingIOSurfaceMac::EvictionDoEvict() {
+ eviction_scheduled_ = false;
+ // Walk the list of allocated surfaces from least recently used to most
+ // recently used.
+ for (EvictionQueue::iterator it = eviction_queue_.Get().begin();
+ it != eviction_queue_.Get().end();) {
+ CompositingIOSurfaceMac* surface = *it;
+ ++it;
+
+ // If the number of IOSurfaces allocated is less than the threshold,
+ // stop walking the list of surfaces.
+ if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
+ break;
+
+ // Don't evict anything that has not yet been drawn.
+ if (!surface->eviction_has_been_drawn_since_updated_)
+ continue;
+
+ // Don't evict anything with pending copy requests.
+ if (!surface->copy_requests_.empty())
+ continue;
+
+ // Evict the surface.
+ surface->UnrefIOSurface();
+ }
+}
+
+// static
+base::LazyInstance<CompositingIOSurfaceMac::EvictionQueue>
+ CompositingIOSurfaceMac::eviction_queue_;
+
+// static
+bool CompositingIOSurfaceMac::eviction_scheduled_ = false;
+
} // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 9cdbc07..f807fa2 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -2268,7 +2268,9 @@ void RenderWidgetHostViewMac::LayoutLayers() {
EnsureCompositedIOSurfaceLayer();
}
}
- if (compositing_iosurface_ && compositing_iosurface_layer_) {
+ if (compositing_iosurface_ &&
+ compositing_iosurface_->HasIOSurface() &&
+ compositing_iosurface_layer_) {
CGRect layer_bounds = CGRectMake(
0,
0,