summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-31 21:39:22 +0000
committeramanda@chromium.org <amanda@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-31 21:39:22 +0000
commita72c6bb647954c92109a57b3edbb789195edda57 (patch)
tree7d7666fb98785b9bcfc784f61532abd7a485fad1 /chrome
parent3771f9bcce1d418162656f6b802f86784c998353 (diff)
downloadchromium_src-a72c6bb647954c92109a57b3edbb789195edda57.zip
chromium_src-a72c6bb647954c92109a57b3edbb789195edda57.tar.gz
chromium_src-a72c6bb647954c92109a57b3edbb789195edda57.tar.bz2
Update BackingStore to handle the case where our Cocoa view has
not been inserted into a window yet. BUG=20009 TEST=tabs opened in the background should not be blank when you switch to them. Review URL: http://codereview.chromium.org/175027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24941 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/renderer_host/backing_store.h5
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.mm128
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm26
3 files changed, 119 insertions, 40 deletions
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index aea197b..df34eee 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -64,6 +64,10 @@ class BackingStore {
// A CGLayer that stores the contents of the backing store, cached in GPU
// memory if possible.
CGLayerRef cg_layer() { return cg_layer_; }
+ // A CGBitmapContext that stores the contents of the backing store if the
+ // corresponding Cocoa view has not been inserted into an NSWindow yet.
+ CGContextRef cg_bitmap() { return cg_bitmap_; }
+
// Paint the layer into a graphics context--if the target is a window,
// this should be a GPU->GPU copy (and therefore very fast).
void PaintToRect(const gfx::Rect& dest_rect, CGContextRef target);
@@ -118,6 +122,7 @@ class BackingStore {
// Number of bits per pixel of the screen.
int color_depth_;
#elif defined(OS_MACOSX)
+ scoped_cftyperef<CGContextRef> cg_bitmap_;
scoped_cftyperef<CGLayerRef> cg_layer_;
#elif defined(OS_LINUX)
// Paints the bitmap from the renderer onto the backing store without
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index b1f2b92..c877a52 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -29,11 +29,20 @@ BackingStore::BackingStore(RenderWidgetHost* widget, const gfx::Size& size)
// window, so extract a CGContext corresponding to that window that we can
// pass to CGLayerCreateWithContext.
NSWindow* containing_window = [widget->view()->GetNativeView() window];
- if (!containing_window) // possible in unit tests
- return;
- CGContextRef context = static_cast<CGContextRef>([[containing_window graphicsContext] graphicsPort]);
- CGLayerRef layer = CGLayerCreateWithContext(context, size.ToCGSize(), NULL);
- cg_layer_.reset(layer);
+ if (!containing_window) {
+ // If we are not in a containing window yet, create a CGBitmapContext
+ // to use as a stand-in for the layer.
+ scoped_cftyperef<CGColorSpaceRef>
+ color_space(CGColorSpaceCreateDeviceRGB());
+ cg_bitmap_.reset(CGBitmapContextCreate(NULL, size.width(), size.height(),
+ 8, size.width() * 8, color_space,
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ } else {
+ CGContextRef context = static_cast<CGContextRef>(
+ [[containing_window graphicsContext] graphicsPort]);
+ CGLayerRef layer = CGLayerCreateWithContext(context, size.ToCGSize(), NULL);
+ cg_layer_.reset(layer);
+ }
}
BackingStore::~BackingStore() {
@@ -48,24 +57,51 @@ size_t BackingStore::MemorySize() {
void BackingStore::PaintRect(base::ProcessHandle process,
TransportDIB* bitmap,
const gfx::Rect& bitmap_rect) {
- if (!cg_layer()) return;
-
scoped_cftyperef<CGColorSpaceRef> color_space(CGColorSpaceCreateDeviceRGB());
scoped_cftyperef<CGDataProviderRef> data_provider(
CGDataProviderCreateWithData(NULL, bitmap->memory(),
- bitmap_rect.width() * bitmap_rect.height() * 4, NULL));
- scoped_cftyperef<CGImageRef> image(CGImageCreate(bitmap_rect.width(),
- bitmap_rect.height(), 8, 32, 4 * bitmap_rect.width(), color_space,
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, data_provider,
- NULL, false, kCGRenderingIntentDefault));
+ bitmap_rect.width() * bitmap_rect.height() * 4, NULL));
+ scoped_cftyperef<CGImageRef> image(
+ CGImageCreate(bitmap_rect.width(), bitmap_rect.height(), 8, 32,
+ 4 * bitmap_rect.width(), color_space,
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+ data_provider, NULL, false, kCGRenderingIntentDefault));
- // The CGLayer's origin is in the lower left, but flipping the CTM would
- // cause the image to get drawn upside down. So we move the rectangle
- // to the right position before drawing the image.
- CGContextRef layer = CGLayerGetContext(cg_layer());
- gfx::Rect paint_rect = bitmap_rect;
- paint_rect.set_y(size_.height() - bitmap_rect.bottom());
- CGContextDrawImage(layer, paint_rect.ToCGRect(), image);
+ if (!cg_layer()) {
+ // we don't have a CGLayer yet, so see if we can create one.
+ NSWindow* containing_window =
+ [render_widget_host()->view()->GetNativeView() window];
+ if (containing_window) {
+ CGContextRef context = static_cast<CGContextRef>(
+ [[containing_window graphicsContext] graphicsPort]);
+ CGLayerRef layer =
+ CGLayerCreateWithContext(context, size().ToCGSize(), NULL);
+ cg_layer_.reset(layer);
+ // now that we have a layer, copy the cached image into it
+ scoped_cftyperef<CGImageRef> bitmap_image(
+ CGBitmapContextCreateImage(cg_bitmap_));
+ CGContextDrawImage(CGLayerGetContext(layer),
+ CGRectMake(0, 0, size().width(), size().height()),
+ bitmap_image);
+ // Discard the cache bitmap, since we no longer need it.
+ cg_bitmap_.reset(NULL);
+ }
+ }
+
+ if (cg_layer()) {
+ // The CGLayer's origin is in the lower left, but flipping the CTM would
+ // cause the image to get drawn upside down. So we move the rectangle
+ // to the right position before drawing the image.
+ CGContextRef layer = CGLayerGetContext(cg_layer());
+ gfx::Rect paint_rect = bitmap_rect;
+ paint_rect.set_y(size_.height() - bitmap_rect.bottom());
+ CGContextDrawImage(layer, paint_rect.ToCGRect(), image);
+ } else {
+ // The layer hasn't been created yet, so draw into the cache bitmap.
+ gfx::Rect paint_rect = bitmap_rect;
+ paint_rect.set_y(size_.height() - bitmap_rect.bottom());
+ CGContextDrawImage(cg_bitmap_, paint_rect.ToCGRect(), image);
+ }
}
// Scroll the contents of our CGLayer
@@ -93,21 +129,47 @@ void BackingStore::ScrollRect(base::ProcessHandle process,
if ((dx && abs(dx) < layer_size.width) ||
(dy && abs(dy) < layer_size.height)) {
- //
- scoped_cftyperef<CGLayerRef> new_layer(CGLayerCreateWithContext(
- CGLayerGetContext(cg_layer()), layer_size, NULL));
- CGContextRef layer = CGLayerGetContext(new_layer);
- CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer());
- CGContextSaveGState(layer);
- CGContextClipToRect(layer, CGRectMake(clip_rect.x(),
- size_.height() - clip_rect.bottom(),
- clip_rect.width(),
- clip_rect.height()));
- CGContextDrawLayerAtPoint(layer, CGPointMake(dx, -dy), cg_layer());
- CGContextRestoreGState(layer);
- cg_layer_.swap(new_layer);
+ if (cg_layer()) {
+ CGContextRef context = CGLayerGetContext(cg_layer());
+ scoped_cftyperef<CGLayerRef> new_layer(
+ CGLayerCreateWithContext(context, layer_size, NULL));
+ CGContextRef layer = CGLayerGetContext(new_layer);
+ CGContextDrawLayerAtPoint(layer, CGPointMake(0, 0), cg_layer());
+ CGContextSaveGState(layer);
+ CGContextClipToRect(layer, CGRectMake(clip_rect.x(),
+ size_.height() - clip_rect.bottom(),
+ clip_rect.width(),
+ clip_rect.height()));
+ CGContextDrawLayerAtPoint(layer, CGPointMake(dx, -dy), cg_layer());
+ CGContextRestoreGState(layer);
+ cg_layer_.swap(new_layer);
+ } else {
+ // We don't have a layer, so scroll the contents of the CGBitmapContext.
+ scoped_cftyperef<CGColorSpaceRef>
+ color_space(CGColorSpaceCreateDeviceRGB());
+ scoped_cftyperef<CGContextRef> new_bitmap(
+ CGBitmapContextCreate(NULL, size_.width(), size_.height(), 8,
+ size_.width() * 8, color_space,
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ scoped_cftyperef<CGImageRef> bitmap_image(
+ CGBitmapContextCreateImage(cg_bitmap_));
+ CGContextDrawImage(new_bitmap,
+ CGRectMake(0, 0, size_.width(), size_.height()),
+ bitmap_image);
+ CGContextSaveGState(new_bitmap);
+ CGContextClipToRect(new_bitmap,
+ CGRectMake(clip_rect.x(),
+ size_.height() - clip_rect.bottom(),
+ clip_rect.width(),
+ clip_rect.height()));
+ CGContextDrawImage(new_bitmap,
+ CGRectMake(dx, -dy, size_.width(), size_.height()),
+ bitmap_image);
+ CGContextRestoreGState(new_bitmap);
+ cg_bitmap_.swap(new_bitmap);
+ }
}
- // Now paint the new bitmap data into the CGLayer
+ // Now paint the new bitmap data
PaintRect(process, bitmap, bitmap_rect);
return;
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index af3ce8a..1010475 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -549,7 +549,7 @@ void RenderWidgetHostViewMac::SetActive(bool active) {
renderWidgetHostView_->about_to_validate_and_paint_ = false;
dirtyRect = renderWidgetHostView_->invalid_rect_;
- if (backing_store && backing_store->cg_layer()) {
+ if (backing_store) {
NSRect view_bounds = [self bounds];
gfx::Rect damaged_rect([self NSRectToRect:dirtyRect]);
@@ -559,12 +559,24 @@ void RenderWidgetHostViewMac::SetActive(bool active) {
gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect);
if (!paint_rect.IsEmpty()) {
- CGContextRef context = static_cast<CGContextRef>(
- [[NSGraphicsContext currentContext] graphicsPort]);
-
- // TODO: add clipping to dirtyRect if it improves drawing performance.
- CGContextDrawLayerAtPoint(context, CGPointMake(0.0, 0.0),
- backing_store->cg_layer());
+ // if we have a CGLayer, draw that into the window
+ if (backing_store->cg_layer()) {
+ CGContextRef context = static_cast<CGContextRef>(
+ [[NSGraphicsContext currentContext] graphicsPort]);
+
+ // TODO: add clipping to dirtyRect if it improves drawing performance.
+ CGContextDrawLayerAtPoint(context, CGPointMake(0.0, 0.0),
+ backing_store->cg_layer());
+ } else {
+ // if we haven't created a layer yet, draw the cached bitmap into
+ // the window. The CGLayer will be created the next time the renderer
+ // paints.
+ CGContextRef context = static_cast<CGContextRef>(
+ [[NSGraphicsContext currentContext] graphicsPort]);
+ scoped_cftyperef<CGImageRef> image(
+ CGBitmapContextCreateImage(backing_store->cg_bitmap()));
+ CGContextDrawImage(context, bitmap_rect.ToCGRect(), image);
+ }
}
// Fill the remaining portion of the damaged_rect with white