1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/gl/gl_context_osmesa.h" 6 7 #include <GL/osmesa.h> 8 9 #include "base/logging.h" 10 #include "ui/gfx/size.h" 11 #include "ui/gl/gl_bindings.h" 12 #include "ui/gl/gl_surface.h" 13 14 namespace gfx { 15 16 GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group) 17 : GLContextReal(share_group), 18 context_(NULL) { 19 } 20 21 bool GLContextOSMesa::Initialize(GLSurface* compatible_surface, 22 GpuPreference gpu_preference) { 23 DCHECK(!context_); 24 25 OSMesaContext share_handle = static_cast<OSMesaContext>( 26 share_group() ? share_group()->GetHandle() : NULL); 27 28 GLuint format = compatible_surface->GetFormat(); 29 DCHECK_NE(format, (unsigned)0); 30 context_ = OSMesaCreateContextExt(format, 31 0, // depth bits 32 0, // stencil bits 33 0, // accum bits 34 share_handle); 35 if (!context_) { 36 LOG(ERROR) << "OSMesaCreateContextExt failed."; 37 return false; 38 } 39 40 return true; 41 } 42 43 void GLContextOSMesa::Destroy() { 44 if (context_) { 45 OSMesaDestroyContext(static_cast<OSMesaContext>(context_)); 46 context_ = NULL; 47 } 48 } 49 50 bool GLContextOSMesa::MakeCurrent(GLSurface* surface) { 51 DCHECK(context_); 52 53 gfx::Size size = surface->GetSize(); 54 55 ScopedReleaseCurrent release_current; 56 if (!OSMesaMakeCurrent(context_, 57 surface->GetHandle(), 58 GL_UNSIGNED_BYTE, 59 size.width(), 60 size.height())) { 61 LOG(ERROR) << "OSMesaMakeCurrent failed."; 62 Destroy(); 63 return false; 64 } 65 66 // Set this as soon as the context is current, since we might call into GL. 67 SetRealGLApi(); 68 69 // Row 0 is at the top. 70 OSMesaPixelStore(OSMESA_Y_UP, 0); 71 72 SetCurrent(surface); 73 if (!InitializeDynamicBindings()) { 74 return false; 75 } 76 77 if (!surface->OnMakeCurrent(this)) { 78 LOG(ERROR) << "Could not make current."; 79 return false; 80 } 81 82 release_current.Cancel(); 83 return true; 84 } 85 86 void GLContextOSMesa::ReleaseCurrent(GLSurface* surface) { 87 if (!IsCurrent(surface)) 88 return; 89 90 SetCurrent(NULL); 91 // TODO: Calling with NULL here does not work to release the context. 92 OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0); 93 } 94 95 bool GLContextOSMesa::IsCurrent(GLSurface* surface) { 96 DCHECK(context_); 97 98 bool native_context_is_current = 99 context_ == OSMesaGetCurrentContext(); 100 101 // If our context is current then our notion of which GLContext is 102 // current must be correct. On the other hand, third-party code 103 // using OpenGL might change the current context. 104 DCHECK(!native_context_is_current || (GetRealCurrent() == this)); 105 106 if (!native_context_is_current) 107 return false; 108 109 if (surface) { 110 GLint width; 111 GLint height; 112 GLint format; 113 void* buffer = NULL; 114 OSMesaGetColorBuffer(context_, &width, &height, &format, &buffer); 115 if (buffer != surface->GetHandle()) 116 return false; 117 } 118 119 return true; 120 } 121 122 void* GLContextOSMesa::GetHandle() { 123 return context_; 124 } 125 126 void GLContextOSMesa::SetSwapInterval(int interval) { 127 DCHECK(IsCurrent(NULL)); 128 } 129 130 GLContextOSMesa::~GLContextOSMesa() { 131 Destroy(); 132 } 133 134 } // namespace gfx 135