~thomas-voss/glmark2/build-for-mir

1.1.2 by Jani Monoses
Import upstream version 2011.07
1
/*
2
 * Copyright © 2010-2011 Linaro Limited
3
 *
4
 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
5
 *
6
 * glmark2 is free software: you can redistribute it and/or modify it under the
7
 * terms of the GNU General Public License as published by the Free Software
8
 * Foundation, either version 3 of the License, or (at your option) any later
9
 * version.
10
 *
11
 * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * glmark2.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * Authors:
20
 *  Alexandros Frantzis (glmark2)
21
 */
22
#include "canvas-x11-glx.h"
23
#include "log.h"
24
#include "options.h"
25
26
#include <string>
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
27
#include <climits>
1.1.2 by Jani Monoses
Import upstream version 2011.07
28
29
static PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT_;
30
static PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA_;
8 by Ricardo Salveti de Araujo
* debian/patches/update-handle-api-change-glx_ext_swap_control.patch:
31
static PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESA_;
1.1.2 by Jani Monoses
Import upstream version 2011.07
32
33
/*********************
34
 * Protected methods *
35
 *********************/
36
37
XVisualInfo *
38
CanvasX11GLX::get_xvisualinfo()
39
{
40
    if (!ensure_glx_fbconfig())
41
        return 0;
42
43
    XVisualInfo *vis_info = glXGetVisualFromFBConfig(xdpy_, glx_fbconfig_ );
44
45
    return vis_info;
46
}
47
48
bool
49
CanvasX11GLX::make_current()
50
{
51
    if (!ensure_glx_context())
52
        return false;
53
54
    if (glx_context_ == glXGetCurrentContext())
55
        return true;
56
57
    init_extensions();
58
59
    if (!glXMakeCurrent(xdpy_, xwin_, glx_context_)) {
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
60
        Log::error("glXMakeCurrent failed\n");
1.1.2 by Jani Monoses
Import upstream version 2011.07
61
        return false;
62
    }
63
8 by Ricardo Salveti de Araujo
* debian/patches/update-handle-api-change-glx_ext_swap_control.patch:
64
    unsigned int desired_swap(0);
65
    unsigned int actual_swap(-1);
66
    if (glXSwapIntervalEXT_) {
67
        glXSwapIntervalEXT_(xdpy_, xwin_, desired_swap);
68
        glXQueryDrawable(xdpy_, xwin_, GLX_SWAP_INTERVAL_EXT, &actual_swap);
69
        if (actual_swap == desired_swap)
70
            return true;
71
    }
72
73
    if (glXSwapIntervalMESA_) {
74
        glXSwapIntervalMESA_(desired_swap);
75
        actual_swap = glXGetSwapIntervalMESA_();
76
        if (actual_swap == desired_swap)
77
            return true;
78
    }
79
80
    Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n");
1.1.2 by Jani Monoses
Import upstream version 2011.07
81
82
    return true;
83
}
84
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
85
void
86
CanvasX11GLX::get_glvisualconfig(GLVisualConfig &visual_config)
87
{
88
    if (!ensure_glx_fbconfig())
89
        return;
90
91
    get_glvisualconfig_glx(glx_fbconfig_, visual_config);
92
}
1.1.2 by Jani Monoses
Import upstream version 2011.07
93
94
/*******************
95
 * Private methods *
96
 *******************/
