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

Side by Side Diff: content/browser/compositor/io_surface_layer_mac.mm

Issue 753933002: MacViews: Move content::AcceleratedWidget to new component, ui/accelerated_widget_mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20141124-MacViews-MoveSoftwareLayerMac-fromcl
Patch Set: gn check Created 6 years 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
(Empty)
1 // Copyright 2013 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.
4
5 #include "content/browser/compositor/io_surface_layer_mac.h"
6
7 #include <CoreFoundation/CoreFoundation.h>
8 #include <OpenGL/CGLIOSurface.h>
9 #include <OpenGL/CGLRenderers.h>
10 #include <OpenGL/gl.h>
11 #include <OpenGL/OpenGL.h>
12
13 #include "base/debug/trace_event.h"
14 #include "base/mac/mac_util.h"
15 #include "base/mac/sdk_forward_declarations.h"
16 #include "content/browser/compositor/io_surface_context_mac.h"
17 #include "content/browser/compositor/io_surface_texture_mac.h"
18 #include "ui/base/cocoa/animation_utils.h"
19 #include "ui/gfx/size_conversions.h"
20 #include "ui/gl/gpu_switching_manager.h"
21
22 ////////////////////////////////////////////////////////////////////////////////
23 // IOSurfaceLayerHelper
24
25 namespace content {
26
27 IOSurfaceLayerHelper::IOSurfaceLayerHelper(
28 IOSurfaceLayerClient* client,
29 IOSurfaceLayer* layer)
30 : client_(client),
31 layer_(layer),
32 needs_display_(false),
33 has_pending_frame_(false),
34 did_not_draw_counter_(0),
35 is_pumping_frames_(false),
36 timer_(
37 FROM_HERE,
38 base::TimeDelta::FromSeconds(1) / 6,
39 this,
40 &IOSurfaceLayerHelper::TimerFired) {}
41
42 IOSurfaceLayerHelper::~IOSurfaceLayerHelper() {
43 // Any acks that were waiting on this layer to draw will not occur, so ack
44 // them now to prevent blocking the renderer.
45 AckPendingFrame(true);
46 }
47
48 void IOSurfaceLayerHelper::GotNewFrame() {
49 // A trace value of 2 indicates that there is a pending swap ack. See
50 // canDrawInCGLContext for other value meanings.
51 TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 2);
52
53 has_pending_frame_ = true;
54 needs_display_ = true;
55 timer_.Reset();
56
57 // If reqested, draw immediately and don't bother trying to use the
58 // isAsynchronous property to ensure smooth animation. If this is while
59 // frames are being pumped then ack and display immediately to get a
60 // correct-sized frame displayed as soon as possible.
61 if (is_pumping_frames_ || client_->IOSurfaceLayerShouldAckImmediately()) {
62 SetNeedsDisplayAndDisplayAndAck();
63 } else {
64 if (![layer_ isAsynchronous])
65 [layer_ setAsynchronous:YES];
66 }
67 }
68
69 void IOSurfaceLayerHelper::SetNeedsDisplay() {
70 needs_display_ = true;
71 }
72
73 bool IOSurfaceLayerHelper::CanDraw() {
74 // If we return NO 30 times in a row, switch to being synchronous to avoid
75 // burning CPU cycles on this callback.
76 if (needs_display_) {
77 did_not_draw_counter_ = 0;
78 } else {
79 did_not_draw_counter_ += 1;
80 if (did_not_draw_counter_ == 30)
81 [layer_ setAsynchronous:NO];
82 }
83
84 // Add an instantaneous blip to the PendingSwapAck state to indicate
85 // that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually
86 // from 2, indicating that a swap ack is pending) indicates that we
87 // requested a draw. A blip up to 1 (usually from 0, indicating there is no
88 // pending swap ack) indicates that we did not request a draw. This would
89 // be more natural to do with a tracing pseudo-thread
90 // http://crbug.com/366300
91 TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, needs_display_ ? 3 : 1);
92 TRACE_COUNTER_ID1("browser", "PendingSwapAck", this,
93 has_pending_frame_ ? 2 : 0);
94
95 return needs_display_;
96 }
97
98 void IOSurfaceLayerHelper::DidDraw(bool success) {
99 needs_display_ = false;
100 AckPendingFrame(success);
101 }
102
103 void IOSurfaceLayerHelper::AckPendingFrame(bool success) {
104 if (!has_pending_frame_)
105 return;
106 has_pending_frame_ = false;
107 if (success)
108 client_->IOSurfaceLayerDidDrawFrame();
109 else
110 client_->IOSurfaceLayerHitError();
111 // A trace value of 0 indicates that there is no longer a pending swap ack.
112 TRACE_COUNTER_ID1("browser", "PendingSwapAck", this, 0);
113 }
114
115 void IOSurfaceLayerHelper::SetNeedsDisplayAndDisplayAndAck() {
116 // Drawing using setNeedsDisplay and displayIfNeeded will result in
117 // subsequent canDrawInCGLContext callbacks getting dropped, and jerky
118 // animation. Disable asynchronous drawing before issuing these calls as a
119 // workaround.
120 // http://crbug.com/395827
121 if ([layer_ isAsynchronous])
122 [layer_ setAsynchronous:NO];
123
124 [layer_ setNeedsDisplay];
125 DisplayIfNeededAndAck();
126 }
127
128 void IOSurfaceLayerHelper::DisplayIfNeededAndAck() {
129 if (!needs_display_)
130 return;
131
132 // As in SetNeedsDisplayAndDisplayAndAck, disable asynchronous drawing before
133 // issuing displayIfNeeded.
134 // http://crbug.com/395827
135 if ([layer_ isAsynchronous])
136 [layer_ setAsynchronous:NO];
137
138 // Do not bother drawing while pumping new frames -- wait until the waiting
139 // block ends to draw any of the new frames.
140 if (!is_pumping_frames_)
141 [layer_ displayIfNeeded];
142
143 // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
144 // rapidly (e.g, with vsync off). This is unacceptable because the failure
145 // to ack a single frame will hang the renderer. Ensure that the renderer
146 // not be blocked by lying and claiming that we drew the frame.
147 AckPendingFrame(true);
148 }
149
150 void IOSurfaceLayerHelper::TimerFired() {
151 DisplayIfNeededAndAck();
152 }
153
154 void IOSurfaceLayerHelper::BeginPumpingFrames() {
155 is_pumping_frames_ = true;
156 }
157
158 void IOSurfaceLayerHelper::EndPumpingFrames() {
159 is_pumping_frames_ = false;
160 DisplayIfNeededAndAck();
161 }
162
163 } // namespace content
164
165 ////////////////////////////////////////////////////////////////////////////////
166 // IOSurfaceLayer
167
168 @implementation IOSurfaceLayer
169
170 - (id)initWithClient:(content::IOSurfaceLayerClient*)client
171 withScaleFactor:(float)scale_factor {
172 if (self = [super init]) {
173 helper_.reset(new content::IOSurfaceLayerHelper(client, self));
174
175 iosurface_ = content::IOSurfaceTexture::Create();
176 context_ = content::IOSurfaceContext::Get(
177 content::IOSurfaceContext::kCALayerContext);
178 if (!iosurface_.get() || !context_.get()) {
179 LOG(ERROR) << "Failed create CompositingIOSurface or context";
180 [self resetClient];
181 [self release];
182 return nil;
183 }
184
185 [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
186 [self setAnchorPoint:CGPointMake(0, 0)];
187 // Setting contents gravity is necessary to prevent the layer from being
188 // scaled during dyanmic resizes (especially with devtools open).
189 [self setContentsGravity:kCAGravityTopLeft];
190 if ([self respondsToSelector:(@selector(setContentsScale:))]) {
191 [self setContentsScale:scale_factor];
192 }
193 }
194 return self;
195 }
196
197 - (void)dealloc {
198 DCHECK(!helper_);
199 [super dealloc];
200 }
201
202 - (bool)gotFrameWithIOSurface:(IOSurfaceID)io_surface_id
203 withPixelSize:(gfx::Size)pixel_size
204 withScaleFactor:(float)scale_factor {
205 return iosurface_->SetIOSurface(io_surface_id, pixel_size);
206 }
207
208 - (void)poisonContextAndSharegroup {
209 context_->PoisonContextAndSharegroup();
210 }
211
212 - (bool)hasBeenPoisoned {
213 return context_->HasBeenPoisoned();
214 }
215
216 - (float)scaleFactor {
217 if ([self respondsToSelector:(@selector(contentsScale))])
218 return [self contentsScale];
219 return 1;
220 }
221
222 - (int)rendererID {
223 GLint current_renderer_id = -1;
224 if (CGLGetParameter(context_->cgl_context(),
225 kCGLCPCurrentRendererID,
226 &current_renderer_id) == kCGLNoError) {
227 return current_renderer_id & kCGLRendererIDMatchingMask;
228 }
229 return -1;
230 }
231
232 - (void)resetClient {
233 helper_.reset();
234 }
235
236 - (void)gotNewFrame {
237 helper_->GotNewFrame();
238 }
239
240 - (void)setNeedsDisplayAndDisplayAndAck {
241 helper_->SetNeedsDisplayAndDisplayAndAck();
242 }
243
244 - (void)displayIfNeededAndAck {
245 helper_->DisplayIfNeededAndAck();
246 }
247
248 - (void)beginPumpingFrames {
249 helper_->BeginPumpingFrames();
250 }
251
252 - (void)endPumpingFrames {
253 helper_->EndPumpingFrames();
254 }
255
256 // The remaining methods implement the CAOpenGLLayer interface.
257
258 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
259 if (!context_.get())
260 return [super copyCGLPixelFormatForDisplayMask:mask];
261 return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context()));
262 }
263
264 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
265 if (!context_.get())
266 return [super copyCGLContextForPixelFormat:pixelFormat];
267 return CGLRetainContext(context_->cgl_context());
268 }
269
270 - (void)setNeedsDisplay {
271 if (helper_)
272 helper_->SetNeedsDisplay();
273 [super setNeedsDisplay];
274 }
275
276 - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
277 pixelFormat:(CGLPixelFormatObj)pixelFormat
278 forLayerTime:(CFTimeInterval)timeInterval
279 displayTime:(const CVTimeStamp*)timeStamp {
280 if (helper_)
281 return helper_->CanDraw();
282 return NO;
283 }
284
285 - (void)drawInCGLContext:(CGLContextObj)glContext
286 pixelFormat:(CGLPixelFormatObj)pixelFormat
287 forLayerTime:(CFTimeInterval)timeInterval
288 displayTime:(const CVTimeStamp*)timeStamp {
289 TRACE_EVENT0("browser", "IOSurfaceLayer::drawInCGLContext");
290
291 bool draw_succeeded = iosurface_->DrawIOSurface();
292 if (helper_)
293 helper_->DidDraw(draw_succeeded);
294
295 [super drawInCGLContext:glContext
296 pixelFormat:pixelFormat
297 forLayerTime:timeInterval
298 displayTime:timeStamp];
299 }
300
301 @end
OLDNEW
« no previous file with comments | « content/browser/compositor/io_surface_layer_mac.h ('k') | content/browser/compositor/io_surface_texture_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698