| 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 // Creates a new OpenGL texture object bound to the given texture target. |
| 150 // Caller owns the returned texture. |
| 151 static GLuint CreateTexture(GLenum target) { |
| 152 GLuint texture = 0; |
| 153 glGenTextures(1, &texture); |
| 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 return texture; |
| 160 } |
| 161 |
| 149 void AcceleratedSurface::AllocateRenderBuffers(GLenum target, | 162 void AcceleratedSurface::AllocateRenderBuffers(GLenum target, |
| 150 const gfx::Size& size) { | 163 const gfx::Size& size) { |
| 151 if (!texture_) { | 164 if (!texture_) { |
| 152 // Generate the texture object. | 165 // Generate the texture object. |
| 153 glGenTextures(1, &texture_); | 166 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. | 167 // Generate and bind the framebuffer object. |
| 160 glGenFramebuffersEXT(1, &fbo_); | 168 glGenFramebuffersEXT(1, &fbo_); |
| 161 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); | 169 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_); |
| 162 // Generate (but don't bind) the depth buffer -- we don't need | 170 // Generate (but don't bind) the depth buffer -- we don't need |
| 163 // this bound in order to do offscreen rendering. | 171 // this bound in order to do offscreen rendering. |
| 164 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_); | 172 glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_); |
| 165 } | 173 } |
| 166 | 174 |
| 167 // Reallocate the depth buffer. | 175 // Reallocate the depth buffer. |
| 168 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_); | 176 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) { | 226 void AcceleratedSurface::Clear(const gfx::Rect& rect) { |
| 219 DCHECK(gl_context_->IsCurrent(gl_surface_.get())); | 227 DCHECK(gl_context_->IsCurrent(gl_surface_.get())); |
| 220 glClearColor(0, 0, 0, 0); | 228 glClearColor(0, 0, 0, 0); |
| 221 glViewport(0, 0, rect.width(), rect.height()); | 229 glViewport(0, 0, rect.width(), rect.height()); |
| 222 glMatrixMode(GL_PROJECTION); | 230 glMatrixMode(GL_PROJECTION); |
| 223 glLoadIdentity(); | 231 glLoadIdentity(); |
| 224 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); | 232 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); |
| 225 glClear(GL_COLOR_BUFFER_BIT); | 233 glClear(GL_COLOR_BUFFER_BIT); |
| 226 } | 234 } |
| 227 | 235 |
| 228 uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { | 236 uint32 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { |
| 229 if (surface_size_ == size) { | 237 if (surface_size_ == size) { |
| 230 // Return 0 to indicate to the caller that no new backing store | 238 // Return 0 to indicate to the caller that no new backing store |
| 231 // allocation occurred. | 239 // allocation occurred. |
| 232 return 0; | 240 return 0; |
| 233 } | 241 } |
| 234 | 242 |
| 235 // Only support IO surfaces if the GL implementation is the native desktop GL. | 243 // 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 | 244 // IO surfaces will not work with, for example, OSMesa software renderer |
| 237 // GL contexts. | 245 // GL contexts. |
| 238 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) | 246 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) |
| 239 return 0; | 247 return 0; |
| 240 | 248 |
| 241 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 249 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
| 242 if (!io_surface_support) | 250 if (!io_surface_support) |
| 243 return 0; // Caller can try using SetWindowSizeForTransportDIB(). | 251 return 0; // Caller can try using SetWindowSizeForTransportDIB(). |
| 244 | 252 |
| 245 gfx::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get()); | 253 gfx::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get()); |
| 246 if (!make_current.Succeeded()) | 254 if (!make_current.Succeeded()) |
| 247 return 0; | 255 return 0; |
| 248 | 256 |
| 249 gfx::Size clamped_size = ClampToValidDimensions(size); | 257 gfx::Size clamped_size = ClampToValidDimensions(size); |
| 250 | 258 |
| 251 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on | 259 // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on |
| 252 // Mac OS X and is required for IOSurface interoperability. | 260 // Mac OS X and is required for IOSurface interoperability. |
| 253 GLenum target = GL_TEXTURE_RECTANGLE_ARB; | 261 GLenum target = GL_TEXTURE_RECTANGLE_ARB; |
| 254 if (allocate_fbo_) { | 262 if (allocate_fbo_) { |
| 255 AllocateRenderBuffers(target, clamped_size); | 263 AllocateRenderBuffers(target, clamped_size); |
| 256 } else if (!texture_) { | 264 } else if (!texture_) { |
| 257 // Generate the texture object. | 265 // Generate the texture object. |
| 258 glGenTextures(1, &texture_); | 266 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 } | 267 } |
| 265 | 268 |
| 266 // Allocate a new IOSurface, which is the GPU resource that can be | 269 // Allocate a new IOSurface, which is the GPU resource that can be |
| 267 // shared across processes. | 270 // shared across processes. |
| 268 base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> properties; | 271 base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> properties; |
| 269 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, | 272 properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault, |
| 270 0, | 273 0, |
| 271 &kCFTypeDictionaryKeyCallBacks, | 274 &kCFTypeDictionaryKeyCallBacks, |
| 272 &kCFTypeDictionaryValueCallBacks)); | 275 &kCFTypeDictionaryValueCallBacks)); |
| 273 AddIntegerValue(properties, | 276 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 | 311 // intended to send back a mach port from IOSurfaceCreateMachPort |
| 309 // but it looks like Chrome IPC would need to be modified to | 312 // but it looks like Chrome IPC would need to be modified to |
| 310 // properly send mach ports between processes. For the time being we | 313 // properly send mach ports between processes. For the time being we |
| 311 // make our IOSurfaces global and send back their identifiers. On | 314 // make our IOSurfaces global and send back their identifiers. On |
| 312 // the browser process side the identifier is reconstituted into an | 315 // the browser process side the identifier is reconstituted into an |
| 313 // IOSurface for on-screen rendering. | 316 // IOSurface for on-screen rendering. |
| 314 io_surface_id_ = io_surface_support->IOSurfaceGetID(io_surface_); | 317 io_surface_id_ = io_surface_support->IOSurfaceGetID(io_surface_); |
| 315 return io_surface_id_; | 318 return io_surface_id_; |
| 316 } | 319 } |
| 317 | 320 |
| 318 uint64 AcceleratedSurface::GetSurfaceId() { | 321 uint32 AcceleratedSurface::GetSurfaceId() { |
| 319 return io_surface_id_; | 322 return io_surface_id_; |
| 320 } | 323 } |
| 321 | 324 |
| 322 TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize( | 325 TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize( |
| 323 const gfx::Size& size) { | 326 const gfx::Size& size) { |
| 324 if (surface_size_ == size) { | 327 if (surface_size_ == size) { |
| 325 // Return an invalid handle to indicate to the caller that no new backing | 328 // Return an invalid handle to indicate to the caller that no new backing |
| 326 // store allocation occurred. | 329 // store allocation occurred. |
| 327 return TransportDIB::DefaultHandleValue(); | 330 return TransportDIB::DefaultHandleValue(); |
| 328 } | 331 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 } | 377 } |
| 375 return transport_dib_->handle(); | 378 return transport_dib_->handle(); |
| 376 } | 379 } |
| 377 | 380 |
| 378 void AcceleratedSurface::SetTransportDIBAllocAndFree( | 381 void AcceleratedSurface::SetTransportDIBAllocAndFree( |
| 379 const base::Callback<void(size_t, TransportDIB::Handle*)>& allocator, | 382 const base::Callback<void(size_t, TransportDIB::Handle*)>& allocator, |
| 380 const base::Callback<void(TransportDIB::Id)>& deallocator) { | 383 const base::Callback<void(TransportDIB::Id)>& deallocator) { |
| 381 dib_alloc_callback_ = allocator; | 384 dib_alloc_callback_ = allocator; |
| 382 dib_free_callback_ = deallocator; | 385 dib_free_callback_ = deallocator; |
| 383 } | 386 } |
| OLD | NEW |