~ubuntu-branches/ubuntu/wily/mir/wily-proposed

« back to all changes in this revision

Viewing changes to src/server/graphics/surfaceless_egl_context.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-01-08 02:04:38 UTC
  • mto: This revision was merged to the branch mainline in revision 58.
  • Revision ID: package-import@ubuntu.com-20140108020438-e1npu0pm7qdv5wc4
Tags: upstream-0.1.3+14.04.20140108
Import upstream version 0.1.3+14.04.20140108

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2013 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3,
 
6
 * as published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir/graphics/surfaceless_egl_context.h"
 
20
#include "mir/graphics/gl_extensions_base.h"
 
21
 
 
22
#include <boost/throw_exception.hpp>
 
23
#include <stdexcept>
 
24
#include <vector>
 
25
 
 
26
namespace mg = mir::graphics;
 
27
 
 
28
namespace
 
29
{
 
30
 
 
31
class EGLExtensions : public mg::GLExtensionsBase
 
32
{
 
33
public:
 
34
    EGLExtensions(EGLDisplay egl_display) :
 
35
        mg::GLExtensionsBase{
 
36
            reinterpret_cast<char const*>(eglQueryString(egl_display, EGL_EXTENSIONS))}
 
37
    {
 
38
    }
 
39
};
 
40
 
 
41
bool supports_surfaceless_context(EGLDisplay egl_display)
 
42
{
 
43
    EGLExtensions const extensions{egl_display};
 
44
 
 
45
    return extensions.support("EGL_KHR_surfaceless_context");
 
46
}
 
47
 
 
48
std::vector<EGLint> ensure_pbuffer_set(EGLint const* attribs)
 
49
{
 
50
    bool has_preferred_surface = false;
 
51
    std::vector<EGLint> attribs_with_surface_type;
 
52
    int i = 0;
 
53
 
 
54
    while (attribs[i] != EGL_NONE)
 
55
    {
 
56
        attribs_with_surface_type.push_back(attribs[i]);
 
57
        if (attribs[i] == EGL_SURFACE_TYPE)
 
58
        {
 
59
            has_preferred_surface = true;
 
60
            if (attribs[i+1] == EGL_DONT_CARE)
 
61
            {
 
62
                /* Need to treat EGL_DONT_CARE specially, as it is defined as all-bits-set */
 
63
                attribs_with_surface_type.push_back(EGL_PBUFFER_BIT);
 
64
            }
 
65
            else
 
66
            {
 
67
                attribs_with_surface_type.push_back(attribs[i+1] | EGL_PBUFFER_BIT);
 
68
            }
 
69
        }
 
70
        else
 
71
        {
 
72
            attribs_with_surface_type.push_back(attribs[i+1]);
 
73
        }
 
74
        i += 2;
 
75
    }
 
76
 
 
77
    if (!has_preferred_surface)
 
78
    {
 
79
        attribs_with_surface_type.push_back(EGL_SURFACE_TYPE);
 
80
        attribs_with_surface_type.push_back(EGL_PBUFFER_BIT);
 
81
    }
 
82
 
 
83
    attribs_with_surface_type.push_back(EGL_NONE);
 
84
 
 
85
    return attribs_with_surface_type;
 
86
}
 
87
 
 
88
EGLConfig choose_config(EGLDisplay egl_display, EGLint const* attribs, bool surfaceless)
 
89
{
 
90
    EGLConfig egl_config{0};
 
91
    int num_egl_configs{0};
 
92
    std::vector<EGLint> validated_attribs;
 
93
 
 
94
    if (!surfaceless)
 
95
    {
 
96
        validated_attribs = ensure_pbuffer_set(attribs);
 
97
        attribs = validated_attribs.data();
 
98
    }
 
99
 
 
100
    if (eglChooseConfig(egl_display, attribs, &egl_config, 1, &num_egl_configs) == EGL_FALSE ||
 
101
        num_egl_configs != 1)
 
102
    {
 
103
        BOOST_THROW_EXCEPTION(std::runtime_error("Failed to choose EGL config"));
 
104
    }
 
105
 
 
106
    return egl_config;
 
107
}
 
108
 
 
109
EGLSurface create_surface(EGLDisplay egl_display, EGLConfig egl_config)
 
110
{
 
111
    static EGLint const dummy_pbuffer_attribs[] =
 
112
    {
 
113
        EGL_WIDTH, 1,
 
114
        EGL_HEIGHT, 1,
 
115
        EGL_NONE
 
116
    };
 
117
 
 
118
    return eglCreatePbufferSurface(egl_display, egl_config, dummy_pbuffer_attribs);
 
119
}
 
120
 
 
121
EGLint const default_egl_context_attr[] =
 
122
{
 
123
    EGL_CONTEXT_CLIENT_VERSION, 2,
 
124
    EGL_NONE
 
125
};
 
126
 
 
127
EGLint const default_attr[] =
 
128
{
 
129
    EGL_SURFACE_TYPE, EGL_DONT_CARE,
 
130
    EGL_RED_SIZE, 8,
 
131
    EGL_GREEN_SIZE, 8,
 
132
    EGL_BLUE_SIZE, 8,
 
133
    EGL_ALPHA_SIZE, 0,
 
134
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 
135
    EGL_NONE
 
136
};
 
137
 
 
138
 
 
139
}
 
