Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "ui/gfx/surface/accelerated_surface_mac.h" | 5 #include "ui/gfx/surface/accelerated_surface_mac.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/mac/scoped_cftyperef.h" | 8 #include "base/mac/scoped_cftyperef.h" |
| 9 #include "ui/gfx/gl/gl_bindings.h" | 9 #include "ui/gfx/gl/gl_bindings.h" |
| 10 #include "ui/gfx/gl/gl_context.h" | 10 #include "ui/gfx/gl/gl_context.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 gl_surface_ = NULL; | 80 gl_surface_ = NULL; |
| 81 } | 81 } |
| 82 | 82 |
| 83 // Call after making changes to the surface which require a visual update. | 83 // Call after making changes to the surface which require a visual update. |
| 84 // Makes the rendering show up in other processes. | 84 // Makes the rendering show up in other processes. |
| 85 void AcceleratedSurface::SwapBuffers() { | 85 void AcceleratedSurface::SwapBuffers() { |
| 86 if (io_surface_.get() != NULL) { | 86 if (io_surface_.get() != NULL) { |
| 87 if (allocate_fbo_) { | 87 if (allocate_fbo_) { |
| 88 // Bind and unbind the framebuffer to make changes to the | 88 // Bind and unbind the framebuffer to make changes to the |
| 89 // IOSurface show up in the other process. | 89 // IOSurface show up in the other process. |
| 90 glFlush(); | |
| 91 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); | 90 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); |
| 92 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | 91 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| 92 glFlush(); | |
| 93 } else { | 93 } else { |
| 94 // Copy the current framebuffer's contents into our "live" texture. | 94 // Copy the current framebuffer's contents into our "live" texture. |
| 95 // Note that the current GL context might not be ours at this point! | 95 // Note that the current GL context might not be ours at this point! |
| 96 // This is deliberate, so that surrounding code using GL can produce | 96 // This is deliberate, so that surrounding code using GL can produce |
| 97 // rendering results consumed by the AcceleratedSurface. | 97 // rendering results consumed by the AcceleratedSurface. |
| 98 // Need to save and restore OpenGL state around this call. | 98 // Need to save and restore OpenGL state around this call. |
| 99 GLint current_texture = 0; | 99 GLint current_texture = 0; |
| 100 GLenum target_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB; | 100 GLenum target_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB; |
| 101 GLenum target = GL_TEXTURE_RECTANGLE_ARB; | 101 GLenum target = GL_TEXTURE_RECTANGLE_ARB; |
| 102 glGetIntegerv(target_binding, ¤t_texture); | 102 glGetIntegerv(target_binding, ¤t_texture); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 } | 139 } |
| 140 | 140 |
| 141 static void AddIntegerValue(CFMutableDictionaryRef dictionary, | 141 static void AddIntegerValue(CFMutableDictionaryRef dictionary, |
| 142 const CFStringRef key, | 142 const CFStringRef key, |
| 143 int32 value) { | 143 int32 value) { |
| 144 base::mac::ScopedCFTypeRef<CFNumberRef> number( | 144 base::mac::ScopedCFTypeRef<CFNumberRef> number( |
| 145 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); | 145 CFNumberCreate(NULL, kCFNumberSInt32Type, &value)); |
| 146 CFDictionaryAddValue(dictionary, key, number.get()); | 146 CFDictionaryAddValue(dictionary, key, number.get()); |
| 147 } | 147 } |
| 148 | 148 |
| 149 static GLuint CreateTexture(GLenum target) { | |
|
stuartmorgan
2011/11/28 10:09:04
Needs a method-level comment (which should probabl
Ken Russell (switch to Gerrit)
2011/11/28 23:40:15
Done.
| |
| 150 GLuint texture = 0; | |
| 151 glGenTextures(1, &texture); | |
| 152 glBindTexture(target, texture); | |
| 153 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 154 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 155 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 156 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 157 return texture; | |
| 158 } | |
| 159 | |
| 149 void AcceleratedSurface::AllocateRenderBuffers(GLenum target, | 160 void AcceleratedSurface::AllocateRenderBuffers(GLenum target, |
| 150 const gfx::Size& size) { | 161 const gfx::Size& size) { |
| 151 if (!texture_) { | 162 if (!texture_) { |
| 152 // Generate the texture object. | 163 // Generate the texture object. |
| 153 glGenTextures(1, &texture_); | 164 texture_ = CreateTexture(target); |
| 154 glBindTexture(target, texture_); | |
| 155 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 156 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 157 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 158 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 159 // Generate and bind the framebuffer object. | 165 // Generate and bind the framebuffer object. |
| 160 glGenFramebuffersEXT(1, &fbo_); | 166 glGenFramebuffersEXT(1, &fbo_); |
| 161 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | 167 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| 162 // Generate (but don't bind) the depth buffer -- we don't need | 168 // Generate (but don't bind) the depth buffer -- we don't need |
| 163 // this bound in order to do offscreen rendering. | 169 // this bound in order to do offscreen rendering. |
| 164 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_); | 170 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_); |
| 165 } | 171 } |
| 166 | 172 |
| 167 // Reallocate the depth buffer. | 173 // Reallocate the depth buffer. |
| 168 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_); | 174 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 void AcceleratedSurface::Clear(const gfx::Rect& rect) { | 224 void AcceleratedSurface::Clear(const gfx::Rect& rect) { |
| 219 DCHECK(gl_context_->IsCurrent(gl_surface_.get())); | 225 DCHECK(gl_context_->IsCurrent(gl_surface_.get())); |
| 220 glClearColor(0, 0, 0, 0); | 226 glClearColor(0, 0, 0, 0); |
| 221 glViewport(0, 0, rect.width(), rect.height()); | 227 glViewport(0, 0, rect.width(), rect.height()); |
| 222 glMatrixMode(GL_PROJECTION); | 228 glMatrixMode(GL_PROJECTION); |
| 223 glLoadIdentity(); | 229 glLoadIdentity(); |
| 224 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); | 230 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); |
| 225 glClear(GL_COLOR_BUFFER_BIT); | 231 glClear(GL_COLOR_BUFFER_BIT); |
| 226 } | 232 } |
| 227 | 233 |
| 228 uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { | 234 uint32 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { |
| 229 if (surface_size_ == size) { | 235 if (surface_size_ == size) { |
| 230 // Return 0 to indicate to the caller that no new backing store | 236 // Return 0 to indicate to the caller that no new backing store |
| 231 // allocation occurred. | 237 // allocation occurred. |
| 232 return 0; | 238 return 0; |
| 233 } | 239 } |
| 234 | 240 |
| 235 // Only support IO surfaces if the GL implementation is the native desktop GL. | 241 // Only support IO surfaces if the GL implementation is the native desktop GL. |
| 236 // IO surfaces will not work with, for example, OSMesa software renderer | 242 // IO surfaces will not work with, for example, OSMesa software renderer |
| 237 // GL contexts. | 243 // GL contexts. |
| 238 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) | 244 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) |
| 239 return 0; | 245 return 0; |
| 240 | 246 |
| 241 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 247 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
| 242 if (!io_surface_support) | 248 if (!io_surface_support) |
| 243 return 0; // Caller can try using SetWindowSizeForTransportDIB(). | 249 return 0; // Caller can try using SetWindowSizeForTransportDIB(). |
| 244 | 250 |
| 245 gfx::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get()); | 251 gfx::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get()); |
| 246 if (!make_current.Succeeded()) | 252 if (!make_current.Succeeded()) |
| 247 return 0; | 253 return 0; |
| 248 | 254 |
| 249 gfx::Size clamped_size = ClampToValidDimensions(size); | 255 gfx::Size clamped_size = ClampToValidDimensions(size); |
| 250 | 256 |
| 251 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on | 257 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on |
| 252 // Mac OS X and is required for IOSurface interoperability. | 258 // Mac OS X and is required for IOSurface interoperability. |
| 253 GLenum target = GL_TEXTURE_RECTANGLE_ARB; | 259 GLenum target = GL_TEXTURE_RECTANGLE_ARB; |
| 254 if (allocate_fbo_) { | 260 if (allocate_fbo_) { |
| 255 AllocateRenderBuffers(target, clamped_size); | 261 AllocateRenderBuffers(target, clamped_size); |
| 256 } else if (!texture_) { | 262 } else if (!texture_) { |
| 257 // Generate the texture object. | 263 // Generate the texture object. |
| 258 glGenTextures(1, &texture_); | 264 texture_ = CreateTexture(target); |
| 259 glBindTexture(target, texture_); | |
| 260 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | |
| 261 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
| 262 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
| 263 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
| 264 } | 265 } |
| 265 | 266 |
| 266 // Allocate a new IOSurface, which is the GPU resource that can be | 267 // Allocate a new IOSurface, which is the GPU resource that can be |
| 267 // shared across processes. | 268 // shared across processes. |
| 268 base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> properties; | 269 base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> properties; |
| 269 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, | 270 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, |
| 270 0, | 271 0, |
| 271 &kCFTypeDictionaryKeyCallBacks, | 272 &kCFTypeDictionaryKeyCallBacks, |
| 272 &kCFTypeDictionaryValueCallBacks)); | 273 &kCFTypeDictionaryValueCallBacks)); |
| 273 AddIntegerValue(properties, | 274 AddIntegerValue(properties, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 // intended to send back a mach port from IOSurfaceCreateMachPort | 309 // intended to send back a mach port from IOSurfaceCreateMachPort |
| 309 // but it looks like Chrome IPC would need to be modified to | 310 // but it looks like Chrome IPC would need to be modified to |
| 310 // properly send mach ports between processes. For the time being we | 311 // properly send mach ports between processes. For the time being we |
| 311 // make our IOSurfaces global and send back their identifiers. On | 312 // make our IOSurfaces global and send back their identifiers. On |
| 312 // the browser process side the identifier is reconstituted into an | 313 // the browser process side the identifier is reconstituted into an |
| 313 // IOSurface for on-screen rendering. | 314 // IOSurface for on-screen rendering. |
| 314 io_surface_id_ = io_surface_support->IOSurfaceGetID(io_surface_); | 315 io_surface_id_ = io_surface_support->IOSurfaceGetID(io_surface_); |
| 315 return io_surface_id_; | 316 return io_surface_id_; |
| 316 } | 317 } |
| 317 | 318 |
| 318 uint64 AcceleratedSurface::GetSurfaceId() { | 319 uint32 AcceleratedSurface::GetSurfaceId() { |
| 319 return io_surface_id_; | 320 return io_surface_id_; |
| 320 } | 321 } |
| 321 | 322 |
| 322 TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize( | 323 TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize( |
| 323 const gfx::Size& size) { | 324 const gfx::Size& size) { |
| 324 if (surface_size_ == size) { | 325 if (surface_size_ == size) { |
| 325 // Return an invalid handle to indicate to the caller that no new backing | 326 // Return an invalid handle to indicate to the caller that no new backing |
| 326 // store allocation occurred. | 327 // store allocation occurred. |
| 327 return TransportDIB::DefaultHandleValue(); | 328 return TransportDIB::DefaultHandleValue(); |
| 328 } | 329 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 } | 375 } |
| 375 return transport_dib_->handle(); | 376 return transport_dib_->handle(); |
| 376 } | 377 } |
| 377 | 378 |
| 378 void AcceleratedSurface::SetTransportDIBAllocAndFree( | 379 void AcceleratedSurface::SetTransportDIBAllocAndFree( |
| 379 const base::Callback<void(size_t, TransportDIB::Handle*)>& allocator, | 380 const base::Callback<void(size_t, TransportDIB::Handle*)>& allocator, |
| 380 const base::Callback<void(TransportDIB::Id)>& deallocator) { | 381 const base::Callback<void(TransportDIB::Id)>& deallocator) { |
| 381 dib_alloc_callback_ = allocator; | 382 dib_alloc_callback_ = allocator; |
| 382 dib_free_callback_ = deallocator; | 383 dib_free_callback_ = deallocator; |
| 383 } | 384 } |
| OLD | NEW |