Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Unified Diff: content/common/gpu/image_transport_surface_calayer_mac.mm

Issue 454243002: Make GPU back-pressure work with remote CALayers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix flashes Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/gpu/image_transport_surface_calayer_mac.mm
diff --git a/content/common/gpu/image_transport_surface_calayer_mac.mm b/content/common/gpu/image_transport_surface_calayer_mac.mm
index 4ad8f92b4031c117f6377dce499e753738ea4993..ed8d3535cb9b26b90db5ac9d441c9a77c6a1e124 100644
--- a/content/common/gpu/image_transport_surface_calayer_mac.mm
+++ b/content/common/gpu/image_transport_surface_calayer_mac.mm
@@ -9,36 +9,39 @@
#include "ui/base/cocoa/animation_utils.h"
#include "ui/gfx/geometry/size_conversions.h"
-@interface ImageTransportLayer (Private) {
+@interface ImageTransportLayer : CAOpenGLLayer {
+ content::CALayerStorageProvider* storageProvider_;
}
+- (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider;
+- (void)resetStorageProvider;
@end
@implementation ImageTransportLayer
-- (id)initWithContext:(CGLContextObj)context
- withTexture:(GLuint)texture
- withPixelSize:(gfx::Size)pixelSize
- withScaleFactor:(float)scaleFactor {
- if (self = [super init]) {
- shareContext_.reset(CGLRetainContext(context));
- texture_ = texture;
- pixelSize_ = pixelSize;
-
- gfx::Size dipSize(gfx::ToFlooredSize(gfx::ScaleSize(
- pixelSize_, 1.0f / scaleFactor)));
- [self setContentsScale:scaleFactor];
- [self setFrame:CGRectMake(0, 0, dipSize.width(), dipSize.height())];
- }
+- (id)initWithStorageProvider:
+ (content::CALayerStorageProvider*)storageProvider {
+ if (self = [super init])
+ storageProvider_ = storageProvider;
return self;
}
+- (void)resetStorageProvider {
+ storageProvider_ = NULL;
+}
+
- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
- return CGLRetainPixelFormat(CGLGetPixelFormat(shareContext_));
+ if (!storageProvider_)
+ return NULL;
+ return CGLRetainPixelFormat(CGLGetPixelFormat(
+ storageProvider_->LayerShareGroupContext()));
}
- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+ if (!storageProvider_)
+ return NULL;
CGLContextObj context = NULL;
- CGLError error = CGLCreateContext(pixelFormat, shareContext_, &context);
+ CGLError error = CGLCreateContext(
+ pixelFormat, storageProvider_->LayerShareGroupContext(), &context);
if (error != kCGLNoError)
DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
return context;
@@ -48,49 +51,21 @@
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp {
- return YES;
+ if (!storageProvider_)
+ return NO;
+ return storageProvider_->LayerCanDraw();
}
- (void)drawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp {
- glClearColor(1, 0, 1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-
- GLint viewport[4] = {0, 0, 0, 0};
- glGetIntegerv(GL_VIEWPORT, viewport);
- gfx::Size viewportSize(viewport[2], viewport[3]);
-
- // Set the coordinate system to be one-to-one with pixels.
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, viewportSize.width(), 0, viewportSize.height(), -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- // Draw a fullscreen quad.
- glColor4f(1, 1, 1, 1);
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
- glBegin(GL_QUADS);
- {
- glTexCoord2f(0, 0);
- glVertex2f(0, 0);
-
- glTexCoord2f(0, pixelSize_.height());
- glVertex2f(0, pixelSize_.height());
-
- glTexCoord2f(pixelSize_.width(), pixelSize_.height());
- glVertex2f(pixelSize_.width(), pixelSize_.height());
-
- glTexCoord2f(pixelSize_.width(), 0);
- glVertex2f(pixelSize_.width(), 0);
+ if (storageProvider_) {
+ storageProvider_->LayerDoDraw();
+ } else {
+ glClearColor(1, 1, 1, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
}
- glEnd();
- glBindTexture(0, texture_);
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
-
[super drawInCGLContext:glContext
pixelFormat:pixelFormat
forLayerTime:timeInterval
@@ -101,7 +76,14 @@
namespace content {
-CALayerStorageProvider::CALayerStorageProvider() {
+CALayerStorageProvider::CALayerStorageProvider(
+ ImageTransportSurfaceFBO* transport_surface)
+ : transport_surface_(transport_surface),
+ has_pending_draw_(false),
+ can_draw_returned_false_count_(0),
+ fbo_texture_(0) {
+ // Allocate a CAContext to use to transport the CALayer to the browser
+ // process.
base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
CGSConnectionID connection_id = CGSMainConnectionID();
context_.reset([CAContext contextWithCGSConnection:connection_id
@@ -144,18 +126,33 @@ bool CALayerStorageProvider::AllocateColorBufferStorage(
// Disable the fade-in animation as the layer is changed.
ScopedCAActionDisabler disabler;
- // Resize the CAOpenGLLayer to match the size needed, and change it to be the
- // hosted layer.
- layer_.reset([[ImageTransportLayer alloc] initWithContext:context
- withTexture:texture
- withPixelSize:pixel_size
- withScaleFactor:scale_factor]);
+ // Allocate a CALayer to draw texture into.
+ share_group_context_.reset(CGLRetainContext(context));
+ fbo_texture_ = texture;
+ fbo_pixel_size_ = pixel_size;
+ layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
+ gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
+ fbo_pixel_size_, 1.0f / scale_factor)));
+ [layer_ setContentsScale:scale_factor];
+ [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
return true;
}
void CALayerStorageProvider::FreeColorBufferStorage() {
- [context_ setLayer:nil];
+ // We shouldn't be asked to free a texture when we still have yet to draw it.
+ DCHECK(!has_pending_draw_);
+ has_pending_draw_ = false;
+ can_draw_returned_false_count_ = 0;
+
+ // Note that |context_| still holds a reference to |layer_|, and will until
+ // a new frame is swapped in.
+ [layer_ displayIfNeeded];
+ [layer_ resetStorageProvider];
layer_.reset();
+
+ share_group_context_.reset();
+ fbo_texture_ = 0;
+ fbo_pixel_size_ = gfx::Size();
}
uint64 CALayerStorageProvider::GetSurfaceHandle() const {
@@ -163,15 +160,80 @@ uint64 CALayerStorageProvider::GetSurfaceHandle() const {
}
void CALayerStorageProvider::WillSwapBuffers() {
+ DCHECK(!has_pending_draw_);
+ has_pending_draw_ = true;
+
// Don't add the layer to the CAContext until a SwapBuffers is going to be
// called, because the texture does not have any content until the
// SwapBuffers call is about to be made.
if ([context_ layer] != layer_.get())
[context_ setLayer:layer_];
- // TODO(ccameron): Use the isAsynchronous property to ensure smooth
- // animation.
- [layer_ setNeedsDisplay];
+ if (![layer_ isAsynchronous])
+ [layer_ setAsynchronous:YES];
+}
+
+void CALayerStorageProvider::CanFreeSwappedBuffer() {
+}
+
+CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
+ return share_group_context_;
+}
+
+bool CALayerStorageProvider::LayerCanDraw() {
+ if (has_pending_draw_) {
+ can_draw_returned_false_count_ = 0;
+ return true;
+ } else {
+ if (can_draw_returned_false_count_ == 30) {
+ if ([layer_ isAsynchronous])
+ [layer_ setAsynchronous:NO];
+ } else {
+ can_draw_returned_false_count_ += 1;
+ }
+ return false;
+ }
+}
+
+void CALayerStorageProvider::LayerDoDraw() {
+ DCHECK(has_pending_draw_);
+ has_pending_draw_ = false;
+
+ GLint viewport[4] = {0, 0, 0, 0};
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ gfx::Size viewport_size(viewport[2], viewport[3]);
+
+ // Set the coordinate system to be one-to-one with pixels.
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // Draw a fullscreen quad.
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fbo_texture_);
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0, 0);
+ glVertex2f(0, 0);
+
+ glTexCoord2f(0, fbo_pixel_size_.height());
+ glVertex2f(0, fbo_pixel_size_.height());
+
+ glTexCoord2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
+ glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
+
+ glTexCoord2f(fbo_pixel_size_.width(), 0);
+ glVertex2f(fbo_pixel_size_.width(), 0);
+ }
+ glEnd();
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ // Allow forward progress in the context now that the swap is complete.
+ transport_surface_->UnblockContextAfterPendingSwap();
}
} // namespace content
« no previous file with comments | « content/common/gpu/image_transport_surface_calayer_mac.h ('k') | content/common/gpu/image_transport_surface_fbo_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698