~albaguirre/mir/possibly-fix-yakkety-build-failure

1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
1
/*
2
 * Copyright © 2014 Canonical Ltd.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License version 3 as
6
 * 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
 * Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
17
 *         Alberto Aguirre <alberto.aguirre@canonical.com>
18
 */
19
20
#include "eglapp.h"
21
#include <assert.h>
22
#include <stdio.h>
23
#include <GLES2/gl2.h>
24
25
#include <vector>
26
#include <stdexcept>
27
#include <iostream>
1575.6.2 by Christopher James Halse Rogers
Use std::min() and constify max_count
28
#include <algorithm>
1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
29
30
static GLuint load_shader(const char *src, GLenum type)
31
{
32
    GLuint shader = glCreateShader(type);
33
    if (shader)
34
    {
35
        GLint compiled;
36
        glShaderSource(shader, 1, &src, NULL);
37
        glCompileShader(shader);
38
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
39
        if (!compiled)
40
        {
41
            GLchar log[1024];
42
            glGetShaderInfoLog(shader, sizeof log - 1, NULL, log);
43
            log[sizeof log - 1] = '\0';
44
            printf("load_shader compile failed: %s\n", log);
45
            glDeleteShader(shader);
46
            shader = 0;
47
        }
48
    }
49
    return shader;
50
}
51
52
class DrawableDigit
53
{
54
public:
55
    DrawableDigit(std::initializer_list<std::vector<GLubyte>> list)
56
    {
57
        for (auto const& arg : list)
58
        {
59
            indices.insert(indices.end(), arg.begin(), arg.end());
60
        }
61
    }
62
63
    void draw()
64
    {
65
        glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_BYTE, indices.data());
66
    }
67
68
private:
69
    DrawableDigit() = delete;
70
    std::vector<GLubyte> indices;
