summaryrefslogtreecommitdiffstats
path: root/chrome/common/accelerated_surface_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common/accelerated_surface_mac.cc')
-rw-r--r--chrome/common/accelerated_surface_mac.cc334
1 files changed, 0 insertions, 334 deletions
diff --git a/chrome/common/accelerated_surface_mac.cc b/chrome/common/accelerated_surface_mac.cc
deleted file mode 100644
index d12ecb6..0000000
--- a/chrome/common/accelerated_surface_mac.cc
+++ /dev/null
@@ -1,334 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/accelerated_surface_mac.h"
-
-#include "base/gfx/rect.h"
-#include "base/logging.h"
-#include "chrome/common/io_surface_support_mac.h"
-
-AcceleratedSurface::AcceleratedSurface()
- : gl_context_(NULL),
- pbuffer_(NULL),
- surface_width_(0),
- surface_height_(0),
- texture_(0),
- fbo_(0),
- depth_stencil_renderbuffer_(0),
- bound_fbo_(0),
- bound_renderbuffer_(0) {
-}
-
-bool AcceleratedSurface::Initialize() {
- // Create a 1x1 pbuffer and associated context to bootstrap things
- static const CGLPixelFormatAttribute attribs[] = {
- (CGLPixelFormatAttribute) kCGLPFAPBuffer,
- (CGLPixelFormatAttribute) 0
- };
- CGLPixelFormatObj pixel_format;
- GLint num_pixel_formats;
- if (CGLChoosePixelFormat(attribs,
- &pixel_format,
- &num_pixel_formats) != kCGLNoError) {
- DLOG(ERROR) << "Error choosing pixel format.";
- return false;
- }
- if (!pixel_format) {
- return false;
- }
- CGLContextObj context;
- CGLError res = CGLCreateContext(pixel_format, 0, &context);
- CGLDestroyPixelFormat(pixel_format);
- if (res != kCGLNoError) {
- DLOG(ERROR) << "Error creating context.";
- return false;
- }
- CGLPBufferObj pbuffer;
- if (CGLCreatePBuffer(1, 1,
- GL_TEXTURE_2D, GL_RGBA,
- 0, &pbuffer) != kCGLNoError) {
- CGLDestroyContext(context);
- DLOG(ERROR) << "Error creating pbuffer.";
- return false;
- }
- if (CGLSetPBuffer(context, pbuffer, 0, 0, 0) != kCGLNoError) {
- CGLDestroyContext(context);
- CGLDestroyPBuffer(pbuffer);
- DLOG(ERROR) << "Error attaching pbuffer to context.";
- return false;
- }
- gl_context_ = context;
- pbuffer_ = pbuffer;
- // Now we're ready to handle SetWindowSize calls, which will
- // allocate and/or reallocate the IOSurface and associated offscreen
- // OpenGL structures for rendering.
- return true;
-}
-
-void AcceleratedSurface::Destroy() {
- // Release the old TransportDIB in the browser.
- if (dib_free_callback_.get() && transport_dib_.get()) {
- dib_free_callback_->Run(transport_dib_->id());
- }
- transport_dib_.reset();
- if (gl_context_)
- CGLDestroyContext(gl_context_);
- if (pbuffer_)
- CGLDestroyPBuffer(pbuffer_);
-}
-
-// Call after making changes to the surface which require a visual update.
-// Makes the rendering show up in other processes.
-void AcceleratedSurface::SwapBuffers() {
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- }
- if (io_surface_.get() != NULL) {
- // Bind and unbind the framebuffer to make changes to the
- // IOSurface show up in the other process.
- glFlush();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- } else if (transport_dib_.get() != NULL) {
- // Pre-Mac OS X 10.6, fetch the rendered image from the FBO and copy it
- // into the TransportDIB.
- // TODO(dspringer): There are a couple of options that can speed this up.
- // First is to use async reads into a PBO, second is to use SPI that
- // allows many tasks to access the same CGSSurface.
- void* pixel_memory = transport_dib_->memory();
- if (pixel_memory) {
- // Note that glReadPixels does an implicit glFlush().
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadPixels(0,
- 0,
- surface_width_,
- surface_height_,
- GL_BGRA, // This pixel format should have no conversion.
- GL_UNSIGNED_INT_8_8_8_8_REV,
- pixel_memory);
- }
- }
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
- }
-}
-
-static void AddBooleanValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- bool value) {
- CFDictionaryAddValue(dictionary, key,
- (value ? kCFBooleanTrue : kCFBooleanFalse));
-}
-
-static void AddIntegerValue(CFMutableDictionaryRef dictionary,
- const CFStringRef key,
- int32 value) {
- CFNumberRef number = CFNumberCreate(NULL, kCFNumberSInt32Type, &value);
- CFDictionaryAddValue(dictionary, key, number);
-}
-
-void AcceleratedSurface::AllocateRenderBuffers(GLenum target,
- int32 width, int32 height) {
- if (!texture_) {
- // Generate the texture object.
- glGenTextures(1, &texture_);
- glBindTexture(target, texture_);
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- // Generate and bind the framebuffer object.
- glGenFramebuffersEXT(1, &fbo_);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- bound_fbo_ = fbo_;
- // Generate (but don't bind) the depth buffer -- we don't need
- // this bound in order to do offscreen rendering.
- glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_);
- }
-
- // Reallocate the depth buffer.
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_renderbuffer_);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
- GL_DEPTH24_STENCIL8_EXT,
- width,
- height);
-
- // Unbind the renderbuffers.
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, bound_renderbuffer_);
-
- // Make sure that subsequent set-up code affects the render texture.
- glBindTexture(target, texture_);
-}
-
-bool AcceleratedSurface::SetupFrameBufferObject(GLenum target) {
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);
- }
- GLenum fbo_status;
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- target,
- texture_,
- 0);
- fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
- GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT,
- depth_stencil_renderbuffer_);
- fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- }
- // Attach the depth and stencil buffer.
- if (fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT) {
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
- 0x8D20, // GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER_EXT,
- depth_stencil_renderbuffer_);
- fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- }
- if (bound_fbo_ != fbo_) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo_);
- }
- return fbo_status == GL_FRAMEBUFFER_COMPLETE_EXT;
-}
-
-bool AcceleratedSurface::MakeCurrent() {
- if (CGLGetCurrentContext() != gl_context_) {
- if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
- DLOG(ERROR) << "Unable to make gl context current.";
- return false;
- }
- }
- return true;
-}
-
-void AcceleratedSurface::Clear(const gfx::Rect& rect) {
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glViewport(0, 0, rect.width(), rect.height());
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, rect.width(), 0, rect.height(), -1, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-uint64 AcceleratedSurface::SetSurfaceSize(int32 width, int32 height) {
- if (surface_width_ == width && surface_height_ == height) {
- // Return 0 to indicate to the caller that no new backing store
- // allocation occurred.
- return 0;
- }
-
- IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
- if (!io_surface_support)
- return 0; // Caller can try using SetWindowSizeForTransportDIB().
-
- if (!MakeCurrent())
- return 0;
-
- // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
- // Mac OS X and is required for IOSurface interoperability.
- GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- AllocateRenderBuffers(target, width, height);
-
- // Allocate a new IOSurface, which is the GPU resource that can be
- // shared across processes.
- scoped_cftyperef<CFMutableDictionaryRef> properties;
- properties.reset(CFDictionaryCreateMutable(kCFAllocatorDefault,
- 0,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks));
- AddIntegerValue(properties,
- io_surface_support->GetKIOSurfaceWidth(), width);
- AddIntegerValue(properties,
- io_surface_support->GetKIOSurfaceHeight(), height);
- AddIntegerValue(properties,
- io_surface_support->GetKIOSurfaceBytesPerElement(), 4);
- AddBooleanValue(properties,
- io_surface_support->GetKIOSurfaceIsGlobal(), true);
- // I believe we should be able to unreference the IOSurfaces without
- // synchronizing with the browser process because they are
- // ultimately reference counted by the operating system.
- io_surface_.reset(io_surface_support->IOSurfaceCreate(properties));
-
- // Don't think we need to identify a plane.
- GLuint plane = 0;
- io_surface_support->CGLTexImageIOSurface2D(gl_context_,
- target,
- GL_RGBA,
- width,
- height,
- GL_BGRA,
- GL_UNSIGNED_INT_8_8_8_8_REV,
- io_surface_.get(),
- plane);
- // Set up the frame buffer object.
- SetupFrameBufferObject(target);
- surface_width_ = width;
- surface_height_ = height;
-
- // Now send back an identifier for the IOSurface. We originally
- // intended to send back a mach port from IOSurfaceCreateMachPort
- // but it looks like Chrome IPC would need to be modified to
- // properly send mach ports between processes. For the time being we
- // make our IOSurfaces global and send back their identifiers. On
- // the browser process side the identifier is reconstituted into an
- // IOSurface for on-screen rendering.
- return io_surface_support->IOSurfaceGetID(io_surface_);
-}
-
-TransportDIB::Handle AcceleratedSurface::SetTransportDIBSize(
- int32 width, int32 height) {
- if (surface_width_ == width && surface_height_ == height) {
- // Return an invalid handle to indicate to the caller that no new backing
- // store allocation occurred.
- return TransportDIB::DefaultHandleValue();
- }
- surface_width_ = width;
- surface_height_ = height;
-
- // Release the old TransportDIB in the browser.
- if (dib_free_callback_.get() && transport_dib_.get()) {
- dib_free_callback_->Run(transport_dib_->id());
- }
- transport_dib_.reset();
-
- // Ask the renderer to create a TransportDIB.
- size_t dib_size = width * 4 * height; // 4 bytes per pixel.
- TransportDIB::Handle dib_handle;
- if (dib_alloc_callback_.get()) {
- dib_alloc_callback_->Run(dib_size, &dib_handle);
- }
- if (!TransportDIB::is_valid(dib_handle)) {
- // If the allocator fails, it means the DIB was not created in the browser,
- // so there is no need to run the deallocator here.
- return TransportDIB::DefaultHandleValue();
- }
- transport_dib_.reset(TransportDIB::Map(dib_handle));
- if (transport_dib_.get() == NULL) {
- // TODO(dspringer): if the Map() fails, should the deallocator be run so
- // that the DIB is deallocated in the browser?
- return TransportDIB::DefaultHandleValue();
- }
-
- // Set up the render buffers and reserve enough space on the card for the
- // framebuffer texture.
- GLenum target = GL_TEXTURE_RECTANGLE_ARB;
- AllocateRenderBuffers(target, width, height);
- glTexImage2D(target,
- 0, // mipmap level 0
- GL_RGBA8, // internal pixel format
- width,
- height,
- 0, // 0 border
- GL_BGRA, // Used for consistency
- GL_UNSIGNED_INT_8_8_8_8_REV,
- NULL); // No data, just reserve room on the card.
- SetupFrameBufferObject(target);
- return transport_dib_->handle();
-}
-
-void AcceleratedSurface::SetTransportDIBAllocAndFree(
- Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator) {
- dib_alloc_callback_.reset(allocator);
- dib_free_callback_.reset(deallocator);
-}