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
GLContextOSMesa(GLShareGroup * share_group)16 GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group)
17 : GLContextReal(share_group),
18 context_(NULL) {
19 }
20
Initialize(GLSurface * compatible_surface,GpuPreference gpu_preference)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
Destroy()43 void GLContextOSMesa::Destroy() {
44 if (context_) {
45 OSMesaDestroyContext(static_cast<OSMesaContext>(context_));
46 context_ = NULL;
47 }
48 }
49
MakeCurrent(GLSurface * surface)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
ReleaseCurrent(GLSurface * surface)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
IsCurrent(GLSurface * surface)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
GetHandle()122 void* GLContextOSMesa::GetHandle() {
123 return context_;
124 }
125
SetSwapInterval(int interval)126 void GLContextOSMesa::SetSwapInterval(int interval) {
127 DCHECK(IsCurrent(NULL));
128 }
129
~GLContextOSMesa()130 GLContextOSMesa::~GLContextOSMesa() {
131 Destroy();
132 }
133
134 } // namespace gfx
135