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

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

Issue 454243002: Make GPU back-pressure work with remote CALayers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix flashes Created 6 years, 4 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/mac/sdk_forward_declarations.h" 7 #include "base/mac/sdk_forward_declarations.h"
8 #include "content/common/gpu/surface_handle_types_mac.h" 8 #include "content/common/gpu/surface_handle_types_mac.h"
9 #include "ui/base/cocoa/animation_utils.h" 9 #include "ui/base/cocoa/animation_utils.h"
10 #include "ui/gfx/geometry/size_conversions.h" 10 #include "ui/gfx/geometry/size_conversions.h"
11 11
12 @interface ImageTransportLayer (Private) { 12 @interface ImageTransportLayer : CAOpenGLLayer {
13 content::CALayerStorageProvider* storageProvider_;
13 } 14 }
15 - (id)initWithStorageProvider:(content::CALayerStorageProvider*)storageProvider;
16 - (void)resetStorageProvider;
14 @end 17 @end
15 18
16 @implementation ImageTransportLayer 19 @implementation ImageTransportLayer
17 20
18 - (id)initWithContext:(CGLContextObj)context 21 - (id)initWithStorageProvider:
19 withTexture:(GLuint)texture 22 (content::CALayerStorageProvider*)storageProvider {
20 withPixelSize:(gfx::Size)pixelSize 23 if (self = [super init])
21 withScaleFactor:(float)scaleFactor { 24 storageProvider_ = storageProvider;
22 if (self = [super init]) {
23 shareContext_.reset(CGLRetainContext(context));
24 texture_ = texture;
25 pixelSize_ = pixelSize;
26
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())];
31 }
32 return self; 25 return self;
33 } 26 }
34 27
28 - (void)resetStorageProvider {
29 storageProvider_ = NULL;
30 }
31
35 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask { 32 - (CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask {
36 return CGLRetainPixelFormat(CGLGetPixelFormat(shareContext_)); 33 if (!storageProvider_)
34 return NULL;
35 return CGLRetainPixelFormat(CGLGetPixelFormat(
36 storageProvider_->LayerShareGroupContext()));
37 } 37 }
38 38
39 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { 39 - (CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat {
40 if (!storageProvider_)
41 return NULL;
40 CGLContextObj context = NULL; 42 CGLContextObj context = NULL;
41 CGLError error = CGLCreateContext(pixelFormat, shareContext_, &context); 43 CGLError error = CGLCreateContext(
44 pixelFormat, storageProvider_->LayerShareGroupContext(), &context);
42 if (error != kCGLNoError) 45 if (error != kCGLNoError)
43 DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error; 46 DLOG(ERROR) << "CGLCreateContext failed with CGL error: " << error;
44 return context; 47 return context;
45 } 48 }
46 49
47 - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext 50 - (BOOL)canDrawInCGLContext:(CGLContextObj)glContext
48 pixelFormat:(CGLPixelFormatObj)pixelFormat 51 pixelFormat:(CGLPixelFormatObj)pixelFormat
49 forLayerTime:(CFTimeInterval)timeInterval 52 forLayerTime:(CFTimeInterval)timeInterval
50 displayTime:(const CVTimeStamp*)timeStamp { 53 displayTime:(const CVTimeStamp*)timeStamp {
51 return YES; 54 if (!storageProvider_)
55 return NO;
56 return storageProvider_->LayerCanDraw();
52 } 57 }
53 58
54 - (void)drawInCGLContext:(CGLContextObj)glContext 59 - (void)drawInCGLContext:(CGLContextObj)glContext
55 pixelFormat:(CGLPixelFormatObj)pixelFormat 60 pixelFormat:(CGLPixelFormatObj)pixelFormat
56 forLayerTime:(CFTimeInterval)timeInterval 61 forLayerTime:(CFTimeInterval)timeInterval
57 displayTime:(const CVTimeStamp*)timeStamp { 62 displayTime:(const CVTimeStamp*)timeStamp {
58 glClearColor(1, 0, 1, 1); 63 if (storageProvider_) {
59 glClear(GL_COLOR_BUFFER_BIT); 64 storageProvider_->LayerDoDraw();
60 65 } else {
61 GLint viewport[4] = {0, 0, 0, 0}; 66 glClearColor(1, 1, 1, 1);
62 glGetIntegerv(GL_VIEWPORT, viewport); 67 glClear(GL_COLOR_BUFFER_BIT);
63 gfx::Size viewportSize(viewport[2], viewport[3]);
64
65 // Set the coordinate system to be one-to-one with pixels.
66 glMatrixMode(GL_PROJECTION);
67 glLoadIdentity();
68 glOrtho(0, viewportSize.width(), 0, viewportSize.height(), -1, 1);
69 glMatrixMode(GL_MODELVIEW);
70 glLoadIdentity();
71
72 // Draw a fullscreen quad.
73 glColor4f(1, 1, 1, 1);
74 glEnable(GL_TEXTURE_RECTANGLE_ARB);
75 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
76 glBegin(GL_QUADS);
77 {
78 glTexCoord2f(0, 0);
79 glVertex2f(0, 0);
80
81 glTexCoord2f(0, pixelSize_.height());
82 glVertex2f(0, pixelSize_.height());
83
84 glTexCoord2f(pixelSize_.width(), pixelSize_.height());
85 glVertex2f(pixelSize_.width(), pixelSize_.height());
86
87 glTexCoord2f(pixelSize_.width(), 0);
88 glVertex2f(pixelSize_.width(), 0);
89 } 68 }
90 glEnd();
91 glBindTexture(0, texture_);
92 glDisable(GL_TEXTURE_RECTANGLE_ARB);
93
94 [super drawInCGLContext:glContext 69 [super drawInCGLContext:glContext
95 pixelFormat:pixelFormat 70 pixelFormat:pixelFormat
96 forLayerTime:timeInterval 71 forLayerTime:timeInterval
97 displayTime:timeStamp]; 72 displayTime:timeStamp];
98 } 73 }
99 74
100 @end 75 @end
101 76
102 namespace content { 77 namespace content {
103 78
104 CALayerStorageProvider::CALayerStorageProvider() { 79 CALayerStorageProvider::CALayerStorageProvider(
80 ImageTransportSurfaceFBO* transport_surface)
81 : transport_surface_(transport_surface),
82 has_pending_draw_(false),
83 can_draw_returned_false_count_(0),
84 fbo_texture_(0) {
85 // Allocate a CAContext to use to transport the CALayer to the browser
86 // process.
105 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]); 87 base::scoped_nsobject<NSDictionary> dict([[NSDictionary alloc] init]);
106 CGSConnectionID connection_id = CGSMainConnectionID(); 88 CGSConnectionID connection_id = CGSMainConnectionID();
107 context_.reset([CAContext contextWithCGSConnection:connection_id 89 context_.reset([CAContext contextWithCGSConnection:connection_id
108 options:dict]); 90 options:dict]);
109 [context_ retain]; 91 [context_ retain];
110 } 92 }
111 93
112 CALayerStorageProvider::~CALayerStorageProvider() { 94 CALayerStorageProvider::~CALayerStorageProvider() {
113 } 95 }
114 96
(...skipping 22 matching lines...) Expand all
137 error = glGetError(); 119 error = glGetError();
138 if (error != GL_NO_ERROR) { 120 if (error != GL_NO_ERROR) {
139 DLOG(ERROR) << "glTexImage failed with GL error: " << error; 121 DLOG(ERROR) << "glTexImage failed with GL error: " << error;
140 return false; 122 return false;
141 } 123 }
142 glFlush(); 124 glFlush();
143 125
144 // Disable the fade-in animation as the layer is changed. 126 // Disable the fade-in animation as the layer is changed.
145 ScopedCAActionDisabler disabler; 127 ScopedCAActionDisabler disabler;
146 128
147 // Resize the CAOpenGLLayer to match the size needed, and change it to be the 129 // Allocate a CALayer to draw texture into.
148 // hosted layer. 130 share_group_context_.reset(CGLRetainContext(context));
149 layer_.reset([[ImageTransportLayer alloc] initWithContext:context 131 fbo_texture_ = texture;
150 withTexture:texture 132 fbo_pixel_size_ = pixel_size;
151 withPixelSize:pixel_size 133 layer_.reset([[ImageTransportLayer alloc] initWithStorageProvider:this]);
152 withScaleFactor: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())];
153 return true; 138 return true;
154 } 139 }
155 140
156 void CALayerStorageProvider::FreeColorBufferStorage() { 141 void CALayerStorageProvider::FreeColorBufferStorage() {
157 [context_ setLayer:nil]; 142 // We shouldn't be asked to free a texture when we still have yet to draw it.
143 DCHECK(!has_pending_draw_);
144 has_pending_draw_ = false;
145 can_draw_returned_false_count_ = 0;
146
147 // Note that |context_| still holds a reference to |layer_|, and will until
148 // a new frame is swapped in.
149 [layer_ displayIfNeeded];
150 [layer_ resetStorageProvider];
158 layer_.reset(); 151 layer_.reset();
152
153 share_group_context_.reset();
154 fbo_texture_ = 0;
155 fbo_pixel_size_ = gfx::Size();
159 } 156 }
160 157
161 uint64 CALayerStorageProvider::GetSurfaceHandle() const { 158 uint64 CALayerStorageProvider::GetSurfaceHandle() const {
162 return SurfaceHandleFromCAContextID([context_ contextId]); 159 return SurfaceHandleFromCAContextID([context_ contextId]);
163 } 160 }
164 161
165 void CALayerStorageProvider::WillSwapBuffers() { 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 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 167 // called, because the texture does not have any content until the
168 // SwapBuffers call is about to be made. 168 // SwapBuffers call is about to be made.
169 if ([context_ layer] != layer_.get()) 169 if ([context_ layer] != layer_.get())
170 [context_ setLayer:layer_]; 170 [context_ setLayer:layer_];
171 171
172 // TODO(ccameron): Use the isAsynchronous property to ensure smooth 172 if (![layer_ isAsynchronous])
173 // animation. 173 [layer_ setAsynchronous:YES];
174 [layer_ setNeedsDisplay]; 174 }
175
176 void CALayerStorageProvider::CanFreeSwappedBuffer() {
177 }
178
179 CGLContextObj CALayerStorageProvider::LayerShareGroupContext() {
180 return share_group_context_;
181 }
182
183 bool CALayerStorageProvider::LayerCanDraw() {
184 if (has_pending_draw_) {
185 can_draw_returned_false_count_ = 0;
186 return true;
187 } else {
188 if (can_draw_returned_false_count_ == 30) {
189 if ([layer_ isAsynchronous])
190 [layer_ setAsynchronous:NO];
191 } else {
192 can_draw_returned_false_count_ += 1;
193 }
194 return false;
195 }
196 }
197
198 void CALayerStorageProvider::LayerDoDraw() {
199 DCHECK(has_pending_draw_);
200 has_pending_draw_ = false;
201
202 GLint viewport[4] = {0, 0, 0, 0};
203 glGetIntegerv(GL_VIEWPORT, viewport);
204 gfx::Size viewport_size(viewport[2], viewport[3]);
205
206 // Set the coordinate system to be one-to-one with pixels.
207 glMatrixMode(GL_PROJECTION);
208 glLoadIdentity();
209 glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1);
210 glMatrixMode(GL_MODELVIEW);
211 glLoadIdentity();
212
213 // Draw a fullscreen quad.
214 glColor4f(1, 1, 1, 1);
215 glEnable(GL_TEXTURE_RECTANGLE_ARB);
216 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fbo_texture_);
217 glBegin(GL_QUADS);
218 {
219 glTexCoord2f(0, 0);
220 glVertex2f(0, 0);
221
222 glTexCoord2f(0, fbo_pixel_size_.height());
223 glVertex2f(0, fbo_pixel_size_.height());
224
225 glTexCoord2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
226 glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height());
227
228 glTexCoord2f(fbo_pixel_size_.width(), 0);
229 glVertex2f(fbo_pixel_size_.width(), 0);
230 }
231 glEnd();
232 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
233 glDisable(GL_TEXTURE_RECTANGLE_ARB);
234
235 // Allow forward progress in the context now that the swap is complete.
236 transport_surface_->UnblockContextAfterPendingSwap();
175 } 237 }
176 238
177 } // 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