OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "app/surface/accelerated_surface_mac.h" | 5 #include "app/surface/accelerated_surface_mac.h" |
6 | 6 |
7 #include "app/gfx/gl/gl_bindings.h" | 7 #include "app/gfx/gl/gl_bindings.h" |
8 #include "app/surface/io_surface_support_mac.h" | 8 #include "app/surface/io_surface_support_mac.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "gfx/rect.h" | 10 #include "gfx/rect.h" |
11 | 11 |
12 AcceleratedSurface::AcceleratedSurface() | 12 AcceleratedSurface::AcceleratedSurface() |
13 : gl_context_(NULL), | 13 : allocate_fbo_(false), |
14 pbuffer_(NULL), | |
15 allocate_fbo_(false), | |
16 texture_(0), | 14 texture_(0), |
17 fbo_(0), | 15 fbo_(0), |
18 depth_stencil_renderbuffer_(0) { | 16 depth_stencil_renderbuffer_(0) { |
19 } | 17 } |
20 | 18 |
21 bool AcceleratedSurface::Initialize(CGLContextObj share_context, | 19 bool AcceleratedSurface::Initialize(gfx::GLContext* share_context, |
22 bool allocate_fbo) { | 20 bool allocate_fbo) { |
23 allocate_fbo_ = allocate_fbo; | 21 allocate_fbo_ = allocate_fbo; |
24 | 22 |
25 // TODO(kbr): we should reuse the code for PbufferGLContext here instead | 23 gl_context_.reset(gfx::GLContext::CreateOffscreenGLContext(share_context)); |
26 // of duplicating it. However, in order to do so, we need to move the | 24 if (!gl_context_.get()) |
27 // GLContext classes out of gpu/ and into gfx/. | 25 return false; |
28 | 26 |
29 // Create a 1x1 pbuffer and associated context to bootstrap things | 27 // Now we're ready to handle SetSurfaceSize calls, which will |
30 static const CGLPixelFormatAttribute attribs[] = { | |
31 (CGLPixelFormatAttribute) kCGLPFAPBuffer, | |
32 (CGLPixelFormatAttribute) 0 | |
33 }; | |
34 CGLPixelFormatObj pixel_format; | |
35 GLint num_pixel_formats; | |
36 if (CGLChoosePixelFormat(attribs, | |
37 &pixel_format, | |
38 &num_pixel_formats) != kCGLNoError) { | |
39 DLOG(ERROR) << "Error choosing pixel format."; | |
40 return false; | |
41 } | |
42 if (!pixel_format) { | |
43 return false; | |
44 } | |
45 CGLContextObj context; | |
46 CGLError res = CGLCreateContext(pixel_format, share_context, &context); | |
47 CGLDestroyPixelFormat(pixel_format); | |
48 if (res != kCGLNoError) { | |
49 DLOG(ERROR) << "Error creating context."; | |
50 return false; | |
51 } | |
52 CGLPBufferObj pbuffer; | |
53 if (CGLCreatePBuffer(1, 1, | |
54 GL_TEXTURE_2D, GL_RGBA, | |
55 0, &pbuffer) != kCGLNoError) { | |
56 CGLDestroyContext(context); | |
57 DLOG(ERROR) << "Error creating pbuffer."; | |
58 return false; | |
59 } | |
60 if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) { | |
61 CGLDestroyContext(context); | |
62 CGLDestroyPBuffer(pbuffer); | |
63 DLOG(ERROR) << "Error attaching pbuffer to context."; | |
64 return false; | |
65 } | |
66 gl_context_ = context; | |
67 pbuffer_ = pbuffer; | |
68 // Now we're ready to handle SetWindowSize calls, which will | |
69 // allocate and/or reallocate the IOSurface and associated offscreen | 28 // allocate and/or reallocate the IOSurface and associated offscreen |
70 // OpenGL structures for rendering. | 29 // OpenGL structures for rendering. |
71 return true; | 30 return true; |
72 } | 31 } |
73 | 32 |
74 void AcceleratedSurface::Destroy() { | 33 void AcceleratedSurface::Destroy() { |
75 // The FBO and texture objects will be destroyed when the OpenGL context, | 34 // The FBO and texture objects will be destroyed when the OpenGL context, |
76 // and any other contexts sharing resources with it, is. We don't want to | 35 // and any other contexts sharing resources with it, is. We don't want to |
77 // make the context current one last time here just in order to delete | 36 // make the context current one last time here just in order to delete |
78 // these objects. | 37 // these objects. |
79 | 38 |
80 // Release the old TransportDIB in the browser. | 39 // Release the old TransportDIB in the browser. |
81 if (dib_free_callback_.get() && transport_dib_.get()) { | 40 if (dib_free_callback_.get() && transport_dib_.get()) { |
82 dib_free_callback_->Run(transport_dib_->id()); | 41 dib_free_callback_->Run(transport_dib_->id()); |
83 } | 42 } |
84 transport_dib_.reset(); | 43 transport_dib_.reset(); |
85 if (gl_context_) | 44 |
86 CGLDestroyContext(gl_context_); | 45 if (gl_context_.get()) |
87 if (pbuffer_) | 46 gl_context_->Destroy(); |
88 CGLDestroyPBuffer(pbuffer_); | 47 gl_context_.reset(); |
89 } | 48 } |
90 | 49 |
91 // Call after making changes to the surface which require a visual update. | 50 // Call after making changes to the surface which require a visual update. |
92 // Makes the rendering show up in other processes. | 51 // Makes the rendering show up in other processes. |
93 void AcceleratedSurface::SwapBuffers() { | 52 void AcceleratedSurface::SwapBuffers() { |
94 if (io_surface_.get() != NULL) { | 53 if (io_surface_.get() != NULL) { |
95 if (allocate_fbo_) { | 54 if (allocate_fbo_) { |
96 // Bind and unbind the framebuffer to make changes to the | 55 // Bind and unbind the framebuffer to make changes to the |
97 // IOSurface show up in the other process. | 56 // IOSurface show up in the other process. |
98 glFlush(); | 57 glFlush(); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) { | 150 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) { |
192 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | 151 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
193 GL_DEPTH_ATTACHMENT_EXT, | 152 GL_DEPTH_ATTACHMENT_EXT, |
194 GL_RENDERBUFFER_EXT, | 153 GL_RENDERBUFFER_EXT, |
195 depth_stencil_renderbuffer_); | 154 depth_stencil_renderbuffer_); |
196 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | 155 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
197 } | 156 } |
198 // Attach the depth and stencil buffer. | 157 // Attach the depth and stencil buffer. |
199 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) { | 158 if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) { |
200 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | 159 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, |
201 0x8D20, // GL_STENCIL_ATTACHMENT, | 160 0x8D20, // GL_STENCIL_ATTACHMENT, |
202 GL_RENDERBUFFER_EXT, | 161 GL_RENDERBUFFER_EXT, |
203 depth_stencil_renderbuffer_); | 162 depth_stencil_renderbuffer_); |
204 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | 163 fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
205 } | 164 } |
206 return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT; | 165 return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT; |
207 } | 166 } |
208 | 167 |
209 bool AcceleratedSurface::MakeCurrent() { | 168 bool AcceleratedSurface::MakeCurrent() { |
210 if (CGLGetCurrentContext() != gl_context_) { | 169 if (!gl_context_.get()) |
211 if (CGLSetCurrentContext(gl_context_) != kCGLNoError) { | 170 return false; |
212 DLOG(ERROR) << "Unable to make gl context current."; | 171 return gl_context_->MakeCurrent(); |
213 return false; | |
214 } | |
215 } | |
216 return true; | |
217 } | 172 } |
218 | 173 |
219 void AcceleratedSurface::Clear(const gfx::Rect& rect) { | 174 void AcceleratedSurface::Clear(const gfx::Rect& rect) { |
| 175 DCHECK(gl_context_->IsCurrent()); |
220 glClearColor(0, 0, 0, 0); | 176 glClearColor(0, 0, 0, 0); |
221 glViewport(0, 0, rect.width(), rect.height()); | 177 glViewport(0, 0, rect.width(), rect.height()); |
222 glMatrixMode(GL_PROJECTION); | 178 glMatrixMode(GL_PROJECTION); |
223 glLoadIdentity(); | 179 glLoadIdentity(); |
224 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); | 180 glOrtho(0, rect.width(), 0, rect.height(), -1, 1); |
225 glClear(GL_COLOR_BUFFER_BIT); | 181 glClear(GL_COLOR_BUFFER_BIT); |
226 } | 182 } |
227 | 183 |
228 uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { | 184 uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) { |
229 if (surface_size_ == size) { | 185 if (surface_size_ == size) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 io_surface_support->GetKIOSurfaceBytesPerElement(), 4); | 223 io_surface_support->GetKIOSurfaceBytesPerElement(), 4); |
268 AddBooleanValue(properties, | 224 AddBooleanValue(properties, |
269 io_surface_support->GetKIOSurfaceIsGlobal(), true); | 225 io_surface_support->GetKIOSurfaceIsGlobal(), true); |
270 // I believe we should be able to unreference the IOSurfaces without | 226 // I believe we should be able to unreference the IOSurfaces without |
271 // synchronizing with the browser process because they are | 227 // synchronizing with the browser process because they are |
272 // ultimately reference counted by the operating system. | 228 // ultimately reference counted by the operating system. |
273 io_surface_.reset(io_surface_support->IOSurfaceCreate(properties)); | 229 io_surface_.reset(io_surface_support->IOSurfaceCreate(properties)); |
274 | 230 |
275 // Don't think we need to identify a plane. | 231 // Don't think we need to identify a plane. |
276 GLuint plane = 0; | 232 GLuint plane = 0; |
277 io_surface_support->CGLTexImageIOSurface2D(gl_context_, | 233 io_surface_support->CGLTexImageIOSurface2D( |
278 target, | 234 static_cast<CGLContextObj>(gl_context_->GetHandle()), |
279 GL_RGBA, | 235 target, |
280 size.width(), | 236 GL_RGBA, |
281 size.height(), | 237 size.width(), |
282 GL_BGRA, | 238 size.height(), |
283 GL_UNSIGNED_INT_8_8_8_8_REV, | 239 GL_BGRA, |
284 io_surface_.get(), | 240 GL_UNSIGNED_INT_8_8_8_8_REV, |
285 plane); | 241 io_surface_.get(), |
| 242 plane); |
286 if (allocate_fbo_) { | 243 if (allocate_fbo_) { |
287 // Set up the frame buffer object. | 244 // Set up the frame buffer object. |
288 SetupFrameBufferObject(target); | 245 SetupFrameBufferObject(target); |
289 } | 246 } |
290 surface_size_ = size; | 247 surface_size_ = size; |
291 | 248 |
292 // Now send back an identifier for the IOSurface. We originally | 249 // Now send back an identifier for the IOSurface. We originally |
293 // intended to send back a mach port from IOSurfaceCreateMachPort | 250 // intended to send back a mach port from IOSurfaceCreateMachPort |
294 // but it looks like Chrome IPC would need to be modified to | 251 // but it looks like Chrome IPC would need to be modified to |
295 // properly send mach ports between processes. For the time being we | 252 // properly send mach ports between processes. For the time being we |
(...skipping 30 matching lines...) Expand all Loading... |
326 return TransportDIB::DefaultHandleValue(); | 283 return TransportDIB::DefaultHandleValue(); |
327 } | 284 } |
328 transport_dib_.reset(TransportDIB::Map(dib_handle)); | 285 transport_dib_.reset(TransportDIB::Map(dib_handle)); |
329 if (transport_dib_.get() == NULL) { | 286 if (transport_dib_.get() == NULL) { |
330 // TODO(dspringer): if the Map() fails, should the deallocator be run so | 287 // TODO(dspringer): if the Map() fails, should the deallocator be run so |
331 // that the DIB is deallocated in the browser? | 288 // that the DIB is deallocated in the browser? |
332 return TransportDIB::DefaultHandleValue(); | 289 return TransportDIB::DefaultHandleValue(); |
333 } | 290 } |
334 | 291 |
335 if (allocate_fbo_) { | 292 if (allocate_fbo_) { |
| 293 DCHECK(gl_context_->IsCurrent()); |
336 // Set up the render buffers and reserve enough space on the card for the | 294 // Set up the render buffers and reserve enough space on the card for the |
337 // framebuffer texture. | 295 // framebuffer texture. |
338 GLenum target = GL_TEXTURE_RECTANGLE_ARB; | 296 GLenum target = GL_TEXTURE_RECTANGLE_ARB; |
339 AllocateRenderBuffers(target, size); | 297 AllocateRenderBuffers(target, size); |
340 glTexImage2D(target, | 298 glTexImage2D(target, |
341 0, // mipmap level 0 | 299 0, // mipmap level 0 |
342 GL_RGBA8, // internal pixel format | 300 GL_RGBA8, // internal pixel format |
343 size.width(), | 301 size.width(), |
344 size.height(), | 302 size.height(), |
345 0, // 0 border | 303 0, // 0 border |
346 GL_BGRA, // Used for consistency | 304 GL_BGRA, // Used for consistency |
347 GL_UNSIGNED_INT_8_8_8_8_REV, | 305 GL_UNSIGNED_INT_8_8_8_8_REV, |
348 NULL); // No data, just reserve room on the card. | 306 NULL); // No data, just reserve room on the card. |
349 SetupFrameBufferObject(target); | 307 SetupFrameBufferObject(target); |
350 } | 308 } |
351 return transport_dib_->handle(); | 309 return transport_dib_->handle(); |
352 } | 310 } |
353 | 311 |
354 void AcceleratedSurface::SetTransportDIBAllocAndFree( | 312 void AcceleratedSurface::SetTransportDIBAllocAndFree( |
355 Callback2<size_t, TransportDIB::Handle*>::Type* allocator, | 313 Callback2<size_t, TransportDIB::Handle*>::Type* allocator, |
356 Callback1<TransportDIB::Id>::Type* deallocator) { | 314 Callback1<TransportDIB::Id>::Type* deallocator) { |
357 dib_alloc_callback_.reset(allocator); | 315 dib_alloc_callback_.reset(allocator); |
358 dib_free_callback_.reset(deallocator); | 316 dib_free_callback_.reset(deallocator); |
359 } | 317 } |
OLD | NEW |