97
98
bool
99
CanvasX11GLX::check_glx_version()
100
{
101
    int glx_major, glx_minor;
102
103
    if (!glXQueryVersion(xdpy_, &glx_major, &glx_minor ) ||
104
        (glx_major == 1  && glx_minor < 3) || glx_major < 1)
105
    {
106
        Log::error("GLX version >= 1.3 is required\n");
107
        return false;
108
    }
109
110
    return true;
111
}
112
113
void
114
CanvasX11GLX::init_extensions()
115
{
116
    /*
117
     * Parse the extensions we care about from the extension string.
118
     * Don't even bother to get function pointers until we know the
119
     * extension is present.
120
     */
121
    std::string extString;
122
    const char* exts = glXQueryExtensionsString(xdpy_, 0);
123
    if (exts) {
124
        extString = exts;
125
    }
126
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
127
    /*
1.1.2 by Jani Monoses
Import upstream version 2011.07
128
     * GLX_EXT_swap_control or GL_MESA_swap_control. Note that
129
     * GLX_SGI_swap_control is not enough because it doesn't allow 0 as a valid
130
     * value (i.e. you can't turn off VSync).
131
     */
132
    if (extString.find("GLX_EXT_swap_control") != std::string::npos) {
133
        glXSwapIntervalEXT_ =
134
            reinterpret_cast<PFNGLXSWAPINTERVALEXTPROC>(
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
135
                glXGetProcAddress(
136
                    reinterpret_cast<const GLubyte *>("glXSwapIntervalEXT")
137
                )
138
            );
1.1.2 by Jani Monoses
Import upstream version 2011.07
139
    }
140
    else if (extString.find("GLX_MESA_swap_control") != std::string::npos) {
141
        glXSwapIntervalMESA_ =
142
            reinterpret_cast<PFNGLXSWAPINTERVALMESAPROC>(
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
143
                glXGetProcAddress(
144
                    reinterpret_cast<const GLubyte *>("glXSwapIntervalMESA")
145
                )
146
            );
8 by Ricardo Salveti de Araujo
* debian/patches/update-handle-api-change-glx_ext_swap_control.patch:
147
        glXGetSwapIntervalMESA_ =
148
            reinterpret_cast<PFNGLXGETSWAPINTERVALMESAPROC>(
149
                glXGetProcAddress(
150
                    reinterpret_cast<const GLubyte *>("glXGetSwapIntervalMESA")
151
                )
152
            );
1.1.2 by Jani Monoses
Import upstream version 2011.07
153
    }
154
155
156
    if (!glXSwapIntervalEXT_ && !glXSwapIntervalMESA_) {
157
        Log::info("** GLX does not support GLX_EXT_swap_control or GLX_MESA_swap_control!\n");
158
    }
159
}
160
161
bool
162
CanvasX11GLX::ensure_glx_fbconfig()
163
{
164
    static int attribs[] = {
165
        GLX_X_RENDERABLE, True,
166
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
167
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
168
        GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
169
        GLX_RED_SIZE, visual_config_.red,
170
        GLX_GREEN_SIZE, visual_config_.green,
171
        GLX_BLUE_SIZE, visual_config_.blue,
172
        GLX_ALPHA_SIZE, visual_config_.alpha,
173
        GLX_DEPTH_SIZE, visual_config_.depth,
174
        GLX_BUFFER_SIZE, visual_config_.buffer,
1.1.2 by Jani Monoses
Import upstream version 2011.07
175
        GLX_DOUBLEBUFFER, True,
176
        None
177
    };
178
    int num_configs;
179
180
    if (glx_fbconfig_)
181
        return true;
182
183
    if (!check_glx_version())
184
        return false;
185
186
    GLXFBConfig *fbc = glXChooseFBConfig(xdpy_, DefaultScreen(xdpy_),
187
                                         attribs, &num_configs);
188
    if (!fbc) {
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
189
        Log::error("glXChooseFBConfig() failed\n");
1.1.2 by Jani Monoses
Import upstream version 2011.07
190
        return false;
191
    }
192
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
193
    std::vector<GLXFBConfig> configs(fbc, fbc + num_configs);
194
1.1.2 by Jani Monoses
Import upstream version 2011.07
195
    Log::debug("Found %d matching FB configs.\n", num_configs);
196
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
197
    /* Select the best matching config */
198
    glx_fbconfig_ = select_best_config(configs);
1.1.2 by Jani Monoses
Import upstream version 2011.07
199
200
    XFree(fbc);
201
202
    if (Options::show_debug) {
203
        int buf, red, green, blue, alpha, depth, id, native_id;
204
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_FBCONFIG_ID, &id);
205
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_VISUAL_ID, &native_id);
206
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BUFFER_SIZE, &buf);
207
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_RED_SIZE, &red);
208
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_GREEN_SIZE, &green);
209
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_BLUE_SIZE, &blue);
210
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_ALPHA_SIZE, &alpha);
211
        glXGetFBConfigAttrib(xdpy_, glx_fbconfig_, GLX_DEPTH_SIZE, &depth);
