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

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: Incorporate review feedback 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 22 matching lines...) Expand all
48 const scoped_refptr<IOSurfaceContext>& offscreen_context) 50 const scoped_refptr<IOSurfaceContext>& offscreen_context)
49 : offscreen_context_(offscreen_context), 51 : offscreen_context_(offscreen_context),
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 ReleaseIOSurfaceAndTexture();
59 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
60 offscreen_context_->cgl_context());
61 UnrefIOSurfaceWithContextCurrent();
62 }
63 offscreen_context_ = NULL; 61 offscreen_context_ = NULL;
64 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end()); 62 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
65 } 63 }
66 64
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() { 65 bool IOSurfaceTexture::DrawIOSurface() {
77 TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface"); 66 TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface");
78 DCHECK(HasIOSurface()); 67
68 // If we have release the IOSurface, clear the screen to light grey and
69 // early-out.
70 if (!io_surface_) {
71 glClearColor(0.9, 0.9, 0.9, 1);
72 glClear(GL_COLOR_BUFFER_BIT);
73 return false;
74 }
79 75
80 // The viewport is the size of the CALayer, which should always match the 76 // The viewport is the size of the CALayer, which should always match the
81 // IOSurface pixel size. 77 // IOSurface pixel size.
82 GLint viewport[4]; 78 GLint viewport[4];
83 glGetIntegerv(GL_VIEWPORT, viewport); 79 glGetIntegerv(GL_VIEWPORT, viewport);
84 gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]); 80 gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
85 DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString()); 81 DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString());
86 82
87 // Set the projection matrix to match 1 unit to 1 pixel. 83 // Set the projection matrix to match 1 unit to 1 pixel.
88 glMatrixMode(GL_PROJECTION); 84 glMatrixMode(GL_PROJECTION);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // rendering artifacts. 128 // rendering artifacts.
133 glClearColor(0.8, 0.8, 0.8, 1.0); 129 glClearColor(0.8, 0.8, 0.8, 1.0);
134 glClear(GL_COLOR_BUFFER_BIT); 130 glClear(GL_COLOR_BUFFER_BIT);
135 } 131 }
136 132
137 eviction_has_been_drawn_since_updated_ = true; 133 eviction_has_been_drawn_since_updated_ = true;
138 return result; 134 return result;
139 } 135 }
140 136
141 bool IOSurfaceTexture::SetIOSurface( 137 bool IOSurfaceTexture::SetIOSurface(
142 scoped_refptr<IOSurfaceContext> context,
143 IOSurfaceID io_surface_id, 138 IOSurfaceID io_surface_id,
144 const gfx::Size& pixel_size) { 139 const gfx::Size& pixel_size) {
145 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture"); 140 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture");
146 141
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. 142 // Destroy the old IOSurface and texture if it is no longer needed.
151 bool needs_new_iosurface = 143 bool needs_new_iosurface =
152 !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_); 144 !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_);
153 if (needs_new_iosurface) 145 if (needs_new_iosurface)
154 UnrefIOSurfaceWithContextCurrent(); 146 ReleaseIOSurfaceAndTexture();
155 147
156 // Note that because IOSurface sizes are rounded, the same IOSurface may have 148 // 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 149 // two different sizes associated with it, so update the sizes before the
158 // early-out. 150 // early-out.
159 pixel_size_ = pixel_size; 151 pixel_size_ = pixel_size;
160 152
161 // Early-out if the IOSurface has not changed. 153 // Early-out if the IOSurface has not changed.
162 if (!needs_new_iosurface) 154 if (!needs_new_iosurface)
163 return true; 155 return true;
164 156
157 // If we early-out at any point from now on, it's because of an error, and we
158 // should destroy the texture and release the IOSurface.
159 base::ScopedClosureRunner error_runner(base::BindBlock(^{
160 ReleaseIOSurfaceAndTexture();
161 }));
162
165 // Open the IOSurface handle. 163 // Open the IOSurface handle.
166 io_surface_.reset(IOSurfaceLookup(io_surface_id)); 164 io_surface_.reset(IOSurfaceLookup(io_surface_id));
167 if (!io_surface_) { 165 if (!io_surface_)
168 UnrefIOSurfaceWithContextCurrent();
169 return false; 166 return false;
170 }
171 167
172 // Actual IOSurface size is rounded up to reduce reallocations during window 168 // Actual IOSurface size is rounded up to reduce reallocations during window
173 // resize. Get the actual size to properly map the texture. 169 // resize. Get the actual size to properly map the texture.
174 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_), 170 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
175 IOSurfaceGetHeight(io_surface_)); 171 IOSurfaceGetHeight(io_surface_));
176 172
177 // Create the GL texture and set it to be backed by the IOSurface. 173 // Create the GL texture and set it to be backed by the IOSurface.
178 glGenTextures(1, &texture_); 174 CGLError cgl_error = kCGLNoError;
179 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 175 {
180 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 176 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
181 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 177 offscreen_context_->cgl_context());
182 GLuint plane = 0; 178 glGenTextures(1, &texture_);
183 CGLError cgl_error = CGLTexImageIOSurface2D( 179 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
184 context->cgl_context(), 180 glTexParameterf(
185 GL_TEXTURE_RECTANGLE_ARB, 181 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
186 GL_RGBA, 182 glTexParameterf(
187 rounded_size.width(), 183 GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
188 rounded_size.height(), 184 cgl_error = CGLTexImageIOSurface2D(
189 GL_BGRA, 185 offscreen_context_->cgl_context(),
190 GL_UNSIGNED_INT_8_8_8_8_REV, 186 GL_TEXTURE_RECTANGLE_ARB,
191 io_surface_.get(), 187 GL_RGBA,
192 plane); 188 rounded_size.width(),
193 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 189 rounded_size.height(),
194 GetAndSaveGLError(); 190 GL_BGRA,
191 GL_UNSIGNED_INT_8_8_8_8_REV,
192 io_surface_.get(),
193 0 /* plane */);
194 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
195 GetAndSaveGLError();
196 }
195 197
196 // Return failure if an error was encountered by CGL or GL. 198 // Return failure if an error was encountered by CGL or GL.
197 if (cgl_error != kCGLNoError) { 199 if (cgl_error != kCGLNoError) {
198 LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error; 200 LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error;
199 UnrefIOSurfaceWithContextCurrent();
200 return false; 201 return false;
201 } 202 }
202 if (gl_error_ != GL_NO_ERROR) { 203 if (gl_error_ != GL_NO_ERROR) {
203 LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_; 204 LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_;
204 UnrefIOSurfaceWithContextCurrent();
205 return false; 205 return false;
206 } 206 }
207 207
208 ignore_result(error_runner.Release());
208 return true; 209 return true;
209 } 210 }
210 211
211 void IOSurfaceTexture::UnrefIOSurface() { 212 void IOSurfaceTexture::ReleaseIOSurfaceAndTexture() {
212 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 213 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
213 offscreen_context_->cgl_context()); 214 offscreen_context_->cgl_context());
214 UnrefIOSurfaceWithContextCurrent();
215 }
216 215
217 void IOSurfaceTexture::UnrefIOSurfaceWithContextCurrent() {
218 if (texture_) { 216 if (texture_) {
219 glDeleteTextures(1, &texture_); 217 glDeleteTextures(1, &texture_);
220 texture_ = 0; 218 texture_ = 0;
221 } 219 }
222 pixel_size_ = gfx::Size(); 220 pixel_size_ = gfx::Size();
223 io_surface_.reset(); 221 io_surface_.reset();
224 222
225 EvictionMarkEvicted(); 223 EvictionMarkEvicted();
226 } 224 }
227 225
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 // If the number of IOSurfaces allocated is less than the threshold, 276 // If the number of IOSurfaces allocated is less than the threshold,
279 // stop walking the list of surfaces. 277 // stop walking the list of surfaces.
280 if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces) 278 if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
281 break; 279 break;
282 280
283 // Don't evict anything that has not yet been drawn. 281 // Don't evict anything that has not yet been drawn.
284 if (!surface->eviction_has_been_drawn_since_updated_) 282 if (!surface->eviction_has_been_drawn_since_updated_)
285 continue; 283 continue;
286 284
287 // Evict the surface. 285 // Evict the surface.
288 surface->UnrefIOSurface(); 286 surface->ReleaseIOSurfaceAndTexture();
289 } 287 }
290 } 288 }
291 289
292 // static 290 // static
293 base::LazyInstance<IOSurfaceTexture::EvictionQueue> 291 base::LazyInstance<IOSurfaceTexture::EvictionQueue>
294 IOSurfaceTexture::eviction_queue_; 292 IOSurfaceTexture::eviction_queue_;
295 293
296 // static 294 // static
297 bool IOSurfaceTexture::eviction_scheduled_ = false; 295 bool IOSurfaceTexture::eviction_scheduled_ = false;
298 296
299 } // namespace content 297 } // 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