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

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

Issue 517733002: Revert of Fix assorted issues with remote CoreAnimation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@clean_up_accel_layers
Patch Set: 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"
8 #include "base/mac/sdk_forward_declarations.h" 7 #include "base/mac/sdk_forward_declarations.h"
9 #include "content/common/gpu/surface_handle_types_mac.h" 8 #include "content/common/gpu/surface_handle_types_mac.h"
10 #include "ui/base/cocoa/animation_utils.h" 9 #include "ui/base/cocoa/animation_utils.h"
11 #include "ui/gfx/geometry/size_conversions.h" 10 #include "ui/gfx/geometry/size_conversions.h"
12 #include "ui/gl/gl_gl_api_implementation.h"
13 #include "ui/gl/gl_switches.h"
14 11
15 @interface ImageTransportLayer : CAOpenGLLayer { 12 @interface ImageTransportLayer : CAOpenGLLayer {
16 content::CALayerStorageProvider* storageProvider_; 13 content::CALayerStorageProvider* storageProvider_;
17 } 14 }
18 - (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider; 15 - (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider;
19 - (void)resetStorageProvider; 16 - (void)resetStorageProvider;
20 @end 17 @end
21 18
22 @implementation ImageTransportLayer 19 @implementation ImageTransportLayer
23 20
24 - (id)initWithStorageProvider: 21 - (id)initWithStorageProvider:
25 (content::CALayerStorageProvider*)storageProvider { 22 (content::CALayerStorageProvider*)storageProvider {
26 if (self = [super init]) 23 if (self = [super init])
27 storageProvider_ = storageProvider; 24 storageProvider_ = storageProvider;
28 return self; 25 return self;
29 } 26 }
30 27
31 - (void)resetStorageProvider { 28 - (void)resetStorageProvider {
32 if (storageProvider_)
33 storageProvider_->LayerResetStorageProvider();
34 storageProvider_ = NULL; 29 storageProvider_ = NULL;
35 } 30 }
36 31
37 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { 32 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
38 if (!storageProvider_) 33 if (!storageProvider_)
39 return NULL; 34 return NULL;
40 return CGLRetainPixelFormat(CGLGetPixelFormat( 35 return CGLRetainPixelFormat(CGLGetPixelFormat(
41 storageProvider_->LayerShareGroupContext())); 36 storageProvider_->LayerShareGroupContext()));
42 } 37 }
43 38
(...skipping 14 matching lines...) Expand all
58 displayTime:(const CVTimeStamp*)timeStamp { 53 displayTime:(const CVTimeStamp*)timeStamp {
59 if (!storageProvider_) 54 if (!storageProvider_)
60 return NO; 55 return NO;
61 return storageProvider_->LayerCanDraw(); 56 return storageProvider_->LayerCanDraw();
62 } 57 }
63 58
64 - (void)drawInCGLContext:(CGLContextObj)glContext 59 - (void)drawInCGLContext:(CGLContextObj)glContext
65 pixelFormat:(CGLPixelFormatObj)pixelFormat 60 pixelFormat:(CGLPixelFormatObj)pixelFormat
66 forLayerTime:(CFTimeInterval)timeInterval 61 forLayerTime:(CFTimeInterval)timeInterval
67 displayTime:(const CVTimeStamp*)timeStamp { 62 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
72 if (storageProvider_) { 63 if (storageProvider_) {
73 storageProvider_->LayerDoDraw(); 64 storageProvider_->LayerDoDraw();
74 } else { 65 } else {
75 glClearColor(1, 1, 1, 1); 66 glClearColor(1, 1, 1, 1);
76 glClear(GL_COLOR_BUFFER_BIT); 67 glClear(GL_COLOR_BUFFER_BIT);
77 } 68 }
78 [super drawInCGLContext:glContext 69 [super drawInCGLContext:glContext
79 pixelFormat:pixelFormat 70 pixelFormat:pixelFormat
80 forLayerTime:timeInterval 71 forLayerTime:timeInterval
81 displayTime:timeStamp]; 72 displayTime:timeStamp];
82 } 73 }
83 74
84 @end 75 @end
85 76
86 namespace content { 77 namespace content {
87 78
88 CALayerStorageProvider::CALayerStorageProvider( 79 CALayerStorageProvider::CALayerStorageProvider(
89 ImageTransportSurfaceFBO* transport_surface) 80 ImageTransportSurfaceFBO* transport_surface)
90 : transport_surface_(transport_surface), 81 : transport_surface_(transport_surface),
91 gpu_vsync_disabled_(CommandLine::ForCurrentProcess()->HasSwitch(
92 switches::kDisableGpuVsync)),
93 has_pending_draw_(false), 82 has_pending_draw_(false),
94 can_draw_returned_false_count_(0), 83 can_draw_returned_false_count_(0),
95 fbo_texture_(0), 84 fbo_texture_(0) {
96 fbo_scale_factor_(1), 85 // Allocate a CAContext to use to transport the CALayer to the browser
97 weak_factory_(this) {} 86 // process.
87 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
88 CGSConnectionID connection_id = CGSMainConnectionID();
89 context_.reset([CAContext contextWithCGSConnection:connection_id
90 options:dict]);
91 [context_ retain];
92 }
98 93
99 CALayerStorageProvider::~CALayerStorageProvider() { 94 CALayerStorageProvider::~CALayerStorageProvider() {
100 } 95 }
101 96
102 gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) { 97 gfx::Size CALayerStorageProvider::GetRoundedSize(gfx::Size size) {
103 return size; 98 return size;
104 } 99 }
105 100
106 bool CALayerStorageProvider::AllocateColorBufferStorage( 101 bool CALayerStorageProvider::AllocateColorBufferStorage(
107 CGLContextObj context, GLuint texture, 102 CGLContextObj context, GLuint texture,
(...skipping 16 matching lines...) Expand all
124 error = glGetError(); 119 error = glGetError();
125 if (error != GL_NO_ERROR) { 120 if (error != GL_NO_ERROR) {
126 DLOG(ERROR) << "glTexImage failed with GL error: " << error; 121 DLOG(ERROR) << "glTexImage failed with GL error: " << error;
127 return false; 122 return false;
128 } 123 }
129 glFlush(); 124 glFlush();
130 125
131 // Disable the fade-in animation as the layer is changed. 126 // Disable the fade-in animation as the layer is changed.
132 ScopedCAActionDisabler disabler; 127 ScopedCAActionDisabler disabler;
133 128
134 // Set the parameters that will be used to allocate the CALayer to draw the 129 // Allocate a CALayer to draw texture into.
135 // texture into.
136 share_group_context_.reset(CGLRetainContext(context)); 130 share_group_context_.reset(CGLRetainContext(context));
137 fbo_texture_ = texture; 131 fbo_texture_ = texture;
138 fbo_pixel_size_ = pixel_size; 132 fbo_pixel_size_ = pixel_size;
139 fbo_scale_factor_ = scale_factor; 133 layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
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())];
140 return true; 138 return true;
141 } 139 }
142 140
143 void CALayerStorageProvider::FreeColorBufferStorage() { 141 void CALayerStorageProvider::FreeColorBufferStorage() {
144 // We shouldn't be asked to free a texture when we still have yet to draw it. 142 // We shouldn't be asked to free a texture when we still have yet to draw it.
145 DCHECK(!has_pending_draw_); 143 DCHECK(!has_pending_draw_);
146 has_pending_draw_ = false; 144 has_pending_draw_ = false;
147 can_draw_returned_false_count_ = 0; 145 can_draw_returned_false_count_ = 0;
148 146
149 // Note that |context_| still holds a reference to |layer_|, and will until 147 // Note that |context_| still holds a reference to |layer_|, and will until
150 // a new frame is swapped in. 148 // a new frame is swapped in.
151 [layer_ displayIfNeeded]; 149 [layer_ displayIfNeeded];
152 [layer_ resetStorageProvider]; 150 [layer_ resetStorageProvider];
153 layer_.reset(); 151 layer_.reset();
154 152
155 share_group_context_.reset(); 153 share_group_context_.reset();
156 fbo_texture_ = 0; 154 fbo_texture_ = 0;
157 fbo_pixel_size_ = gfx::Size(); 155 fbo_pixel_size_ = gfx::Size();
158 } 156 }
159 157
160 void CALayerStorageProvider::SwapBuffers( 158 uint64 CALayerStorageProvider::GetSurfaceHandle() const {
161 const gfx::Size& size, float scale_factor) { 159 return SurfaceHandleFromCAContextID([context_ contextId]);
160 }
161
162 void CALayerStorageProvider::WillSwapBuffers() {
162 DCHECK(!has_pending_draw_); 163 DCHECK(!has_pending_draw_);
163 has_pending_draw_ = true; 164 has_pending_draw_ = true;
164 165
165 // Allocate a CAContext to use to transport the CALayer to the browser 166 // Don't add the layer to the CAContext until a SwapBuffers is going to be
166 // process. 167 // called, because the texture does not have any content until the
167 if (!context_) { 168 // SwapBuffers call is about to be made.
168 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]); 169 if ([context_ layer] != layer_.get())
169 CGSConnectionID connection_id = CGSMainConnectionID(); 170 [context_ setLayer:layer_];
170 context_.reset([CAContext contextWithCGSConnection:connection_id
171 options:dict]);
172 [context_ retain];
173 }
174 171
175 // Allocate a CALayer to use to draw the content. 172 if (![layer_ isAsynchronous])
176 if (!layer_) { 173 [layer_ setAsynchronous:YES];
177 layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
178 gfx::Size dip_size(gfx::ToFlooredSize(gfx::ScaleSize(
179 fbo_pixel_size_, 1.0f / fbo_scale_factor_)));
180 [layer_ setContentsScale:fbo_scale_factor_];
181 [layer_ setFrame:CGRectMake(0, 0, dip_size.width(), dip_size.height())];
182
183 // Make the CALayer current to the CAContext and display its contents
184 // immediately.
185 [context_ setLayer:layer_];
186 }
187
188 // Tell CoreAnimation to draw our frame. We will send the IPC to the browser
189 // when CoreAnimation has drawn our frame.
190 if (gpu_vsync_disabled_) {
191 DrawWithVsyncDisabled();
192 } else {
193 if (![layer_ isAsynchronous])
194 [layer_ setAsynchronous:YES];
195 }
196 } 174 }
197 175
198 void CALayerStorageProvider::DrawWithVsyncDisabled() { 176 void CALayerStorageProvider::CanFreeSwappedBuffer() {
199 DCHECK(has_pending_draw_);
200 [layer_ setNeedsDisplay];
201
202 // Sometimes, setNeedsDisplay calls are dropped on the floor. Make this not
203 // hang the renderer by re-issuing the call if the draw has not yet
204 // happened.
205 if (has_pending_draw_) {
206 // Delay sending another draw immediately to avoid starving the run loop.
207 base::MessageLoop::current()->PostDelayedTask(
208 FROM_HERE,
209 base::Bind(&CALayerStorageProvider::DrawWithVsyncDisabled,
210 weak_factory_.GetWeakPtr()),
211 base::TimeDelta::FromMilliseconds(5));
212 }
213 }
214
215 void CALayerStorageProvider::WillWriteToBackbuffer() {
216 // TODO(ccameron): The browser may need to continue issuing swaps even when
217 // they do not draw. In these cases it is necessary to either double-buffer
218 // the resulting texture, or to drop frames.
219 }
220
221 void CALayerStorageProvider::DiscardBackbuffer() {
222 // If this surface's backbuffer is discarded, it is because this surface has
223 // been made non-visible. Ensure that the previous contents are not briefly
224 // flashed when this is made visible by creating a new CALayer and CAContext
225 // at the next swap.
226 [layer_ resetStorageProvider];
227 layer_.reset();
228 context_.reset();
229 }
230
231 void CALayerStorageProvider::SwapBuffersAckedByBrowser() {
232 } 177 }
233 178
234 CGLContextObj CALayerStorageProvider::LayerShareGroupContext() { 179 CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
235 return share_group_context_; 180 return share_group_context_;
236 } 181 }
237 182
238 bool CALayerStorageProvider::LayerCanDraw() { 183 bool CALayerStorageProvider::LayerCanDraw() {
239 if (has_pending_draw_) { 184 if (has_pending_draw_) {
240 can_draw_returned_false_count_ = 0; 185 can_draw_returned_false_count_ = 0;
241 return true; 186 return true;
242 } else { 187 } else {
243 if ([layer_ isAsynchronous]) { 188 if (can_draw_returned_false_count_ == 30) {
244 DCHECK(!gpu_vsync_disabled_); 189 if ([layer_ isAsynchronous])
245 // If we are in asynchronous mode, we will be getting callbacks at every
246 // vsync, asking us if we have anything to draw. If we get 30 of these in
247 // a row, ask that we stop getting these callback for now, so that we
248 // don't waste CPU cycles.
249 if (can_draw_returned_false_count_ == 30)
250 [layer_ setAsynchronous:NO]; 190 [layer_ setAsynchronous:NO];
251 else 191 } else {
252 can_draw_returned_false_count_ += 1; 192 can_draw_returned_false_count_ += 1;
253 } 193 }
254 return false; 194 return false;
255 } 195 }
256 } 196 }
257 197
258 void CALayerStorageProvider::LayerDoDraw() { 198 void CALayerStorageProvider::LayerDoDraw() {
199 DCHECK(has_pending_draw_);
200 has_pending_draw_ = false;
201
259 GLint viewport[4] = {0, 0, 0, 0}; 202 GLint viewport[4] = {0, 0, 0, 0};
260 glGetIntegerv(GL_VIEWPORT, viewport); 203 glGetIntegerv(GL_VIEWPORT, viewport);
261 gfx::Size viewport_size(viewport[2], viewport[3]); 204 gfx::Size viewport_size(viewport[2], viewport[3]);
262 205
263 // Set the coordinate system to be one-to-one with pixels. 206 // Set the coordinate system to be one-to-one with pixels.
264 glMatrixMode(GL_PROJECTION); 207 glMatrixMode(GL_PROJECTION);
265 glLoadIdentity(); 208 glLoadIdentity();
266 glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1); 209 glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1);
267 glMatrixMode(GL_MODELVIEW); 210 glMatrixMode(GL_MODELVIEW);
268 glLoadIdentity(); 211 glLoadIdentity();
(...skipping 14 matching lines...) Expand all
283 glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); 226 glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
284 227
285 glTexCoord2f(fbo_pixel_size_.width(), 0); 228 glTexCoord2f(fbo_pixel_size_.width(), 0);
286 glVertex2f(fbo_pixel_size_.width(), 0); 229 glVertex2f(fbo_pixel_size_.width(), 0);
287 } 230 }
288 glEnd(); 231 glEnd();
289 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 232 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
290 glDisable(GL_TEXTURE_RECTANGLE_ARB); 233 glDisable(GL_TEXTURE_RECTANGLE_ARB);
291 234
292 // Allow forward progress in the context now that the swap is complete. 235 // Allow forward progress in the context now that the swap is complete.
293 DCHECK(has_pending_draw_); 236 transport_surface_->UnblockContextAfterPendingSwap();
294 SendPendingSwapToBrowserAfterFrameDrawn();
295 }
296
297 void CALayerStorageProvider::LayerResetStorageProvider() {
298 // If we are providing back-pressure by waiting for a draw, that draw will
299 // now never come, so release the pressure now.
300 SendPendingSwapToBrowserAfterFrameDrawn();
301 }
302
303 void CALayerStorageProvider::SendPendingSwapToBrowserAfterFrameDrawn() {
304 if (!has_pending_draw_)
305 return;
306 weak_factory_.InvalidateWeakPtrs();
307 has_pending_draw_ = false;
308 transport_surface_->SendSwapBuffers(
309 SurfaceHandleFromCAContextID([context_ contextId]),
310 fbo_pixel_size_,
311 fbo_scale_factor_);
312 } 237 }
313 238
314 } // namespace content 239 } // 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