15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_context_osmesa.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <GL/osmesa.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_bindings.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gl/gl_surface.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group)
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : GLContextReal(share_group),
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_(NULL) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextOSMesa::Initialize(GLSurface* compatible_surface,
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GpuPreference gpu_preference) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!context_);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMesaContext share_handle = static_cast<OSMesaContext>(
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      share_group() ? share_group()->GetHandle() : NULL);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GLuint format = compatible_surface->GetFormat();
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(format, (unsigned)0);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_ = OSMesaCreateContextExt(format,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    0,  // depth bits
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    0,  // stencil bits
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    0,  // accum bits
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    share_handle);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!context_) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "OSMesaCreateContextExt failed.";
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextOSMesa::Destroy() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context_) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSMesaDestroyContext(static_cast<OSMesaContext>(context_));
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_ = NULL;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextOSMesa::MakeCurrent(GLSurface* surface) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Size size = surface->GetSize();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!OSMesaMakeCurrent(context_,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         surface->GetHandle(),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GL_UNSIGNED_BYTE,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         size.width(),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         size.height())) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "OSMesaMakeCurrent failed.";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Destroy();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Set this as soon as the context is current, since we might call into GL.
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  SetRealGLApi();
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Row 0 is at the top.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMesaPixelStore(OSMESA_Y_UP, 0);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetCurrent(surface);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InitializeExtensionBindings()) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReleaseCurrent(surface);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!surface->OnMakeCurrent(this)) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Could not make current.";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextOSMesa::ReleaseCurrent(GLSurface* surface) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsCurrent(surface))
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SetCurrent(NULL);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GLContextOSMesa::IsCurrent(GLSurface* surface) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(context_);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool native_context_is_current =
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_ == OSMesaGetCurrentContext();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If our context is current then our notion of which GLContext is
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // current must be correct. On the other hand, third-party code
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using OpenGL might change the current context.
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!native_context_is_current || (GetRealCurrent() == this));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!native_context_is_current)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (surface) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLint width;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLint height;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GLint format;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* buffer = NULL;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSMesaGetColorBuffer(context_, &width, &height, &format, &buffer);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (buffer != surface->GetHandle())
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* GLContextOSMesa::GetHandle() {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return context_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GLContextOSMesa::SetSwapInterval(int interval) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsCurrent(NULL));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GLContextOSMesa::~GLContextOSMesa() {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Destroy();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
133