root/ui/gl/gl_context_osmesa.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. context_
  2. Initialize
  3. Destroy
  4. MakeCurrent
  5. ReleaseCurrent
  6. IsCurrent
  7. GetHandle
  8. SetSwapInterval

// 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/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::SetSwapInterval(int interval) {
  DCHECK(IsCurrent(NULL));
}

GLContextOSMesa::~GLContextOSMesa() {
  Destroy();
}

}  // namespace gfx

/* [<][>][^][v][top][bottom][index][help] */