Home | History | Annotate | Download | only in gl
      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