diff options
author | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 14:26:16 +0000 |
---|---|---|
committer | pinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-10 14:26:16 +0000 |
commit | f8ee26e45e8a04bb75a3e7b0449b8acf3efb04e2 (patch) | |
tree | faf7390df7bc035edbda8458897432329040de04 /gpu/command_buffer | |
parent | b5e18b1d24c065bdeb874abca3e9c41b42b5192f (diff) | |
download | chromium_src-f8ee26e45e8a04bb75a3e7b0449b8acf3efb04e2.zip chromium_src-f8ee26e45e8a04bb75a3e7b0449b8acf3efb04e2.tar.gz chromium_src-f8ee26e45e8a04bb75a3e7b0449b8acf3efb04e2.tar.bz2 |
Implement the CoreAnimation drawing model for plug-ins, sharing IPC and some rendering code with the GPU Plug-in. The drawing model negotiation is currently disabled so this should have no visible impact to plug-ins.
BUG=32012
TEST=make sure the pepper GPU plug-ins still work.
Review URL: http://codereview.chromium.org/673001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41158 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 346 |
1 files changed, 11 insertions, 335 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index e07dc99..b9637e9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -31,13 +31,7 @@ // XWindowWrapper is stubbed out for unit-tests. #include "gpu/command_buffer/service/x_utils.h" #elif defined(OS_MACOSX) -// The following two #includes CAN NOT go above the inclusion of -// gl_utils.h and therefore glew.h regardless of what the Google C++ -// style guide says. -#include <CoreFoundation/CoreFoundation.h> // NOLINT -#include <OpenGL/OpenGL.h> // NOLINT -#include "base/scoped_cftyperef.h" -#include "chrome/common/io_surface_support_mac.h" +#include "chrome/common/accelerated_surface_mac.h" #endif namespace gpu { @@ -564,20 +558,6 @@ class GLES2DecoderImpl : public GLES2Decoder { #undef GLES2_CMD_OP -#if defined(OS_MACOSX) - // Helper function to generate names for the backing texture, render buffers - // and FBO. On return, the resulting buffer names can be attached to |fbo_|. - // |target| is the target type for the color buffer. - void AllocateRenderBuffers(GLenum target, int32 width, int32 height); - - // Helper function to attach the buffers previously allocated by a call to - // AllocateRenderBuffers(). On return, |fbo_| can be used for - // rendering. |target| must be the same value as used in the call to - // AllocateRenderBuffers(). Returns |true| if the resulting framebuffer - // object is valid. - bool SetupFrameBufferObject(GLenum target); -#endif - // Current GL error bits. uint32 error_bits_; @@ -626,32 +606,7 @@ class GLES2DecoderImpl : public GLES2Decoder { HGLRC gl_context_; HPBUFFERARB pbuffer_; #elif defined(OS_MACOSX) - CGLContextObj gl_context_; - CGLPBufferObj pbuffer_; - // Either |io_surface_| or |transport_dib_| is a valid pointer, but not both. - // |io_surface_| is non-NULL if the IOSurface APIs are supported (Mac OS X - // 10.6 and later). - // TODO(dspringer,kbr): Should the GPU backing store be encapsulated in its - // own class so all this implementation detail is hidden? - scoped_cftyperef<CFTypeRef> io_surface_; - // TODO(dspringer): If we end up keeping this TransportDIB mechanism, this - // should really be a scoped_ptr_malloc<>, with a deallocate functor that - // runs |dib_free_callback_|. I was not able to figure out how to - // make this work (or even compile). - scoped_ptr<TransportDIB> transport_dib_; - int32 surface_width_; - int32 surface_height_; - GLuint texture_; - GLuint fbo_; - GLuint depth_stencil_renderbuffer_; - // For tracking whether the default framebuffer / renderbuffer or - // ones created by the end user are currently bound - GLuint bound_fbo_; - GLuint bound_renderbuffer_; - // Allocate a TransportDIB in the renderer. - scoped_ptr<Callback2<size_t, TransportDIB::Handle*>::Type> - dib_alloc_callback_; - scoped_ptr<Callback1<TransportDIB::Id>::Type> dib_free_callback_; + AcceleratedSurface surface_; #endif bool anti_aliased_; @@ -684,16 +639,6 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group) gl_device_context_(NULL), gl_context_(NULL), pbuffer_(NULL), -#elif defined(OS_MACOSX) - 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), #endif anti_aliased_(false) { } @@ -1001,13 +946,7 @@ bool GLES2DecoderImpl::MakeCurrent() { #elif defined(OS_LINUX) return window()->MakeCurrent(); #elif defined(OS_MACOSX) - if (CGLGetCurrentContext() != gl_context_) { - if (CGLSetCurrentContext(gl_context_) != kCGLNoError) { - DLOG(ERROR) << "Unable to make gl context current."; - return false; - } - } - return true; + return surface_.MakeCurrent(); #else NOTREACHED(); return false; @@ -1113,48 +1052,7 @@ bool GLES2DecoderImpl::InitPlatformSpecific() { if (!window()->Initialize()) return false; #elif defined(OS_MACOSX) - // 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 surface_.Initialize(); #endif return true; @@ -1240,151 +1138,12 @@ void GLES2DecoderImpl::DestroyPlatformSpecific() { } #if defined(OS_MACOSX) -#if !defined(UNIT_TEST) -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); -} -#endif // !defined(UNIT_TEST) - -void GLES2DecoderImpl::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 GLES2DecoderImpl::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, - 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; -} uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) { #if defined(UNIT_TEST) return 0; #else - 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_); + return surface_.SetSurfaceSize(width, height); #endif // !defined(UNIT_TEST) } @@ -1393,61 +1152,14 @@ TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB( #if defined(UNIT_TEST) return TransportDIB::DefaultHandleValue(); #else - 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(); + return surface_.SetTransportDIBSize(width, height); #endif // !defined(UNIT_TEST) } void GLES2DecoderImpl::SetTransportDIBAllocAndFree( Callback2<size_t, TransportDIB::Handle*>::Type* allocator, Callback1<TransportDIB::Id>::Type* deallocator) { - dib_alloc_callback_.reset(allocator); - dib_free_callback_.reset(deallocator); + surface_.SetTransportDIBAllocAndFree(allocator, deallocator); } #endif // defined(OS_MACOSX) @@ -1461,15 +1173,7 @@ void GLES2DecoderImpl::Destroy() { DCHECK(window()); window()->Destroy(); #elif defined(OS_MACOSX) - // 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_); + surface_.Destroy(); #endif DestroyPlatformSpecific(); @@ -1728,37 +1432,9 @@ void GLES2DecoderImpl::DoSwapBuffers() { DCHECK(window()); window()->SwapBuffers(); #elif defined(OS_MACOSX) - 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_); - } + // TODO(kbr): Need to property hook up and track the OpenGL state and hook + // up the notion of the currently bound FBO. + surface_.SwapBuffers(); #endif if (swap_buffers_callback_.get()) { swap_buffers_callback_->Run(); |