| 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
|
|
|