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

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

Issue 625753002: IOSurface CGL context current lifetime cleanup (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix typo Created 6 years, 2 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
« no previous file with comments | « content/browser/compositor/io_surface_texture_mac.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/compositor/io_surface_texture_mac.h" 5 #include "content/browser/compositor/io_surface_texture_mac.h"
6 6
7 #include <OpenGL/CGLIOSurface.h> 7 #include <OpenGL/CGLIOSurface.h>
8 #include <OpenGL/CGLRenderers.h> 8 #include <OpenGL/CGLRenderers.h>
9 #include <OpenGL/OpenGL.h> 9 #include <OpenGL/OpenGL.h>
10 #include <OpenGL/gl.h> 10 #include <OpenGL/gl.h>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/callback_helpers.h"
14 #include "base/debug/trace_event.h" 15 #include "base/debug/trace_event.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/mac/bind_objc_block.h"
16 #include "base/mac/mac_util.h" 18 #include "base/mac/mac_util.h"
17 #include "base/message_loop/message_loop.h" 19 #include "base/message_loop/message_loop.h"
18 #include "base/threading/platform_thread.h" 20 #include "base/threading/platform_thread.h"
19 #include "content/browser/compositor/io_surface_context_mac.h" 21 #include "content/browser/compositor/io_surface_context_mac.h"
20 #include "content/browser/gpu/gpu_data_manager_impl.h" 22 #include "content/browser/gpu/gpu_data_manager_impl.h"
21 #include "content/browser/renderer_host/render_widget_host_impl.h" 23 #include "content/browser/renderer_host/render_widget_host_impl.h"
22 #include "content/browser/renderer_host/render_widget_host_view_mac.h" 24 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
23 #include "content/common/content_constants_internal.h" 25 #include "content/common/content_constants_internal.h"
24 #include "gpu/config/gpu_driver_bug_workaround_type.h" 26 #include "gpu/config/gpu_driver_bug_workaround_type.h"
25 #include "media/base/video_util.h" 27 #include "media/base/video_util.h"
(...skipping 24 matching lines...) Expand all
50 texture_(0), 52 texture_(0),
51 gl_error_(GL_NO_ERROR), 53 gl_error_(GL_NO_ERROR),
52 eviction_queue_iterator_(eviction_queue_.Get().end()), 54 eviction_queue_iterator_(eviction_queue_.Get().end()),
53 eviction_has_been_drawn_since_updated_(false) { 55 eviction_has_been_drawn_since_updated_(false) {
54 CHECK(offscreen_context_.get()); 56 CHECK(offscreen_context_.get());
55 } 57 }
56 58
57 IOSurfaceTexture::~IOSurfaceTexture() { 59 IOSurfaceTexture::~IOSurfaceTexture() {
58 { 60 {
59 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 61 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
60 offscreen_context_->cgl_context()); 62 offscreen_context_->cgl_context());
Ken Russell (switch to Gerrit) 2014/10/07 22:09:44 Per our over-the-shoulder review, this ScopedCGLSe
ccameron 2014/10/07 22:33:45 Done.
61 UnrefIOSurfaceWithContextCurrent(); 63 ReleaseIOSurfaceAndTexture();
62 } 64 }
63 offscreen_context_ = NULL; 65 offscreen_context_ = NULL;
64 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end()); 66 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
65 } 67 }
66 68
67 int IOSurfaceTexture::GetRendererID() {
68 GLint current_renderer_id = -1;
69 if (CGLGetParameter(offscreen_context_->cgl_context(),
70 kCGLCPCurrentRendererID,
71 &current_renderer_id) == kCGLNoError)
72 return current_renderer_id & kCGLRendererIDMatchingMask;
73 return -1;
74 }
75
76 bool IOSurfaceTexture::DrawIOSurface() { 69 bool IOSurfaceTexture::DrawIOSurface() {
77 TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface"); 70 TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface");
78 DCHECK(HasIOSurface()); 71
72 // If we have release the IOSurface, clear the screen to light grey and
73 // early-out.
74 if (!io_surface_) {
75 glClearColor(0.9, 0.9, 0.9, 1);
76 glClear(GL_COLOR_BUFFER_BIT);
77 return false;
78 }
79 79
80 // The viewport is the size of the CALayer, which should always match the 80 // The viewport is the size of the CALayer, which should always match the
81 // IOSurface pixel size. 81 // IOSurface pixel size.
82 GLint viewport[4]; 82 GLint viewport[4];
83 glGetIntegerv(GL_VIEWPORT, viewport); 83 glGetIntegerv(GL_VIEWPORT, viewport);
84 gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]); 84 gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
85 DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString()); 85 DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString());
86 86
87 // Set the projection matrix to match 1 unit to 1 pixel. 87 // Set the projection matrix to match 1 unit to 1 pixel.
88 glMatrixMode(GL_PROJECTION); 88 glMatrixMode(GL_PROJECTION);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // rendering artifacts. 132 // rendering artifacts.
133 glClearColor(0.8, 0.8, 0.8, 1.0); 133 glClearColor(0.8, 0.8, 0.8, 1.0);
134 glClear(GL_COLOR_BUFFER_BIT); 134 glClear(GL_COLOR_BUFFER_BIT);
135 } 135 }
136 136
137 eviction_has_been_drawn_since_updated_ = true; 137 eviction_has_been_drawn_since_updated_ = true;
138 return result; 138 return result;
139 } 139 }
140 140
141 bool IOSurfaceTexture::SetIOSurface( 141 bool IOSurfaceTexture::SetIOSurface(
142 scoped_refptr<IOSurfaceContext> context,
143 IOSurfaceID io_surface_id, 142 IOSurfaceID io_surface_id,
144 const gfx::Size& pixel_size) { 143 const gfx::Size& pixel_size) {
145 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture"); 144 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture");
146 145
147 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
148 context->cgl_context());
149
150 // Destroy the old IOSurface and texture if it is no longer needed. 146 // Destroy the old IOSurface and texture if it is no longer needed.
151 bool needs_new_iosurface = 147 bool needs_new_iosurface =
152 !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_); 148 !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_);
153 if (needs_new_iosurface) 149 if (needs_new_iosurface)
154 UnrefIOSurfaceWithContextCurrent(); 150 ReleaseIOSurfaceAndTexture();
155 151
156 // Note that because IOSurface sizes are rounded, the same IOSurface may have 152 // Note that because IOSurface sizes are rounded, the same IOSurface may have
157 // two different sizes associated with it, so update the sizes before the 153 // two different sizes associated with it, so update the sizes before the
158 // early-out. 154 // early-out.
159 pixel_size_ = pixel_size; 155 pixel_size_ = pixel_size;
160 156
161 // Early-out if the IOSurface has not changed. 157 // Early-out if the IOSurface has not changed.
162 if (!needs_new_iosurface) 158 if (!needs_new_iosurface)
163 return true; 159 return true;
164 160
161 // If we early-out at any point from now on, it's because of an error, and we
162 // should destroy the texture and release the IOSurface.
163 base::ScopedClosureRunner error_runner(base::BindBlock(^{
164 ReleaseIOSurfaceAndTexture();
165 }));
166
165 // Open the IOSurface handle. 167 // Open the IOSurface handle.
166 io_surface_.reset(IOSurfaceLookup(io_surface_id)); 168 io_surface_.reset(IOSurfaceLookup(io_surface_id));
167 if (!io_surface_) { 169 if (!io_surface_)
168 UnrefIOSurfaceWithContextCurrent();
169 return false; 170 return false;
170 }
171 171
172 // Actual IOSurface size is rounded up to reduce reallocations during window 172 // Actual IOSurface size is rounded up to reduce reallocations during window
173 // resize. Get the actual size to properly map the texture. 173 // resize. Get the actual size to properly map the texture.
174 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_), 174 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
175 IOSurfaceGetHeight(io_surface_)); 175 IOSurfaceGetHeight(io_surface_));
176 176
177 // Create the GL texture and set it to be backed by the IOSurface. 177 // Create the GL texture and set it to be backed by the IOSurface.
178 glGenTextures(1, &texture_); 178 CGLError cgl_error = kCGLNoError;
179 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 179 {
180 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 180 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
181 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 181 offscreen_context_->cgl_context());
Ken Russell (switch to Gerrit) 2014/10/04 00:33:39 I'm sure I'm being dense, but am finding it diffic
ccameron 2014/10/04 00:49:37 The types (kCALayerContext v kOffscreenContext) ac
182 GLuint plane = 0; 182 glGenTextures(1, &texture_);
183 CGLError cgl_error = CGLTexImageIOSurface2D( 183 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
184 context->cgl_context(), 184 glTexParameterf(
185 GL_TEXTURE_RECTANGLE_ARB, 185 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
186 GL_RGBA, 186 glTexParameterf(
187 rounded_size.width(), 187 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
188 rounded_size.height(), 188 cgl_error = CGLTexImageIOSurface2D(
189 GL_BGRA, 189 offscreen_context_->cgl_context(),
190 GL_UNSIGNED_INT_8_8_8_8_REV, 190 GL_TEXTURE_RECTANGLE_ARB,
191 io_surface_.get(), 191 GL_RGBA,
192 plane); 192 rounded_size.width(),
193 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 193 rounded_size.height(),
194 GetAndSaveGLError(); 194 GL_BGRA,
195 GL_UNSIGNED_INT_8_8_8_8_REV,
196 io_surface_.get(),
197 0 /* plane */);
198 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
199 GetAndSaveGLError();
200 }
195 201
196 // Return failure if an error was encountered by CGL or GL. 202 // Return failure if an error was encountered by CGL or GL.
197 if (cgl_error != kCGLNoError) { 203 if (cgl_error != kCGLNoError) {
198 LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error; 204 LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error;
199 UnrefIOSurfaceWithContextCurrent();
200 return false; 205 return false;
201 } 206 }
202 if (gl_error_ != GL_NO_ERROR) { 207 if (gl_error_ != GL_NO_ERROR) {
203 LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_; 208 LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_;
204 UnrefIOSurfaceWithContextCurrent();
205 return false; 209 return false;
206 } 210 }
207 211
212 ignore_result(error_runner.Release());
208 return true; 213 return true;
209 } 214 }
210 215
211 void IOSurfaceTexture::UnrefIOSurface() { 216 void IOSurfaceTexture::ReleaseIOSurfaceAndTexture() {
212 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 217 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
213 offscreen_context_->cgl_context()); 218 offscreen_context_->cgl_context());
214 UnrefIOSurfaceWithContextCurrent();
215 }
216 219
217 void IOSurfaceTexture::UnrefIOSurfaceWithContextCurrent() {
218 if (texture_) { 220 if (texture_) {
219 glDeleteTextures(1, &texture_); 221 glDeleteTextures(1, &texture_);
220 texture_ = 0; 222 texture_ = 0;
221 } 223 }
222 pixel_size_ = gfx::Size(); 224 pixel_size_ = gfx::Size();
223 io_surface_.reset(); 225 io_surface_.reset();
224 226
225 EvictionMarkEvicted(); 227 EvictionMarkEvicted();
226 } 228 }
227 229
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 // If the number of IOSurfaces allocated is less than the threshold, 280 // If the number of IOSurfaces allocated is less than the threshold,
279 // stop walking the list of surfaces. 281 // stop walking the list of surfaces.
280 if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces) 282 if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
281 break; 283 break;
282 284
283 // Don't evict anything that has not yet been drawn. 285 // Don't evict anything that has not yet been drawn.
284 if (!surface->eviction_has_been_drawn_since_updated_) 286 if (!surface->eviction_has_been_drawn_since_updated_)
285 continue; 287 continue;
286 288
287 // Evict the surface. 289 // Evict the surface.
288 surface->UnrefIOSurface(); 290 surface->ReleaseIOSurfaceAndTexture();
289 } 291 }
290 } 292 }
291 293
292 // static 294 // static
293 base::LazyInstance<IOSurfaceTexture::EvictionQueue> 295 base::LazyInstance<IOSurfaceTexture::EvictionQueue>
294 IOSurfaceTexture::eviction_queue_; 296 IOSurfaceTexture::eviction_queue_;
295 297
296 // static 298 // static
297 bool IOSurfaceTexture::eviction_scheduled_ = false; 299 bool IOSurfaceTexture::eviction_scheduled_ = false;
298 300
299 } // namespace content 301 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/compositor/io_surface_texture_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698