71
};
72
73
class TwoDigitCounter
74
{
75
public:
76
    TwoDigitCounter(GLuint prog, float thickness, unsigned int max_count)
1575.6.2 by Christopher James Halse Rogers
Use std::min() and constify max_count
77
        : count{0}, max_count{std::min(max_count, 99u)}, program{prog},
1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
78
          vertices{create_vertices(thickness)}, digit_drawables{create_digits()}
79
    {
80
        vpos = glGetAttribLocation(program, "vPosition");
81
        if (vpos == -1)
82
            throw std::runtime_error("Failed to obtain vPosition attribute");
83
84
        xoff = glGetUniformLocation(program, "xOffset");
85
        if (xoff == -1)
86
            throw std::runtime_error("Failed to obtain xoff uniform");
87
88
        xscale = glGetUniformLocation(program, "xScale");
89
        if (xscale == -1)
90
            throw std::runtime_error("Failed to obtain xscale uniform");
91
92
        glUniform1f(xscale, 0.4f);
93
        glVertexAttribPointer(vpos, 2, GL_FLOAT, GL_FALSE, 0, vertices.data());
94
        glEnableVertexAttribArray(0);
95
    }
96
97
    void draw()
98
    {
99
        drawLeftDigit();
100
        drawRightDigit();
101
        nextCount();
102
    }
103
104
private:
105
    void draw(int digit)
106
    {
107
        if (static_cast<size_t>(digit) > digit_drawables.size())
108
            throw std::logic_error("invalid digit to draw");
109
110
        digit_drawables[digit].draw();
111
    }
112
113
    void drawRightDigit()
114
    {
115
        glUniform1f(xoff, 0.5f);
116
        draw(count % 10);
117
    }
118
119
    void drawLeftDigit()
120
    {
121
        glUniform1f(xoff, -0.5f);
122
        draw(count/10);
123
    }
124
125
    void nextCount()
126
    {
127
        count++;
128
        if (count > max_count) count = 0;
129
    }
130
131
    static std::vector<GLfloat> create_vertices(GLfloat t)
132
    {
133
        return std::vector<GLfloat>{
134
            -1.0f,   -1.0f,
135
            -1.0f+t, -1.0f,
136
             1.0f-t, -1.0f,
137
138
             1.0f,   -1.0f,
139
            -1.0f,   -1.0f+t,
140
             1.0f,   -1.0f+t,
141
142
            -1.0f,   -t/2.0f,
143
            -1.0f+t, -t/2.0f,
144
             1.0f-t, -t/2.0f,
145
146
             1.0f,   -t/2.0f,
147
            -1.0f,    t/2.0f,
148
             1.0f,    t/2.0f,
149
150
            -1.0f,    1.0f-t,
151
             1.0f,    1.0f-t,
152
            -1.0f,    1.0f,
153
154
            -1.0f+t,  1.0f,
155
             1.0f-t,  1.0f,
156
             1.0f,    1.0f,
157
        };
158
    }
159
160
    static std::vector<DrawableDigit> create_digits()
161
    {
162
        std::vector<DrawableDigit> digits;
163
        /*
164
         * Vertex indices for quads which can be used to make
165
         * simple number "font" shapes
166
         */
167
        std::vector<GLubyte> top{12, 14, 13, 13, 14, 17};
168
        std::vector<GLubyte> bottom{0, 4, 3, 3, 4, 5};
169
        std::vector<GLubyte> middle{6, 10, 9, 9, 10, 11};
170
        std::vector<GLubyte> left{0, 14, 1, 1, 14, 15};
171
        std::vector<GLubyte> right{2, 16, 3, 3, 16, 17};
172
173
        std::vector<GLubyte> top_left{6, 14, 7, 7, 14, 15};
174
        std::vector<GLubyte> top_right{8, 16, 9, 9, 16, 17};
175
        std::vector<GLubyte> bottom_left{0, 6, 1, 1, 6, 7};
176
        std::vector<GLubyte> bottom_right{2, 8, 3, 3, 8, 9};
177
178
        digits.push_back({top, bottom, left, right});
179
        digits.push_back({right});
180
        digits.push_back({top, middle, bottom, top_right, bottom_left});
181
        digits.push_back({top, middle, bottom, right});
182
        digits.push_back({top_left, middle, right});
183
        digits.push_back({top, middle, bottom, top_left, bottom_right});
184
        digits.push_back({top, middle, bottom, left, bottom_right});
185
        digits.push_back({top, right});
186
        digits.push_back({top, middle, bottom, left, right});
187
        digits.push_back({top, middle, right, top_left});
188
        return digits;
189
    }
190
191
    unsigned int count;
1575.6.2 by Christopher James Halse Rogers
Use std::min() and constify max_count
192
    unsigned int const max_count;
1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
193
194
    GLint vpos;
195
    GLint xoff;
196
    GLint xscale;
197
    GLuint program;
198
199
    std::vector<GLfloat> const vertices;
200
    std::vector<DrawableDigit> digit_drawables;
201
};
202
203
/* Colours from http://design.ubuntu.com/brand/colour-palette */
1758.2.1 by Daniel van Vugt
examples: Add associativity protection to the MID_AUBERGINE macro parameter.
204
#define MID_AUBERGINE(x) (x)*0.368627451f, (x)*0.152941176f, (x)*0.31372549f
1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
205
#define ORANGE        0.866666667f, 0.282352941f, 0.141414141f
206
207
int main(int argc, char *argv[])
208
{
209
    const char vshadersrc[] =
210
        "attribute vec4 vPosition;            \n"
211
        "uniform float xOffset;               \n"
212
        "uniform float xScale;                \n"
213
        "void main()                          \n"
214
        "{                                    \n"
215
        "    vec4 vertex;                     \n"
216
        "    vertex = vPosition;              \n"
217
        "    vertex.x *= xScale;              \n"
218
        "    vertex.x += xOffset;             \n"
219
        "    gl_Position = vertex;            \n"
220
        "}                                    \n";
221
222
    const char fshadersrc[] =
223
        "precision mediump float;             \n"
224
        "uniform vec4 col;                    \n"
225
        "void main()                          \n"
226
        "{                                    \n"
227
        "    gl_FragColor = col;              \n"
228
        "}                                    \n";
229
230
    GLuint vshader, fshader, prog;
231
    GLint linked, col;
232
    unsigned int width = 512, height = 256;
233
234
    if (!mir_eglapp_init(argc, argv, &width, &height))
235
        return 1;
236
237
    vshader = load_shader(vshadersrc, GL_VERTEX_SHADER);
238
    assert(vshader);
239
    fshader = load_shader(fshadersrc, GL_FRAGMENT_SHADER);
240
    assert(fshader);
241
    prog = glCreateProgram();
242
    assert(prog);
243
    glAttachShader(prog, vshader);
244
    glAttachShader(prog, fshader);
245
    glLinkProgram(prog);
246
247
    glGetProgramiv(prog, GL_LINK_STATUS, &linked);
248
    if (!linked)
249
    {
250
        GLchar log[1024];
251
        glGetProgramInfoLog(prog, sizeof log - 1, NULL, log);
252
        log[sizeof log - 1] = '\0';
253
        printf("Link failed: %s\n", log);
254
        return 2;
255
    }
256
1681.1.1 by Alberto Aguirre
renderer: Change blending equation to assume pre-multiplied alpha (LP: #1318852)
257
    float const opacity = mir_eglapp_background_opacity;
258
    glClearColor(MID_AUBERGINE(opacity), opacity);
1550.4.1 by Alberto Aguirre
Add a simple two digit on-screen counter example.
259
    glViewport(0, 0, width, height);
260
261
    glUseProgram(prog);
262
263
    col = glGetUniformLocation(prog, "col");
264
    glUniform4f(col, ORANGE, 1.0f);
265
266
    float thickness = 0.2f;
267
    unsigned int max_counter = 60;
268
    TwoDigitCounter counter(prog, thickness, max_counter);
269
270
    while (mir_eglapp_running())
271
    {
272
        glClear(GL_COLOR_BUFFER_BIT);
273
        counter.draw();
274
        mir_eglapp_swap_buffers();
275
    }
276
277
    mir_eglapp_shutdown();
278
279
    return 0;
280
}