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

Side by Side Diff: content/common/gpu/image_transport_surface_calayer_mac.mm

Issue 505053002: Fix assorted issues with remote CoreAnimation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@clean_up_accel_layers
Patch Set: Clean up timer logic Created 6 years, 3 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/gpu/image_transport_surface_calayer_mac.h" 5 #include "content/common/gpu/image_transport_surface_calayer_mac.h"
6 6
7 #include "base/command_line.h"
7 #include "base/mac/sdk_forward_declarations.h" 8 #include "base/mac/sdk_forward_declarations.h"
8 #include "content/common/gpu/surface_handle_types_mac.h" 9 #include "content/common/gpu/surface_handle_types_mac.h"
9 #include "ui/base/cocoa/animation_utils.h" 10 #include "ui/base/cocoa/animation_utils.h"
10 #include "ui/gfx/geometry/size_conversions.h" 11 #include "ui/gfx/geometry/size_conversions.h"
12 #include "ui/gl/gl_gl_api_implementation.h"
13 #include "ui/gl/gl_switches.h"
11 14
12 @interface ImageTransportLayer : CAOpenGLLayer { 15 @interface ImageTransportLayer : CAOpenGLLayer {
13 content::CALayerStorageProvider* storageProvider_; 16 content::CALayerStorageProvider* storageProvider_;
14 } 17 }
15 - (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider; 18 - (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider;
16 - (void)resetStorageProvider; 19 - (void)resetStorageProvider;
17 @end 20 @end
18 21
19 @implementation ImageTransportLayer 22 @implementation ImageTransportLayer
20 23
21 - (id)initWithStorageProvider: 24 - (id)initWithStorageProvider:
22 (content::CALayerStorageProvider*)storageProvider { 25 (content::CALayerStorageProvider*)storageProvider {
23 if (self = [super init]) 26 if (self = [super init])
24 storageProvider_ = storageProvider; 27 storageProvider_ = storageProvider;
25 return self; 28 return self;
26 } 29 }
27 30
28 - (void)resetStorageProvider { 31 - (void)resetStorageProvider {
32 if (storageProvider_)
33 storageProvider_->LayerResetStorageProvider();
29 storageProvider_ = NULL; 34 storageProvider_ = NULL;
30 } 35 }
31 36
32 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { 37 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
33 if (!storageProvider_) 38 if (!storageProvider_)
34 return NULL; 39 return NULL;
35 return CGLRetainPixelFormat(CGLGetPixelFormat( 40 return CGLRetainPixelFormat(CGLGetPixelFormat(
36 storageProvider_->LayerShareGroupContext())); 41 storageProvider_->LayerShareGroupContext()));
37 } 42 }
38 43
(...skipping 14 matching lines...) Expand all
53 displayTime:(const CVTimeStamp*)timeStamp { 58 displayTime:(const CVTimeStamp*)timeStamp {
54 if (!storageProvider_) 59 if (!storageProvider_)
55 return NO; 60 return NO;
56 return storageProvider_->LayerCanDraw(); 61 return storageProvider_->LayerCanDraw();
57 } 62 }
58 63
59 - (void)drawInCGLContext:(CGLContextObj)glContext 64 - (void)drawInCGLContext:(CGLContextObj)glContext
60 pixelFormat:(CGLPixelFormatObj)pixelFormat 65 pixelFormat:(CGLPixelFormatObj)pixelFormat
61 forLayerTime:(CFTimeInterval)timeInterval 66 forLayerTime:(CFTimeInterval)timeInterval
62 displayTime:(const CVTimeStamp*)timeStamp { 67 displayTime:(const CVTimeStamp*)timeStamp {
68 // While in this callback, CoreAnimation has set |glContext| to be current.
69 // Ensure that the GL calls that we make are made against the native GL API.
70 gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
71
63 if (storageProvider_) { 72 if (storageProvider_) {
64 storageProvider_->LayerDoDraw(); 73 storageProvider_->LayerDoDraw();
65 } else { 74 } else {
66 glClearColor(1, 1, 1, 1); 75 glClearColor(1, 1, 1, 1);
67 glClear(GL_COLOR_BUFFER_BIT); 76 glClear(GL_COLOR_BUFFER_BIT);
68 } 77 }
69 [super drawInCGLContext:glContext 78 [super drawInCGLContext:glContext
70 pixelFormat:pixelFormat 79 pixelFormat:pixelFormat
71 forLayerTime:timeInterval 80 forLayerTime:timeInterval
72 displayTime:timeStamp]; 81 displayTime:timeStamp];
73 } 82 }
74 83
75 @end 84 @end
76 85
77 namespace content { 86 namespace content {
78 87
79 CALayerStorageProvider::CALayerStorageProvider( 88 CALayerStorageProvider::CALayerStorageProvider(
80 ImageTransportSurfaceFBO* transport_surface) 89 ImageTransportSurfaceFBO* transport_surface)
81 : transport_surface_(transport_surface), 90 : transport_surface_(transport_surface),
91 gpu_vsync_disabled_(CommandLine::ForCurrentProcess()->HasSwitch(
92 switches::kDisableGpuVsync)),
82 has_pending_draw_(false), 93 has_pending_draw_(false),
83 can_draw_returned_false_count_(0), 94 can_draw_returned_false_count_(0),
84 fbo_texture_(0) { 95 fbo_texture_(0),
85 // Allocate a CAContext to use to transport the CALayer to the browser 96 fbo_scale_factor_(1),
86 // process. 97 display_timeout_timer_(
87 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]); 98 FROM_HERE,
88 CGSConnectionID connection_id = CGSMainConnectionID(); 99 base::TimeDelta::FromSeconds(1) / 6,
89 context_.reset([CAContext contextWithCGSConnection:connection_id 100 this,
90 options:dict]); 101 &CALayerStorageProvider::DisplayTimeoutFired) {}
91 [context_ retain];
92 }
93 102
94 CALayerStorageProvider::~CALayerStorageProvider() { 103 CALayerStorageProvider::~CALayerStorageProvider() {
95 } 104 }
96 105
97 gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) { 106 gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
98 return size; 107 return size;
99 } 108 }
100 109
101 bool CALayerStorageProvider::AllocateColorBufferStorage( 110 bool CALayerStorageProvider::AllocateColorBufferStorage(
102 CGLContextObj context, GLuint texture, 111 CGLContextObj context, GLuint texture,
(...skipping 16 matching lines...) Expand all
119 error = glGetError(); 128 error = glGetError();
120 if (error != GL_NO_ERROR) { 129 if (error != GL_NO_ERROR) {
121 DLOG(ERROR) << "glTexImage failed with GL error: " << error; 130 DLOG(ERROR) << "glTexImage failed with GL error: " << error;
122 return false; 131 return false;
123 } 132 }
124 glFlush(); 133 glFlush();
125 134
126 // Disable the fade-in animation as the layer is changed. 135 // Disable the fade-in animation as the layer is changed.
127 ScopedCAActionDisabler disabler; 136 ScopedCAActionDisabler disabler;
128 137
129 // Allocate a CALayer to draw texture into. 138 // Set the parameters that will be used to allocate the CALayer to draw the
139 // texture into.
130 share_group_context_.reset(CGLRetainContext(context)); 140 share_group_context_.reset(CGLRetainContext(context));
131 fbo_texture_ = texture; 141 fbo_texture_ = texture;
132 fbo_pixel_size_ = pixel_size; 142 fbo_pixel_size_ = pixel_size;
133 layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]); 143 fbo_scale_factor_ = scale_factor;
134 gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
135 fbo_pixel_size_, 1.0f / scale_factor)));
136 [layer_ setContentsScale:scale_factor];
137 [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
138 return true; 144 return true;
139 } 145 }
140 146
141 void CALayerStorageProvider::FreeColorBufferStorage() { 147 void CALayerStorageProvider::FreeColorBufferStorage() {
142 // We shouldn't be asked to free a texture when we still have yet to draw it. 148 // We shouldn't be asked to free a texture when we still have yet to draw it.
143 DCHECK(!has_pending_draw_); 149 DCHECK(!has_pending_draw_);
144 has_pending_draw_ = false; 150 has_pending_draw_ = false;
145 can_draw_returned_false_count_ = 0; 151 can_draw_returned_false_count_ = 0;
146 152
147 // Note that |context_| still holds a reference to |layer_|, and will until 153 // Note that |context_| still holds a reference to |layer_|, and will until
148 // a new frame is swapped in. 154 // a new frame is swapped in.
149 [layer_ displayIfNeeded]; 155 [layer_ displayIfNeeded];
150 [layer_ resetStorageProvider]; 156 [layer_ resetStorageProvider];
151 layer_.reset(); 157 layer_.reset();
152 158
153 share_group_context_.reset(); 159 share_group_context_.reset();
154 fbo_texture_ = 0; 160 fbo_texture_ = 0;
155 fbo_pixel_size_ = gfx::Size(); 161 fbo_pixel_size_ = gfx::Size();
156 } 162 }
157 163
158 uint64 CALayerStorageProvider::GetSurfaceHandle() const { 164 void CALayerStorageProvider::DiscardBackbuffer() {
165 // If this surface's backbuffer is discarded, it is because this surface has
166 // been made non-visible. Ensure that the previous contents are not briefly
167 // flashed when this is made visible by creating a new CALayer and CAContext
168 // at the next swap.
169 [layer_ resetStorageProvider];
170 layer_.reset();
171 context_.reset();
172 }
173
174 uint64 CALayerStorageProvider::SwapBuffersAndGetSurfaceHandle() {
175 DCHECK(!has_pending_draw_);
176 has_pending_draw_ = true;
177
178 // Allocate a CAContext to use to transport the CALayer to the browser
179 // process.
180 if (!context_) {
181 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
182 CGSConnectionID connection_id = CGSMainConnectionID();
183 context_.reset([CAContext contextWithCGSConnection:connection_id
184 options:dict]);
185 [context_ retain];
186 }
187
188 // Allocate a CALayer to use to draw the content.
189 if (!layer_) {
190 layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
191 gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
192 fbo_pixel_size_, 1.0f / fbo_scale_factor_)));
193 [layer_ setContentsScale:fbo_scale_factor_];
194 [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
195
196 // Make the CALayer current to the CAContext and display its contents
197 // immediately.
198 [context_ setLayer:layer_];
199 }
200
201 // Tell CoreAnimation to draw our frame.
202 if (gpu_vsync_disabled_) {
203 [layer_ setNeedsDisplay];
204 [layer_ displayIfNeeded];
205 // Rapid setNeedsDisplay+displayIfNeeded calls are sometimes dropped,
206 // ensure forward progress by re-scheduling the command buffer immediately.
207 UnblockIfNeededAfterPendingFrameDrawn();
208 } else {
209 if (![layer_ isAsynchronous])
210 [layer_ setAsynchronous:YES];
211 }
212
213 // In case CoreAnimation drops the frame, or is lazy in actually drawing
214 // the frame, reset the timer to un-block this command buffer in the event
215 // of a timeout.
216 display_timeout_timer_.Reset();
217
159 return SurfaceHandleFromCAContextID([context_ contextId]); 218 return SurfaceHandleFromCAContextID([context_ contextId]);
160 } 219 }
161 220
162 void CALayerStorageProvider::WillSwapBuffers() {
163 DCHECK(!has_pending_draw_);
164 has_pending_draw_ = true;
165
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_];
171
172 if (![layer_ isAsynchronous])
173 [layer_ setAsynchronous:YES];
174 }
175
176 void CALayerStorageProvider::CanFreeSwappedBuffer() { 221 void CALayerStorageProvider::CanFreeSwappedBuffer() {
177 } 222 }
178 223
179 CGLContextObj CALayerStorageProvider::LayerShareGroupContext() { 224 CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
180 return share_group_context_; 225 return share_group_context_;
181 } 226 }
182 227
183 bool CALayerStorageProvider::LayerCanDraw() { 228 bool CALayerStorageProvider::LayerCanDraw() {
184 if (has_pending_draw_) { 229 if (has_pending_draw_) {
185 can_draw_returned_false_count_ = 0; 230 can_draw_returned_false_count_ = 0;
186 return true; 231 return true;
187 } else { 232 } else {
188 if (can_draw_returned_false_count_ == 30) { 233 if ([layer_ isAsynchronous]) {
189 if ([layer_ isAsynchronous]) 234 DCHECK(!gpu_vsync_disabled_);
235 // If we are in asynchronous mode, we will be getting callbacks at every
236 // vsync, asking us if we have anything to draw. If we get 30 of these in
237 // a row, ask that we stop getting these callback for now, so that we
238 // don't waste CPU cycles.
239 if (can_draw_returned_false_count_ == 30)
190 [layer_ setAsynchronous:NO]; 240 [layer_ setAsynchronous:NO];
191 } else { 241 else
192 can_draw_returned_false_count_ += 1; 242 can_draw_returned_false_count_ += 1;
193 } 243 }
194 return false; 244 return false;
195 } 245 }
196 } 246 }
197 247
198 void CALayerStorageProvider::LayerDoDraw() { 248 void CALayerStorageProvider::LayerDoDraw() {
199 DCHECK(has_pending_draw_);
200 has_pending_draw_ = false;
201
202 GLint viewport[4] = {0, 0, 0, 0}; 249 GLint viewport[4] = {0, 0, 0, 0};
203 glGetIntegerv(GL_VIEWPORT, viewport); 250 glGetIntegerv(GL_VIEWPORT, viewport);
204 gfx::Size viewport_size(viewport[2], viewport[3]); 251 gfx::Size viewport_size(viewport[2], viewport[3]);
205 252
206 // Set the coordinate system to be one-to-one with pixels. 253 // Set the coordinate system to be one-to-one with pixels.
207 glMatrixMode(GL_PROJECTION); 254 glMatrixMode(GL_PROJECTION);
208 glLoadIdentity(); 255 glLoadIdentity();
209 glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1); 256 glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1);
210 glMatrixMode(GL_MODELVIEW); 257 glMatrixMode(GL_MODELVIEW);
211 glLoadIdentity(); 258 glLoadIdentity();
(...skipping 14 matching lines...) Expand all
226 glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); 273 glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
227 274
228 glTexCoord2f(fbo_pixel_size_.width(), 0); 275 glTexCoord2f(fbo_pixel_size_.width(), 0);
229 glVertex2f(fbo_pixel_size_.width(), 0); 276 glVertex2f(fbo_pixel_size_.width(), 0);
230 } 277 }
231 glEnd(); 278 glEnd();
232 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 279 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
233 glDisable(GL_TEXTURE_RECTANGLE_ARB); 280 glDisable(GL_TEXTURE_RECTANGLE_ARB);
234 281
235 // Allow forward progress in the context now that the swap is complete. 282 // Allow forward progress in the context now that the swap is complete.
283 UnblockIfNeededAfterPendingFrameDrawn();
284 }
285
286 void CALayerStorageProvider::LayerResetStorageProvider() {
287 // If the command buffer has been unscheduled waiting for the draw, that draw
288 // will never come, so re-schedule the command buffer now.
289 UnblockIfNeededAfterPendingFrameDrawn();
290 }
291
292 void CALayerStorageProvider::DisplayTimeoutFired() {
293 if (!has_pending_draw_)
294 return;
295 if ([layer_ isAsynchronous])
296 [layer_ setAsynchronous:NO];
297 [layer_ displayIfNeeded];
298 UnblockIfNeededAfterPendingFrameDrawn();
299 }
300
301 void CALayerStorageProvider::UnblockIfNeededAfterPendingFrameDrawn() {
302 if (!has_pending_draw_)
303 return;
236 transport_surface_->UnblockContextAfterPendingSwap(); 304 transport_surface_->UnblockContextAfterPendingSwap();
305 has_pending_draw_ = false;
237 } 306 }
238 307
239 } // namespace content 308 } // namespace content
OLDNEW
« 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