212
        Log::debug("GLX chosen config ID: 0x%x Native Visual ID: 0x%x\n"
213
                   "  Buffer: %d bits\n"
214
                   "     Red: %d bits\n"
215
                   "   Green: %d bits\n"
216
                   "    Blue: %d bits\n"
217
                   "   Alpha: %d bits\n"
218
                   "   Depth: %d bits\n",
219
                   id, native_id,
220
                   buf, red, green, blue, alpha, depth);
221
    }
222
223
224
    return true;
225
}
226
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
227
void
228
CanvasX11GLX::init_gl_extensions()
229
{
230
    GLExtensions::MapBuffer = glMapBuffer;
231
    GLExtensions::UnmapBuffer = glUnmapBuffer;
232
}
233
234
bool
235
CanvasX11GLX::reset_context()
236
{
237
    glXDestroyContext(xdpy_, glx_context_);
238
    glx_context_ = 0;
239
240
    return true;
241
}
242
1.1.2 by Jani Monoses
Import upstream version 2011.07
243
bool
244
CanvasX11GLX::ensure_glx_context()
245
{
246
    if (glx_context_)
247
        return true;
248
249
    if (!ensure_glx_fbconfig())
250
        return false;
251
252
    glx_context_ = glXCreateNewContext(xdpy_, glx_fbconfig_, GLX_RGBA_TYPE,
253
                                       0, True);
254
    if (!glx_context_) {
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
255
        Log::error("glXCreateNewContext failed\n");
1.1.2 by Jani Monoses
Import upstream version 2011.07
256
        return false;
257
    }
258
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
259
    init_gl_extensions();
260
1.1.2 by Jani Monoses
Import upstream version 2011.07
261
    return true;
262
}
263
1.1.4 by Ricardo Salveti de Araujo
Import upstream version 2012.08
264
void
265
CanvasX11GLX::get_glvisualconfig_glx(const GLXFBConfig config, GLVisualConfig &visual_config)
266
{
267
    glXGetFBConfigAttrib(xdpy_, config, GLX_BUFFER_SIZE, &visual_config.buffer);
268
    glXGetFBConfigAttrib(xdpy_, config, GLX_RED_SIZE, &visual_config.red);
269
    glXGetFBConfigAttrib(xdpy_, config, GLX_GREEN_SIZE, &visual_config.green);
270
    glXGetFBConfigAttrib(xdpy_, config, GLX_BLUE_SIZE, &visual_config.blue);
271
    glXGetFBConfigAttrib(xdpy_, config, GLX_ALPHA_SIZE, &visual_config.alpha);
272
    glXGetFBConfigAttrib(xdpy_, config, GLX_DEPTH_SIZE, &visual_config.depth);
273
}
274
275
GLXFBConfig
276
CanvasX11GLX::select_best_config(std::vector<GLXFBConfig> configs)
277
{
278
    int best_score(INT_MIN);
279
    GLXFBConfig best_config(0);
280
281
    /*
282
     * Go through all the configs and choose the one with the best score,
283
     * i.e., the one better matching the requested config.
284
     */
285
    for (std::vector<GLXFBConfig>::const_iterator iter = configs.begin();
286
         iter != configs.end();
287
         iter++)
288
    {
289
        const GLXFBConfig config(*iter);
290
        GLVisualConfig vc;
291
        int score;
292
293
        get_glvisualconfig_glx(config, vc);
294
295
        score = vc.match_score(visual_config_);
296
297
        if (score > best_score) {
298
            best_score = score;
299
            best_config = config;
300
        }
301
    }
302
303
    return best_config;
304
}