summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorccameron <ccameron@chromium.org>2015-08-10 18:41:45 -0700
committerCommit bot <commit-bot@chromium.org>2015-08-11 01:42:49 +0000
commitaae371ca10e047d9b192acf869f8ff9601d3cdf7 (patch)
treee769084bff1f212d7e076e0b0c6eba1dbe9c1122
parentc1b891418bbfafcc620ca50805c0b7d610ba4cff (diff)
downloadchromium_src-aae371ca10e047d9b192acf869f8ff9601d3cdf7.zip
chromium_src-aae371ca10e047d9b192acf869f8ff9601d3cdf7.tar.gz
chromium_src-aae371ca10e047d9b192acf869f8ff9601d3cdf7.tar.bz2
Mac: Enable partial swap
This is pretty trivial when using the overlay path. Just create a new layer for the damage. The partial damage layer can be created, removed, or resized with basically no cost, because its backing is the already-existing IOSurface. As each partial swap comes in, union the existing overlay layer's rect with the rect of the new partial swap. If this grows "too big", then do a full swap (which clears the accumulated union). The constants here are pretty arbitrary. BUG=474299 Review URL: https://codereview.chromium.org/1271123002 Cr-Commit-Position: refs/heads/master@{#342771}
-rw-r--r--content/common/gpu/image_transport_surface_overlay_mac.h5
-rw-r--r--content/common/gpu/image_transport_surface_overlay_mac.mm81
-rw-r--r--ui/gfx/geometry/rect_f.cc16
-rw-r--r--ui/gfx/geometry/rect_f.h10
4 files changed, 106 insertions, 6 deletions
diff --git a/content/common/gpu/image_transport_surface_overlay_mac.h b/content/common/gpu/image_transport_surface_overlay_mac.h
index 022fbb4..1265cc4 100644
--- a/content/common/gpu/image_transport_surface_overlay_mac.h
+++ b/content/common/gpu/image_transport_surface_overlay_mac.h
@@ -79,6 +79,7 @@ class ImageTransportSurfaceOverlayMac : public gfx::GLSurface,
scoped_ptr<ImageTransportHelper> helper_;
base::scoped_nsobject<CAContext> ca_context_;
base::scoped_nsobject<CALayer> layer_;
+ base::scoped_nsobject<CALayer> partial_damage_layer_;
gfx::Size pixel_size_;
float scale_factor_;
@@ -94,6 +95,10 @@ class ImageTransportSurfaceOverlayMac : public gfx::GLSurface,
// every swap and also by a callback.
std::deque<linked_ptr<PendingSwap>> pending_swaps_;
+ // The union of the damage rects of SwapBuffersInternal since the last
+ // non-partial swap.
+ gfx::Rect accumulated_partial_damage_pixel_rect_;
+
// The display link used to compute the time for callbacks.
scoped_refptr<ui::DisplayLinkMac> display_link_mac_;
diff --git a/content/common/gpu/image_transport_surface_overlay_mac.mm b/content/common/gpu/image_transport_surface_overlay_mac.mm
index 2e6911c..8f222c5 100644
--- a/content/common/gpu/image_transport_surface_overlay_mac.mm
+++ b/content/common/gpu/image_transport_surface_overlay_mac.mm
@@ -64,6 +64,10 @@ class ImageTransportSurfaceOverlayMac::PendingSwap {
float scale_factor;
std::vector<ui::LatencyInfo> latency_info;
+ // If true, the partial damage rect for the frame.
+ bool use_partial_damage;
+ gfx::Rect pixel_partial_damage_rect;
+
// The IOSurface with new content for this swap.
base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
@@ -105,6 +109,9 @@ bool ImageTransportSurfaceOverlayMac::Initialize() {
[layer_ setGeometryFlipped:YES];
[layer_ setOpaque:YES];
[ca_context_ setLayer:layer_];
+
+ partial_damage_layer_.reset([[CALayer alloc] init]);
+ [partial_damage_layer_ setOpaque:YES];
return true;
}
@@ -180,6 +187,36 @@ gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal(
new_swap->latest_allowed_draw_time = now;
}
+ // Determine if this will be a full or partial damage, and compute the rects
+ // for the damage.
+ {
+ // Grow the partial damage rect to include the new damage.
+ accumulated_partial_damage_pixel_rect_.Union(pixel_damage_rect);
+ // Compute the fraction of the full layer that has been damaged. If this
+ // fraction is very large (>85%), just damage the full layer, and don't
+ // bother with the partial layer.
+ const double kMaximumFractionOfFullDamage = 0.85;
+ double fraction_of_full_damage =
+ accumulated_partial_damage_pixel_rect_.size().GetArea() /
+ static_cast<double>(pixel_size_.GetArea());
+ // Compute the fraction of the accumulated partial damage rect that has been
+ // damaged. If this gets too small (<75%), just re-damage the full window,
+ // so we can re-create a smaller partial damage layer next frame.
+ const double kMinimumFractionOfPartialDamage = 0.75;
+ double fraction_of_partial_damage =
+ pixel_damage_rect.size().GetArea() / static_cast<double>(
+ accumulated_partial_damage_pixel_rect_.size().GetArea());
+ if (fraction_of_full_damage < kMaximumFractionOfFullDamage &&
+ fraction_of_partial_damage > kMinimumFractionOfPartialDamage) {
+ new_swap->use_partial_damage = true;
+ new_swap->pixel_partial_damage_rect =
+ accumulated_partial_damage_pixel_rect_;
+ } else {
+ new_swap->use_partial_damage = false;
+ accumulated_partial_damage_pixel_rect_ = gfx::Rect();
+ }
+ }
+
pending_swaps_.push_back(new_swap);
PostCheckPendingSwapsCallbackIfNeeded(now);
return gfx::SwapResult::SWAP_ACK;
@@ -246,12 +283,44 @@ void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() {
ScopedCAActionDisabler disabler;
id new_contents = static_cast<id>(swap->io_surface.get());
- [layer_ setContents:new_contents];
-
- CGRect new_frame = gfx::ConvertRectToDIP(
- swap->scale_factor, gfx::Rect(swap->pixel_size)).ToCGRect();
- if (!CGRectEqualToRect([layer_ frame], new_frame))
- [layer_ setFrame:new_frame];
+ if (swap->use_partial_damage) {
+ if (![partial_damage_layer_ superlayer])
+ [layer_ addSublayer:partial_damage_layer_];
+ [partial_damage_layer_ setContents:new_contents];
+
+ CGRect new_frame = gfx::ConvertRectToDIP(
+ swap->scale_factor, swap->pixel_partial_damage_rect).ToCGRect();
+ if (!CGRectEqualToRect([partial_damage_layer_ frame], new_frame))
+ [partial_damage_layer_ setFrame:new_frame];
+
+ gfx::RectF contents_rect =
+ gfx::RectF(swap->pixel_partial_damage_rect);
+ contents_rect.Scale(
+ 1. / swap->pixel_size.width(), 1. / swap->pixel_size.height());
+ CGRect cg_contents_rect = CGRectMake(
+ contents_rect.x(), contents_rect.y(),
+ contents_rect.width(), contents_rect.height());
+ [partial_damage_layer_ setContentsRect:cg_contents_rect];
+ } else {
+ // Remove the partial damage layer.
+ if ([partial_damage_layer_ superlayer]) {
+ [partial_damage_layer_ removeFromSuperlayer];
+ [partial_damage_layer_ setContents:nil];
+ }
+
+ // Note that calling setContents with the same IOSurface twice will result
+ // in the screen not being updated, even if the IOSurface's content has
+ // changed. Avoid this by calling setContentsChanged.
+ if ([layer_ contents] == new_contents)
+ [layer_ setContentsChanged];
+ else
+ [layer_ setContents:new_contents];
+
+ CGRect new_frame = gfx::ConvertRectToDIP(
+ swap->scale_factor, gfx::Rect(swap->pixel_size)).ToCGRect();
+ if (!CGRectEqualToRect([layer_ frame], new_frame))
+ [layer_ setFrame:new_frame];
+ }
}
// Send acknowledgement to the browser.
diff --git a/ui/gfx/geometry/rect_f.cc b/ui/gfx/geometry/rect_f.cc
index c87ea3d..a15bdf3 100644
--- a/ui/gfx/geometry/rect_f.cc
+++ b/ui/gfx/geometry/rect_f.cc
@@ -6,6 +6,12 @@
#include <algorithm>
+#if defined(OS_IOS)
+#include <CoreGraphics/CoreGraphics.h>
+#elif defined(OS_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "ui/gfx/geometry/insets_f.h"
@@ -24,6 +30,16 @@ static void AdjustAlongAxis(float dst_origin,
*origin = std::min(dst_origin + dst_size, *origin + *size) - *size;
}
+#if defined(OS_MACOSX)
+RectF::RectF(const CGRect& r)
+ : origin_(r.origin.x, r.origin.y), size_(r.size.width, r.size.height) {
+}
+
+CGRect RectF::ToCGRect() const {
+ return CGRectMake(x(), y(), width(), height());
+}
+#endif
+
void RectF::Inset(const InsetsF& insets) {
Inset(insets.left(), insets.top(), insets.right(), insets.bottom());
}
diff --git a/ui/gfx/geometry/rect_f.h b/ui/gfx/geometry/rect_f.h
index dc233a7..3b132667e 100644
--- a/ui/gfx/geometry/rect_f.h
+++ b/ui/gfx/geometry/rect_f.h
@@ -12,6 +12,10 @@
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
+#if defined(OS_MACOSX)
+typedef struct CGRect CGRect;
+#endif
+
namespace gfx {
class InsetsF;
@@ -27,6 +31,12 @@ class GFX_EXPORT RectF {
RectF(const PointF& origin, const SizeF& size)
: origin_(origin), size_(size) {}
+#if defined(OS_MACOSX)
+ explicit RectF(const CGRect& r);
+ // Construct an equivalent CoreGraphics object.
+ CGRect ToCGRect() const;
+#endif
+
~RectF() {}
float x() const { return origin_.x(); }