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

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

Issue 623563003: Refactor and delete IOSurface code (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase 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>
(...skipping 11 matching lines...) Expand all
22 #include "content/browser/renderer_host/render_widget_host_view_mac.h" 22 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
23 #include "content/common/content_constants_internal.h" 23 #include "content/common/content_constants_internal.h"
24 #include "gpu/config/gpu_driver_bug_workaround_type.h" 24 #include "gpu/config/gpu_driver_bug_workaround_type.h"
25 #include "media/base/video_util.h" 25 #include "media/base/video_util.h"
26 #include "third_party/skia/include/core/SkBitmap.h" 26 #include "third_party/skia/include/core/SkBitmap.h"
27 #include "ui/gfx/rect.h" 27 #include "ui/gfx/rect.h"
28 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 28 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
29 #include "ui/gfx/size_conversions.h" 29 #include "ui/gfx/size_conversions.h"
30 #include "ui/gl/gl_context.h" 30 #include "ui/gl/gl_context.h"
31 31
32 #ifdef NDEBUG
33 #define CHECK_GL_ERROR()
34 #define CHECK_AND_SAVE_GL_ERROR()
35 #else
36 #define CHECK_GL_ERROR() do { \
37 GLenum gl_error = glGetError(); \
38 LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
39 } while (0)
40 #define CHECK_AND_SAVE_GL_ERROR() do { \
41 GLenum gl_error = GetAndSaveGLError(); \
42 LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
43 } while (0)
44 #endif
45
46 namespace content { 32 namespace content {
47 33
48 // static 34 // static
49 scoped_refptr<IOSurfaceTexture> IOSurfaceTexture::Create() { 35 scoped_refptr<IOSurfaceTexture> IOSurfaceTexture::Create() {
50 scoped_refptr<IOSurfaceContext> offscreen_context = 36 scoped_refptr<IOSurfaceContext> offscreen_context =
51 IOSurfaceContext::Get( 37 IOSurfaceContext::Get(
52 IOSurfaceContext::kOffscreenContext); 38 IOSurfaceContext::kOffscreenContext);
53 if (!offscreen_context.get()) { 39 if (!offscreen_context.get()) {
54 LOG(ERROR) << "Failed to create context for offscreen operations"; 40 LOG(ERROR) << "Failed to create context for offscreen operations";
55 return NULL; 41 return NULL;
56 } 42 }
57 43
58 return new IOSurfaceTexture(offscreen_context); 44 return new IOSurfaceTexture(offscreen_context);
59 } 45 }
60 46
61 IOSurfaceTexture::IOSurfaceTexture( 47 IOSurfaceTexture::IOSurfaceTexture(
62 const scoped_refptr<IOSurfaceContext>& offscreen_context) 48 const scoped_refptr<IOSurfaceContext>& offscreen_context)
63 : offscreen_context_(offscreen_context), 49 : offscreen_context_(offscreen_context),
64 io_surface_handle_(0),
65 scale_factor_(1.f),
66 texture_(0), 50 texture_(0),
67 gl_error_(GL_NO_ERROR), 51 gl_error_(GL_NO_ERROR),
68 eviction_queue_iterator_(eviction_queue_.Get().end()), 52 eviction_queue_iterator_(eviction_queue_.Get().end()),
69 eviction_has_been_drawn_since_updated_(false) { 53 eviction_has_been_drawn_since_updated_(false) {
70 CHECK(offscreen_context_.get()); 54 CHECK(offscreen_context_.get());
71 } 55 }
72 56
73 IOSurfaceTexture::~IOSurfaceTexture() { 57 IOSurfaceTexture::~IOSurfaceTexture() {
74 { 58 {
75 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 59 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
76 offscreen_context_->cgl_context()); 60 offscreen_context_->cgl_context());
77 UnrefIOSurfaceWithContextCurrent(); 61 UnrefIOSurfaceWithContextCurrent();
78 } 62 }
79 offscreen_context_ = NULL; 63 offscreen_context_ = NULL;
80 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end()); 64 DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
81 } 65 }
82 66
83 bool IOSurfaceTexture::SetIOSurfaceWithContextCurrent(
84 scoped_refptr<IOSurfaceContext> current_context,
85 IOSurfaceID io_surface_handle,
86 const gfx::Size& size,
87 float scale_factor) {
88 bool result = MapIOSurfaceToTextureWithContextCurrent(
89 current_context, size, scale_factor, io_surface_handle);
90 EvictionMarkUpdated();
91 return result;
92 }
93
94 int IOSurfaceTexture::GetRendererID() { 67 int IOSurfaceTexture::GetRendererID() {
95 GLint current_renderer_id = -1; 68 GLint current_renderer_id = -1;
96 if (CGLGetParameter(offscreen_context_->cgl_context(), 69 if (CGLGetParameter(offscreen_context_->cgl_context(),
97 kCGLCPCurrentRendererID, 70 kCGLCPCurrentRendererID,
98 &current_renderer_id) == kCGLNoError) 71 &current_renderer_id) == kCGLNoError)
99 return current_renderer_id & kCGLRendererIDMatchingMask; 72 return current_renderer_id & kCGLRendererIDMatchingMask;
100 return -1; 73 return -1;
101 } 74 }
102 75
103 bool IOSurfaceTexture::DrawIOSurface( 76 bool IOSurfaceTexture::DrawIOSurface() {
104 scoped_refptr<IOSurfaceContext> drawing_context, 77 TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface");
105 const gfx::Rect& window_rect, 78 DCHECK(HasIOSurface());
106 float window_scale_factor) {
107 DCHECK_EQ(CGLGetCurrentContext(), drawing_context->cgl_context());
108 79
109 bool has_io_surface = HasIOSurface(); 80 // The viewport is the size of the CALayer, which should always match the
110 TRACE_EVENT1("browser", "IOSurfaceTexture::DrawIOSurface", 81 // IOSurface pixel size.
111 "has_io_surface", has_io_surface); 82 GLint viewport[4];
83 glGetIntegerv(GL_VIEWPORT, viewport);
84 gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
85 DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString());
112 86
113 gfx::Rect pixel_window_rect = 87 // Set the projection matrix to match 1 unit to 1 pixel.
114 ToNearestRect(gfx::ScaleRect(window_rect, window_scale_factor));
115 glViewport(
116 pixel_window_rect.x(), pixel_window_rect.y(),
117 pixel_window_rect.width(), pixel_window_rect.height());
118
119 SurfaceQuad quad;
120 quad.set_size(dip_io_surface_size_, pixel_io_surface_size_);
121
122 glMatrixMode(GL_PROJECTION); 88 glMatrixMode(GL_PROJECTION);
123 glLoadIdentity(); 89 glLoadIdentity();
124 90 glOrtho(0, viewport_rect.width(), 0, viewport_rect.height(), -1, 1);
125 // Note that the projection keeps things in view units, so the use of
126 // window_rect / dip_io_surface_size_ (as opposed to the pixel_ variants)
127 // below is correct.
128 glOrtho(0, window_rect.width(), window_rect.height(), 0, -1, 1);
129 glMatrixMode(GL_MODELVIEW); 91 glMatrixMode(GL_MODELVIEW);
130 glLoadIdentity(); 92 glLoadIdentity();
131 93
132 glDisable(GL_DEPTH_TEST); 94 // Draw a quad the size of the IOSurface. This should cover the full viewport.
133 glDisable(GL_BLEND); 95 glColor4f(1, 1, 1, 1);
96 glEnable(GL_TEXTURE_RECTANGLE_ARB);
97 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
98 glBegin(GL_QUADS);
99 glTexCoord2f(0, 0);
100 glVertex2f(0, 0);
101 glTexCoord2f(pixel_size_.width(), 0);
102 glVertex2f(pixel_size_.width(), 0);
103 glTexCoord2f(pixel_size_.width(), pixel_size_.height());
104 glVertex2f(pixel_size_.width(), pixel_size_.height());
105 glTexCoord2f(0, pixel_size_.height());
106 glVertex2f(0, pixel_size_.height());
107 glEnd();
108 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
109 glDisable(GL_TEXTURE_RECTANGLE_ARB);
134 110
135 glColor4f(1, 1, 1, 1); 111 // Workaround for issue 158469. Issue a dummy draw call with texture_ not
136 if (has_io_surface) { 112 // bound to a texture, in order to shake all references to the IOSurface out
137 glEnable(GL_TEXTURE_RECTANGLE_ARB); 113 // of the driver.
138 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 114 glBegin(GL_TRIANGLES);
139 DrawQuad(quad); 115 glEnd();
140 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
141 glDisable(GL_TEXTURE_RECTANGLE_ARB);
142 CHECK_AND_SAVE_GL_ERROR();
143
144 // Fill the resize gutters with white.
145 if (window_rect.width() > dip_io_surface_size_.width() ||
146 window_rect.height() > dip_io_surface_size_.height()) {
147 SurfaceQuad filler_quad;
148 if (window_rect.width() > dip_io_surface_size_.width()) {
149 // Draw right-side gutter down to the bottom of the window.
150 filler_quad.set_rect(dip_io_surface_size_.width(), 0.0f,
151 window_rect.width(), window_rect.height());
152 DrawQuad(filler_quad);
153 }
154 if (window_rect.height() > dip_io_surface_size_.height()) {
155 // Draw bottom gutter to the width of the IOSurfaceTexture.
156 filler_quad.set_rect(
157 0.0f, dip_io_surface_size_.height(),
158 dip_io_surface_size_.width(), window_rect.height());
159 DrawQuad(filler_quad);
160 }
161 }
162
163 // Workaround for issue 158469. Issue a dummy draw call with texture_ not
164 // bound to a texture, in order to shake all references to the IOSurface out
165 // of the driver.
166 glBegin(GL_TRIANGLES);
167 glEnd();
168 CHECK_AND_SAVE_GL_ERROR();
169 } else {
170 // Should match the clear color of RenderWidgetHostViewMac.
171 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
172 glClear(GL_COLOR_BUFFER_BIT);
173 }
174 116
175 bool workaround_needed = 117 bool workaround_needed =
176 GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive( 118 GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
177 gpu::FORCE_GL_FINISH_AFTER_COMPOSITING); 119 gpu::FORCE_GL_FINISH_AFTER_COMPOSITING);
178 if (workaround_needed) { 120 if (workaround_needed) {
179 TRACE_EVENT0("gpu", "glFinish"); 121 TRACE_EVENT0("gpu", "glFinish");
180 glFinish(); 122 glFinish();
181 } 123 }
182 124
183 // Check if any of the drawing calls result in an error. 125 // Check if any of the drawing calls result in an error.
184 GetAndSaveGLError(); 126 GetAndSaveGLError();
185 bool result = true; 127 bool result = true;
186 if (gl_error_ != GL_NO_ERROR) { 128 if (gl_error_ != GL_NO_ERROR) {
187 LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_; 129 LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_;
188 result = false; 130 result = false;
189 // If there was an error, clear the screen to a light grey to avoid 131 // If there was an error, clear the screen to a light grey to avoid
190 // rendering artifacts. If we're in a really bad way, this too may 132 // rendering artifacts.
191 // generate an error. Clear the GL error afterwards just in case.
192 glClearColor(0.8, 0.8, 0.8, 1.0); 133 glClearColor(0.8, 0.8, 0.8, 1.0);
193 glClear(GL_COLOR_BUFFER_BIT); 134 glClear(GL_COLOR_BUFFER_BIT);
194 glGetError();
195 } 135 }
196 136
197 eviction_has_been_drawn_since_updated_ = true; 137 eviction_has_been_drawn_since_updated_ = true;
198 return result; 138 return result;
199 } 139 }
200 140
201 bool IOSurfaceTexture::MapIOSurfaceToTextureWithContextCurrent( 141 bool IOSurfaceTexture::SetIOSurface(
202 const scoped_refptr<IOSurfaceContext>& current_context, 142 scoped_refptr<IOSurfaceContext> context,
203 const gfx::Size pixel_size, 143 IOSurfaceID io_surface_id,
204 float scale_factor, 144 const gfx::Size& pixel_size) {
205 IOSurfaceID io_surface_handle) {
206 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture"); 145 TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture");
207 146
208 if (!io_surface_ || io_surface_handle != io_surface_handle_) 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.
151 bool needs_new_iosurface =
152 !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_);
153 if (needs_new_iosurface)
209 UnrefIOSurfaceWithContextCurrent(); 154 UnrefIOSurfaceWithContextCurrent();
210 155
211 pixel_io_surface_size_ = pixel_size; 156 // Note that because IOSurface sizes are rounded, the same IOSurface may have
212 scale_factor_ = scale_factor; 157 // two different sizes associated with it, so update the sizes before the
213 dip_io_surface_size_ = gfx::ToFlooredSize( 158 // early-out.
214 gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_)); 159 pixel_size_ = pixel_size;
215 160
216 // Early-out if the IOSurface has not changed. Note that because IOSurface 161 // Early-out if the IOSurface has not changed.
217 // sizes are rounded, the same IOSurface may have two different sizes 162 if (!needs_new_iosurface)
218 // associated with it.
219 if (io_surface_ && io_surface_handle == io_surface_handle_)
220 return true; 163 return true;
221 164
222 io_surface_.reset(IOSurfaceLookup(io_surface_handle)); 165 // Open the IOSurface handle.
223 // Can fail if IOSurface with that ID was already released by the gpu 166 io_surface_.reset(IOSurfaceLookup(io_surface_id));
224 // process.
225 if (!io_surface_) { 167 if (!io_surface_) {
226 UnrefIOSurfaceWithContextCurrent(); 168 UnrefIOSurfaceWithContextCurrent();
227 return false; 169 return false;
228 } 170 }
229 171
230 io_surface_handle_ = io_surface_handle;
231
232 // Actual IOSurface size is rounded up to reduce reallocations during window 172 // Actual IOSurface size is rounded up to reduce reallocations during window
233 // resize. Get the actual size to properly map the texture. 173 // resize. Get the actual size to properly map the texture.
234 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_), 174 gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
235 IOSurfaceGetHeight(io_surface_)); 175 IOSurfaceGetHeight(io_surface_));
236 176
177 // Create the GL texture and set it to be backed by the IOSurface.
237 glGenTextures(1, &texture_); 178 glGenTextures(1, &texture_);
238 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 179 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
239 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 180 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
240 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 181 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
241 CHECK_AND_SAVE_GL_ERROR();
242 GLuint plane = 0; 182 GLuint plane = 0;
243 CGLError cgl_error = CGLTexImageIOSurface2D( 183 CGLError cgl_error = CGLTexImageIOSurface2D(
244 current_context->cgl_context(), 184 context->cgl_context(),
245 GL_TEXTURE_RECTANGLE_ARB, 185 GL_TEXTURE_RECTANGLE_ARB,
246 GL_RGBA, 186 GL_RGBA,
247 rounded_size.width(), 187 rounded_size.width(),
248 rounded_size.height(), 188 rounded_size.height(),
249 GL_BGRA, 189 GL_BGRA,
250 GL_UNSIGNED_INT_8_8_8_8_REV, 190 GL_UNSIGNED_INT_8_8_8_8_REV,
251 io_surface_.get(), 191 io_surface_.get(),
252 plane); 192 plane);
253 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); 193 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
194 GetAndSaveGLError();
195
196 // Return failure if an error was encountered by CGL or GL.
254 if (cgl_error != kCGLNoError) { 197 if (cgl_error != kCGLNoError) {
255 LOG(ERROR) << "CGLTexImageIOSurface2D: " << cgl_error; 198 LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error;
256 UnrefIOSurfaceWithContextCurrent(); 199 UnrefIOSurfaceWithContextCurrent();
257 return false; 200 return false;
258 } 201 }
259 GetAndSaveGLError();
260 if (gl_error_ != GL_NO_ERROR) { 202 if (gl_error_ != GL_NO_ERROR) {
261 LOG(ERROR) << "GL error in MapIOSurfaceToTexture: " << gl_error_; 203 LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_;
262 UnrefIOSurfaceWithContextCurrent(); 204 UnrefIOSurfaceWithContextCurrent();
263 return false; 205 return false;
264 } 206 }
207
265 return true; 208 return true;
266 } 209 }
267 210
268 void IOSurfaceTexture::UnrefIOSurface() { 211 void IOSurfaceTexture::UnrefIOSurface() {
269 gfx::ScopedCGLSetCurrentContext scoped_set_current_context( 212 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
270 offscreen_context_->cgl_context()); 213 offscreen_context_->cgl_context());
271 UnrefIOSurfaceWithContextCurrent(); 214 UnrefIOSurfaceWithContextCurrent();
272 } 215 }
273 216
274 void IOSurfaceTexture::DrawQuad(const SurfaceQuad& quad) {
275 TRACE_EVENT0("gpu", "IOSurfaceTexture::DrawQuad");
276
277 glEnableClientState(GL_VERTEX_ARRAY); CHECK_AND_SAVE_GL_ERROR();
278 glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_AND_SAVE_GL_ERROR();
279
280 glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].x_);
281 glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].tx_);
282 glDrawArrays(GL_QUADS, 0, 4); CHECK_AND_SAVE_GL_ERROR();
283
284 glDisableClientState(GL_VERTEX_ARRAY);
285 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
286 }
287
288 void IOSurfaceTexture::UnrefIOSurfaceWithContextCurrent() { 217 void IOSurfaceTexture::UnrefIOSurfaceWithContextCurrent() {
289 if (texture_) { 218 if (texture_) {
290 glDeleteTextures(1, &texture_); 219 glDeleteTextures(1, &texture_);
291 texture_ = 0; 220 texture_ = 0;
292 } 221 }
293 pixel_io_surface_size_ = gfx::Size(); 222 pixel_size_ = gfx::Size();
294 scale_factor_ = 1;
295 dip_io_surface_size_ = gfx::Size();
296 io_surface_.reset(); 223 io_surface_.reset();
297 224
298 // Forget the ID, because even if it is still around when we want to use it
299 // again, OSX may have reused the same ID for a new tab and we don't want to
300 // blit random tab contents.
301 io_surface_handle_ = 0;
302
303 EvictionMarkEvicted(); 225 EvictionMarkEvicted();
304 } 226 }
305 227
306 bool IOSurfaceTexture::HasBeenPoisoned() const { 228 bool IOSurfaceTexture::HasBeenPoisoned() const {
307 return offscreen_context_->HasBeenPoisoned(); 229 return offscreen_context_->HasBeenPoisoned();
308 } 230 }
309 231
310 GLenum IOSurfaceTexture::GetAndSaveGLError() { 232 GLenum IOSurfaceTexture::GetAndSaveGLError() {
311 GLenum gl_error = glGetError(); 233 GLenum gl_error = glGetError();
312 if (gl_error_ == GL_NO_ERROR) 234 if (gl_error_ == GL_NO_ERROR)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 290 }
369 291
370 // static 292 // static
371 base::LazyInstance<IOSurfaceTexture::EvictionQueue> 293 base::LazyInstance<IOSurfaceTexture::EvictionQueue>
372 IOSurfaceTexture::eviction_queue_; 294 IOSurfaceTexture::eviction_queue_;
373 295
374 // static 296 // static
375 bool IOSurfaceTexture::eviction_scheduled_ = false; 297 bool IOSurfaceTexture::eviction_scheduled_ = false;
376 298
377 } // namespace content 299 } // 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