|  | // Copyright (c) 2012 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 "ui/gl/gl_context_osmesa.h" | 
|  |  | 
|  | #include <GL/osmesa.h> | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "ui/gfx/geometry/size.h" | 
|  | #include "ui/gl/gl_bindings.h" | 
|  | #include "ui/gl/gl_surface.h" | 
|  |  | 
|  | namespace gfx { | 
|  |  | 
|  | GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group) | 
|  | : GLContextReal(share_group), | 
|  | context_(NULL) { | 
|  | } | 
|  |  | 
|  | bool GLContextOSMesa::Initialize(GLSurface* compatible_surface, | 
|  | GpuPreference gpu_preference) { | 
|  | DCHECK(!context_); | 
|  |  | 
|  | OSMesaContext share_handle = static_cast<OSMesaContext>( | 
|  | share_group() ? share_group()->GetHandle() : NULL); | 
|  |  | 
|  | GLuint format = compatible_surface->GetFormat(); | 
|  | DCHECK_NE(format, (unsigned)0); | 
|  | context_ = OSMesaCreateContextExt(format, | 
|  | 0,  // depth bits | 
|  | 0,  // stencil bits | 
|  | 0,  // accum bits | 
|  | share_handle); | 
|  | if (!context_) { | 
|  | LOG(ERROR) << "OSMesaCreateContextExt failed."; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void GLContextOSMesa::Destroy() { | 
|  | if (context_) { | 
|  | OSMesaDestroyContext(static_cast<OSMesaContext>(context_)); | 
|  | context_ = NULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | bool GLContextOSMesa::MakeCurrent(GLSurface* surface) { | 
|  | DCHECK(context_); | 
|  |  | 
|  | gfx::Size size = surface->GetSize(); | 
|  |  | 
|  | ScopedReleaseCurrent release_current; | 
|  | if (!OSMesaMakeCurrent(context_, | 
|  | surface->GetHandle(), | 
|  | GL_UNSIGNED_BYTE, | 
|  | size.width(), | 
|  | size.height())) { | 
|  | LOG(ERROR) << "OSMesaMakeCurrent failed."; | 
|  | Destroy(); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Set this as soon as the context is current, since we might call into GL. | 
|  | SetRealGLApi(); | 
|  |  | 
|  | // Row 0 is at the top. | 
|  | OSMesaPixelStore(OSMESA_Y_UP, 0); | 
|  |  | 
|  | SetCurrent(surface); | 
|  | if (!InitializeDynamicBindings()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!surface->OnMakeCurrent(this)) { | 
|  | LOG(ERROR) << "Could not make current."; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | release_current.Cancel(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void GLContextOSMesa::ReleaseCurrent(GLSurface* surface) { | 
|  | if (!IsCurrent(surface)) | 
|  | return; | 
|  |  | 
|  | SetCurrent(NULL); | 
|  | // TODO: Calling with NULL here does not work to release the context. | 
|  | OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0); | 
|  | } | 
|  |  | 
|  | bool GLContextOSMesa::IsCurrent(GLSurface* surface) { | 
|  | DCHECK(context_); | 
|  |  | 
|  | bool native_context_is_current = | 
|  | context_ == OSMesaGetCurrentContext(); | 
|  |  | 
|  | // If our context is current then our notion of which GLContext is | 
|  | // current must be correct. On the other hand, third-party code | 
|  | // using OpenGL might change the current context. | 
|  | DCHECK(!native_context_is_current || (GetRealCurrent() == this)); | 
|  |  | 
|  | if (!native_context_is_current) | 
|  | return false; | 
|  |  | 
|  | if (surface) { | 
|  | GLint width; | 
|  | GLint height; | 
|  | GLint format; | 
|  | void* buffer = NULL; | 
|  | OSMesaGetColorBuffer(context_, &width, &height, &format, &buffer); | 
|  | if (buffer != surface->GetHandle()) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void* GLContextOSMesa::GetHandle() { | 
|  | return context_; | 
|  | } | 
|  |  | 
|  | void GLContextOSMesa::OnSetSwapInterval(int interval) { | 
|  | DCHECK(IsCurrent(NULL)); | 
|  | } | 
|  |  | 
|  | GLContextOSMesa::~GLContextOSMesa() { | 
|  | Destroy(); | 
|  | } | 
|  |  | 
|  | }  // namespace gfx |