1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/gpu/image_transport_surface_calayer_mac.h"
7 #include "base/mac/sdk_forward_declarations.h"
8 #include "content/common/gpu/surface_handle_types_mac.h"
9 #include "ui/base/cocoa/animation_utils.h"
10 #include "ui/gfx/geometry/size_conversions.h"
12 @interface ImageTransportLayer (Private) {
16 @implementation ImageTransportLayer
18 - (id)initWithContext:(CGLContextObj)context
19 withTexture:(GLuint)texture
20 withPixelSize:(gfx::Size)pixelSize
21 withScaleFactor:(float)scaleFactor {
22 if (self = [super init]) {
23 shareContext_.reset(CGLRetainContext(context));
25 pixelSize_ = pixelSize;
27 gfx::Size dipSize(gfx::ToFlooredSize(gfx::ScaleSize(
28 pixelSize_, 1.0f / scaleFactor)));
29 [self setContentsScale:scaleFactor];
30 [self setFrame:CGRectMake(0, 0, dipSize.width(), dipSize.height())];
35 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
36 return CGLRetainPixelFormat(CGLGetPixelFormat(shareContext_));
39 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
40 CGLContextObj context = NULL;
41 CGLError error = CGLCreateContext(pixelFormat, shareContext_, &context);
42 if (error != kCGLNoError)
43 DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
47 - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
48 pixelFormat:(CGLPixelFormatObj)pixelFormat
49 forLayerTime:(CFTimeInterval)timeInterval
50 displayTime:(const CVTimeStamp*)timeStamp {
54 - (void)drawInCGLContext:(CGLContextObj)glContext
55 pixelFormat:(CGLPixelFormatObj)pixelFormat
56 forLayerTime:(CFTimeInterval)timeInterval
57 displayTime:(const CVTimeStamp*)timeStamp {
58 glClearColor(1, 0, 1, 1);
59 glClear(GL_COLOR_BUFFER_BIT);
61 GLint viewport[4] = {0, 0, 0, 0};
62 glGetIntegerv(GL_VIEWPORT, viewport);
63 gfx::Size viewportSize(viewport[2], viewport[3]);
65 // Set the coordinate system to be one-to-one with pixels.
66 glMatrixMode(GL_PROJECTION);
68 glOrtho(0, viewportSize.width(), 0, viewportSize.height(), -1, 1);
69 glMatrixMode(GL_MODELVIEW);
72 // Draw a fullscreen quad.
73 glColor4f(1, 1, 1, 1);
74 glEnable(GL_TEXTURE_RECTANGLE_ARB);
75 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
81 glTexCoord2f(0, pixelSize_.height());
82 glVertex2f(0, pixelSize_.height());
84 glTexCoord2f(pixelSize_.width(), pixelSize_.height());
85 glVertex2f(pixelSize_.width(), pixelSize_.height());
87 glTexCoord2f(pixelSize_.width(), 0);
88 glVertex2f(pixelSize_.width(), 0);
91 glBindTexture(0, texture_);
92 glDisable(GL_TEXTURE_RECTANGLE_ARB);
94 [super drawInCGLContext:glContext
95 pixelFormat:pixelFormat
96 forLayerTime:timeInterval
97 displayTime:timeStamp];
104 CALayerStorageProvider::CALayerStorageProvider() {
105 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
106 CGSConnectionID connection_id = CGSMainConnectionID();
107 context_.reset([CAContext contextWithCGSConnection:connection_id
112 CALayerStorageProvider::~CALayerStorageProvider() {
115 gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
119 bool CALayerStorageProvider::AllocateColorBufferStorage(
120 CGLContextObj context, GLuint texture,
121 gfx::Size pixel_size, float scale_factor) {
122 // Allocate an ordinary OpenGL texture to back the FBO.
124 while ((error = glGetError()) != GL_NO_ERROR) {
125 DLOG(ERROR) << "Error found (and ignored) before allocating buffer "
126 << "storage: " << error;
128 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB,
137 error = glGetError();
138 if (error != GL_NO_ERROR) {
139 DLOG(ERROR) << "glTexImage failed with GL error: " << error;
144 // Disable the fade-in animation as the layer is changed.
145 ScopedCAActionDisabler disabler;
147 // Resize the CAOpenGLLayer to match the size needed, and change it to be the
149 layer_.reset([[ImageTransportLayer alloc] initWithContext:context
151 withPixelSize:pixel_size
152 withScaleFactor:scale_factor]);
156 void CALayerStorageProvider::FreeColorBufferStorage() {
157 [context_ setLayer:nil];
161 uint64 CALayerStorageProvider::GetSurfaceHandle() const {
162 return SurfaceHandleFromCAContextID([context_ contextId]);
165 void CALayerStorageProvider::WillSwapBuffers() {
166 // Don't add the layer to the CAContext until a SwapBuffers is going to be
167 // called, because the texture does not have any content until the
168 // SwapBuffers call is about to be made.
169 if ([context_ layer] != layer_.get())
170 [context_ setLayer:layer_];
172 // TODO(ccameron): Use the isAsynchronous property to ensure smooth
174 [layer_ setNeedsDisplay];
177 } // namespace content