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

Side by Side Diff: content/browser/renderer_host/compositing_iosurface_layer_mac.mm

Issue 310183002: Ack swap buffers after a timeout (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporate review feedback Created 6 years, 6 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 2013 The Chromium Authors. All rights reserved. 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 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/browser/renderer_host/compositing_iosurface_layer_mac.h" 5 #include "content/browser/renderer_host/compositing_iosurface_layer_mac.h"
6 6
7 #include <CoreFoundation/CoreFoundation.h> 7 #include <CoreFoundation/CoreFoundation.h>
8 #include <OpenGL/gl.h> 8 #include <OpenGL/gl.h>
9 9
10 #include "base/mac/mac_util.h" 10 #include "base/mac/mac_util.h"
11 #include "base/mac/sdk_forward_declarations.h" 11 #include "base/mac/sdk_forward_declarations.h"
12 #include "content/browser/renderer_host/render_widget_host_impl.h" 12 #include "content/browser/renderer_host/render_widget_host_impl.h"
13 #include "content/browser/renderer_host/render_widget_host_view_mac.h" 13 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
14 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" 14 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
15 #include "content/browser/renderer_host/compositing_iosurface_mac.h" 15 #include "content/browser/renderer_host/compositing_iosurface_mac.h"
16 #include "ui/base/cocoa/animation_utils.h" 16 #include "ui/base/cocoa/animation_utils.h"
17 #include "ui/gfx/size_conversions.h" 17 #include "ui/gfx/size_conversions.h"
18 #include "ui/gl/gpu_switching_manager.h" 18 #include "ui/gl/gpu_switching_manager.h"
19 19
20 @interface CompositingIOSurfaceLayer(Private)
21 - (void)immediatelyForceDisplayAndAck;
22 - (void)ackPendingFrame:(bool)success;
23 - (void)timerFired;
24 @end
25
26 namespace content {
27
28 // The base::DelayTimer needs a C++ class to operate on, rather than Objective C
29 // class. This helper class provides a bridge between the two.
30 class CompositingIOSurfaceLayerHelper {
31 public:
32 CompositingIOSurfaceLayerHelper(CompositingIOSurfaceLayer* layer)
33 : layer_(layer) {}
34 void TimerFired() {
35 [layer_ timerFired];
36 }
37 private:
38 CompositingIOSurfaceLayer* layer_;
39 };
40
41 } // namespace content
42
20 @implementation CompositingIOSurfaceLayer 43 @implementation CompositingIOSurfaceLayer
21 44
22 - (content::CompositingIOSurfaceMac*)iosurface { 45 - (content::CompositingIOSurfaceMac*)iosurface {
23 return iosurface_.get(); 46 return iosurface_.get();
24 } 47 }
25 48
26 - (content::CompositingIOSurfaceContext*)context { 49 - (content::CompositingIOSurfaceContext*)context {
27 return context_.get(); 50 return context_.get();
28 } 51 }
29 52
30 - (id)initWithIOSurface:(scoped_refptr<content::CompositingIOSurfaceMac>) 53 - (id)initWithIOSurface:(scoped_refptr<content::CompositingIOSurfaceMac>)
31 iosurface 54 iosurface
32 withClient:(content::CompositingIOSurfaceLayerClient*)client { 55 withClient:(content::CompositingIOSurfaceLayerClient*)client {
33 if (self = [super init]) { 56 if (self = [super init]) {
34 iosurface_ = iosurface; 57 iosurface_ = iosurface;
35 client_ = client; 58 client_ = client;
59 helper_.reset(new content::CompositingIOSurfaceLayerHelper(self));
60 timer_.reset(new base::DelayTimer<content::CompositingIOSurfaceLayerHelper>(
61 FROM_HERE,
62 base::TimeDelta::FromSeconds(1) / 6,
63 helper_.get(),
64 &content::CompositingIOSurfaceLayerHelper::TimerFired));
36 65
37 context_ = content::CompositingIOSurfaceContext::Get( 66 context_ = content::CompositingIOSurfaceContext::Get(
38 content::CompositingIOSurfaceContext::kCALayerContextWindowNumber); 67 content::CompositingIOSurfaceContext::kCALayerContextWindowNumber);
39 DCHECK(context_); 68 DCHECK(context_);
40 needs_display_ = NO; 69 needs_display_ = NO;
70 has_pending_frame_ = NO;
41 did_not_draw_counter_ = 0; 71 did_not_draw_counter_ = 0;
42 72
43 [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)]; 73 [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
44 [self setAnchorPoint:CGPointMake(0, 0)]; 74 [self setAnchorPoint:CGPointMake(0, 0)];
45 // Setting contents gravity is necessary to prevent the layer from being 75 // Setting contents gravity is necessary to prevent the layer from being
46 // scaled during dyanmic resizes (especially with devtools open). 76 // scaled during dyanmic resizes (especially with devtools open).
47 [self setContentsGravity:kCAGravityTopLeft]; 77 [self setContentsGravity:kCAGravityTopLeft];
48 if ([self respondsToSelector:(@selector(setContentsScale:))]) { 78 if ([self respondsToSelector:(@selector(setContentsScale:))]) {
49 [self setContentsScale:iosurface_->scale_factor()]; 79 [self setContentsScale:iosurface_->scale_factor()];
50 } 80 }
51 } 81 }
52 return self; 82 return self;
53 } 83 }
54 84
55 - (void)resetClient { 85 - (void)resetClient {
56 client_ = NULL; 86 client_ = NULL;
57 } 87 }
58 88
59 - (void)gotNewFrame { 89 - (void)gotNewFrame {
90 has_pending_frame_ = YES;
91 timer_->Reset();
92
93 // A trace value of 2 indicates that there is a pending swap ack. See
94 // canDrawInCGLContext for other value meanings.
95 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, 2);
96
60 if (context_ && context_->is_vsync_disabled()) { 97 if (context_ && context_->is_vsync_disabled()) {
61 // If vsync is disabled, draw immediately and don't bother trying to use 98 // If vsync is disabled, draw immediately and don't bother trying to use
62 // the isAsynchronous property to ensure smooth animation. 99 // the isAsynchronous property to ensure smooth animation.
63 [self setNeedsDisplay]; 100 [self immediatelyForceDisplayAndAck];
64 [self displayIfNeeded];
65
66 // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
67 // rapidly (e.g, with vsync off). This is unacceptable because the failure
68 // to ack a single frame will hang the renderer. Ensure that the renderer
69 // not be blocked by lying and claiming that we drew the frame.
70 if (needs_display_ && client_)
71 client_->AcceleratedLayerDidDrawFrame(true);
72 } else { 101 } else {
73 needs_display_ = YES; 102 needs_display_ = YES;
74 if (![self isAsynchronous]) 103 if (![self isAsynchronous])
75 [self setAsynchronous:YES]; 104 [self setAsynchronous:YES];
76 } 105 }
77 } 106 }
78 107
108 // Private methods:
109
110 - (void)immediatelyForceDisplayAndAck {
111 [self setNeedsDisplay];
112 [self displayIfNeeded];
113
114 // Calls to setNeedsDisplay can sometimes be ignored, especially if issued
115 // rapidly (e.g, with vsync off). This is unacceptable because the failure
116 // to ack a single frame will hang the renderer. Ensure that the renderer
117 // not be blocked by lying and claiming that we drew the frame.
118 [self ackPendingFrame:true];
119 }
120
121 - (void)ackPendingFrame:(bool)success {
122 if (!has_pending_frame_)
123 return;
124
125 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, 0);
126 has_pending_frame_ = NO;
127 if (client_)
128 client_->AcceleratedLayerDidDrawFrame(success);
129 }
130
131 - (void)timerFired {
132 if (has_pending_frame_)
133 [self immediatelyForceDisplayAndAck];
134 }
135
79 // The remaining methods implement the CAOpenGLLayer interface. 136 // The remaining methods implement the CAOpenGLLayer interface.
80 137
81 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { 138 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
82 if (!context_) 139 if (!context_)
83 return [super copyCGLPixelFormatForDisplayMask:mask]; 140 return [super copyCGLPixelFormatForDisplayMask:mask];
84 return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context())); 141 return CGLRetainPixelFormat(CGLGetPixelFormat(context_->cgl_context()));
85 } 142 }
86 143
87 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { 144 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
88 if (!context_) 145 if (!context_)
(...skipping 10 matching lines...) Expand all
99 pixelFormat:(CGLPixelFormatObj)pixelFormat 156 pixelFormat:(CGLPixelFormatObj)pixelFormat
100 forLayerTime:(CFTimeInterval)timeInterval 157 forLayerTime:(CFTimeInterval)timeInterval
101 displayTime:(const CVTimeStamp*)timeStamp { 158 displayTime:(const CVTimeStamp*)timeStamp {
102 // Add an instantaneous blip to the PendingSwapAck state to indicate 159 // Add an instantaneous blip to the PendingSwapAck state to indicate
103 // that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually 160 // that CoreAnimation asked if a frame is ready. A blip up to to 3 (usually
104 // from 2, indicating that a swap ack is pending) indicates that we requested 161 // from 2, indicating that a swap ack is pending) indicates that we requested
105 // a draw. A blip up to 1 (usually from 0, indicating there is no pending swap 162 // a draw. A blip up to 1 (usually from 0, indicating there is no pending swap
106 // ack) indicates that we did not request a draw. This would be more natural 163 // ack) indicates that we did not request a draw. This would be more natural
107 // to do with a tracing pseudo-thread 164 // to do with a tracing pseudo-thread
108 // http://crbug.com/366300 165 // http://crbug.com/366300
109 if (client_) { 166 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, needs_display_ ? 3 : 1);
110 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self, 167 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self,
111 needs_display_ ? 3 : 1); 168 has_pending_frame_ ? 2 : 0);
112 TRACE_COUNTER_ID1("browser", "PendingSwapAck", self,
113 client_->AcceleratedLayerHasNotAckedPendingFrame() ? 2 : 0);
114 }
115 169
116 // If we return NO 30 times in a row, switch to being synchronous to avoid 170 // If we return NO 30 times in a row, switch to being synchronous to avoid
117 // burning CPU cycles on this callback. 171 // burning CPU cycles on this callback.
118 if (needs_display_) { 172 if (needs_display_) {
119 did_not_draw_counter_ = 0; 173 did_not_draw_counter_ = 0;
120 } else { 174 } else {
121 did_not_draw_counter_ += 1; 175 did_not_draw_counter_ += 1;
122 if (did_not_draw_counter_ > 30) 176 if (did_not_draw_counter_ > 30)
123 [self setAsynchronous:NO]; 177 [self setAsynchronous:NO];
124 } 178 }
(...skipping 21 matching lines...) Expand all
146 gfx::Rect window_rect(viewport[0], viewport[1], viewport[2], viewport[3]); 200 gfx::Rect window_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
147 float window_scale_factor = 1.f; 201 float window_scale_factor = 1.f;
148 if ([self respondsToSelector:(@selector(contentsScale))]) 202 if ([self respondsToSelector:(@selector(contentsScale))])
149 window_scale_factor = [self contentsScale]; 203 window_scale_factor = [self contentsScale];
150 window_rect = ToNearestRect( 204 window_rect = ToNearestRect(
151 gfx::ScaleRect(window_rect, 1.f/window_scale_factor)); 205 gfx::ScaleRect(window_rect, 1.f/window_scale_factor));
152 206
153 bool draw_succeeded = iosurface_->DrawIOSurface( 207 bool draw_succeeded = iosurface_->DrawIOSurface(
154 context_, window_rect, window_scale_factor, false); 208 context_, window_rect, window_scale_factor, false);
155 209
210 [self ackPendingFrame:draw_succeeded];
156 needs_display_ = NO; 211 needs_display_ = NO;
157 if (client_)
158 client_->AcceleratedLayerDidDrawFrame(draw_succeeded);
159 212
160 [super drawInCGLContext:glContext 213 [super drawInCGLContext:glContext
161 pixelFormat:pixelFormat 214 pixelFormat:pixelFormat
162 forLayerTime:timeInterval 215 forLayerTime:timeInterval
163 displayTime:timeStamp]; 216 displayTime:timeStamp];
164 } 217 }
165 218
166 @end 219 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698