140
 
 
141
mg::SurfacelessEGLContext::SurfacelessEGLContext(EGLDisplay egl_display, EGLContext shared_context)
 
142
    : SurfacelessEGLContext(egl_display, default_attr, shared_context)
 
143
{
 
144
}
 
145
 
 
146
mg::SurfacelessEGLContext::SurfacelessEGLContext(
 
147
        EGLDisplay egl_display,
 
148
        EGLint const* attribs,
 
149
        EGLContext shared_context)
 
150
    : egl_display{egl_display},
 
151
      surfaceless{supports_surfaceless_context(egl_display)},
 
152
      egl_config{choose_config(egl_display, attribs, surfaceless)},
 
153
      egl_surface{egl_display,
 
154
                  surfaceless ? EGL_NO_SURFACE : create_surface(egl_display, egl_config),
 
155
                  surfaceless ? EGLSurfaceStore::AllowNoSurface :
 
156
                                EGLSurfaceStore::DisallowNoSurface},
 
157
      egl_context{egl_display,
 
158
                  eglCreateContext(egl_display, egl_config,
 
159
                                   shared_context,
 
160
                                   default_egl_context_attr)}
 
161
{
 
162
}
 
163
 
 
164
 
 
165
mg::SurfacelessEGLContext::SurfacelessEGLContext(SurfacelessEGLContext&& move)
 
166
    : egl_display(move.egl_display),
 
167
      surfaceless(move.surfaceless),
 
168
      egl_config(move.egl_config),
 
169
      egl_surface{std::move(move.egl_surface)},
 
170
      egl_context{std::move(move.egl_context)}
 
171
{
 
172
    move.egl_display = EGL_NO_DISPLAY;
 
173
}
 
174
 
 
175
mg::SurfacelessEGLContext::~SurfacelessEGLContext() noexcept
 
176
{
 
177
    release_current();
 
178
}
 
179
 
 
180
 
 
181
void mg::SurfacelessEGLContext::make_current() const
 
182
{
 
183
    if (eglGetCurrentContext() == egl_context)
 
184
        return;
 
185
 
 
186
    if (eglMakeCurrent(egl_display, egl_surface, egl_surface,
 
187
                       egl_context) == EGL_FALSE)
 
188
    {
 
189
        BOOST_THROW_EXCEPTION(
 
190
            std::runtime_error("could not make context current\n"));
 
191
    }
 
192
}
 
193
 
 
194
void mg::SurfacelessEGLContext::release_current() const
 
195
{
 
196
    if (egl_context != EGL_NO_CONTEXT && eglGetCurrentContext() == egl_context)
 
197
        eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 
198
}
 
199
 
 
200
mg::SurfacelessEGLContext::operator EGLContext() const
 
201
{
 
202
    return egl_context;
 
203
}