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

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

Issue 347653005: Make cross-process CALayers work on Mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@image_transport_1
Patch Set: Incorporate review feedback Created 6 years, 6 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
new file mode 100644
index 0000000000000000000000000000000000000000..4ad8f92b4031c117f6377dce499e753738ea4993
--- /dev/null
+++ b/content/common/gpu/image_transport_surface_calayer_mac.mm
@@ -0,0 +1,177 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/image_transport_surface_calayer_mac.h"
+
+#include "base/mac/sdk_forward_declarations.h"
+#include "content/common/gpu/surface_handle_types_mac.h"
+#include "ui/base/cocoa/animation_utils.h"
+#include "ui/gfx/geometry/size_conversions.h"
+
+@interface ImageTransportLayer (Private) {
+}
+@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())];
+ }
+ return self;
+}
+
+- (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
+ return CGLRetainPixelFormat(CGLGetPixelFormat(shareContext_));
+}
+
+- (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
+ CGLContextObj context = NULL;
+ CGLError error = CGLCreateContext(pixelFormat, shareContext_, &context);
+ if (error != kCGLNoError)
+ DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
+ return context;
+}
+
+- (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+ pixelFormat:(CGLPixelFormatObj)pixelFormat
+ forLayerTime:(CFTimeInterval)timeInterval
+ displayTime:(const CVTimeStamp*)timeStamp {
+ return YES;
+}
+
+- (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);
+ }
+ glEnd();
+ glBindTexture(0, texture_);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ [super drawInCGLContext:glContext
+ pixelFormat:pixelFormat
+ forLayerTime:timeInterval
+ displayTime:timeStamp];
+}
+
+@end
+
+namespace content {
+
+CALayerStorageProvider::CALayerStorageProvider() {
+ base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
+ CGSConnectionID connection_id = CGSMainConnectionID();
+ context_.reset([CAContext contextWithCGSConnection:connection_id
+ options:dict]);
+ [context_ retain];
+}
+
+CALayerStorageProvider::~CALayerStorageProvider() {
+}
+
+gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
+ return size;
+}
+
+bool CALayerStorageProvider::AllocateColorBufferStorage(
+ CGLContextObj context, GLuint texture,
+ gfx::Size pixel_size, float scale_factor) {
+ // Allocate an ordinary OpenGL texture to back the FBO.
+ GLenum error;
+ while ((error = glGetError()) != GL_NO_ERROR) {
+ DLOG(ERROR) << "Error found (and ignored) before allocating buffer "
+ << "storage: " << error;
+ }
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
+ 0,
+ GL_RGBA,
+ pixel_size.width(),
+ pixel_size.height(),
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ NULL);
+ error = glGetError();
+ if (error != GL_NO_ERROR) {
+ DLOG(ERROR) << "glTexImage failed with GL error: " << error;
+ return false;
+ }
+ glFlush();
+
+ // 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]);
+ return true;
+}
+
+void CALayerStorageProvider::FreeColorBufferStorage() {
+ [context_ setLayer:nil];
+ layer_.reset();
+}
+
+uint64 CALayerStorageProvider::GetSurfaceHandle() const {
+ return SurfaceHandleFromCAContextID([context_ contextId]);
+}
+
+void CALayerStorageProvider::WillSwapBuffers() {
+ // 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];
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698