blob: 592a0e23313a5d9cc24505235b5f6c8c44ef58fa [file] [log] [blame]
Zach Reiznere60ae5d2014-12-03 15:55:53 -08001/* Copyright (c) 2014 The Chromium OS 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
6#include <errno.h>
7#include <fcntl.h>
8#include <stdbool.h>
9#include <stdio.h>
10#include <string.h>
11#include <sys/types.h>
12#include <unistd.h>
13
Zach Reiznere60ae5d2014-12-03 15:55:53 -080014#include <EGL/egl.h>
15#include <EGL/eglext.h>
16#include <GLES2/gl2.h>
17#include <GLES2/gl2ext.h>
18
19const char * get_gl_error()
20{
21 switch (glGetError()) {
22 case GL_NO_ERROR:
23 return "No error has been recorded.";
24 case GL_INVALID_ENUM:
25 return "An unacceptable value is specified for an enumerated argument. The offending command is ignored and has no other side effect than to set the error flag.";
26 case GL_INVALID_VALUE:
27 return "A numeric argument is out of range. The offending command is ignored and has no other side effect than to set the error flag.";
28 case GL_INVALID_OPERATION:
29 return "The specified operation is not allowed in the current state. The offending command is ignored and has no other side effect than to set the error flag.";
30 case GL_INVALID_FRAMEBUFFER_OPERATION:
31 return "The command is trying to render to or read from the framebuffer while the currently bound framebuffer is not framebuffer complete (i.e. the return value from glCheckFramebufferStatus is not GL_FRAMEBUFFER_COMPLETE). The offending command is ignored and has no other side effect than to set the error flag.";
32 case GL_OUT_OF_MEMORY:
33 return "There is not enough memory left to execute the command. The state of the GL is undefined, except for the state of the error flags, after this error is recorded.";
34 default:
35 return "Unknown error";
36 }
37}
38
39const char * get_egl_error()
40{
41 switch (eglGetError()) {
42 case EGL_SUCCESS:
43 return "The last function succeeded without error.";
44 case EGL_NOT_INITIALIZED:
45 return "EGL is not initialized, or could not be initialized, for the specified EGL display connection.";
46 case EGL_BAD_ACCESS:
47 return "EGL cannot access a requested resource (for example a context is bound in another thread).";
48 case EGL_BAD_ALLOC:
49 return "EGL failed to allocate resources for the requested operation.";
50 case EGL_BAD_ATTRIBUTE:
51 return "An unrecognized attribute or attribute value was passed in the attribute list.";
52 case EGL_BAD_CONTEXT:
53 return "An EGLContext argument does not name a valid EGL rendering context.";
54 case EGL_BAD_CONFIG:
55 return "An EGLConfig argument does not name a valid EGL frame buffer configuration.";
56 case EGL_BAD_CURRENT_SURFACE:
57 return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.";
58 case EGL_BAD_DISPLAY:
59 return "An EGLDisplay argument does not name a valid EGL display connection.";
60 case EGL_BAD_SURFACE:
61 return "An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.";
62 case EGL_BAD_MATCH:
63 return "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).";
64 case EGL_BAD_PARAMETER:
65 return "One or more argument values are invalid.";
66 case EGL_BAD_NATIVE_PIXMAP:
67 return "A NativePixmapType argument does not refer to a valid native pixmap.";
68 case EGL_BAD_NATIVE_WINDOW:
69 return "A NativeWindowType argument does not refer to a valid native window.";
70 case EGL_CONTEXT_LOST:
71 return "A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering.";
72 default:
73 return "Unknown error";
74 }
75}
76
77struct context {
78 unsigned width;
79 unsigned height;
80 EGLDisplay egl_display;
81 EGLContext egl_ctx;
82
83 unsigned gl_fb;
84 unsigned gl_rb;
85
86};
87
88float f(int i) {
89 int a = i % 40;
90 int b = (i / 40) % 6;
91 switch (b) {
92 case 0:
93 case 1:
94 return 0.0f;
95 case 3:
96 case 4:
97 return 1.0f;
98 case 2:
99 return (a / 40.0f);
100 case 5:
101 return 1.0f - (a / 40.0f);
102 default:
103 return 0.0f;
104 }
105}
106
107void draw(struct context * ctx)
108{
109 int i;
110 const GLchar *vertexShaderStr =
111 "attribute vec4 vPosition;\n"
112 "attribute vec4 vColor;\n"
113 "varying vec4 vFillColor;\n"
114 "void main() {\n"
115 " gl_Position = vPosition;\n"
116 " vFillColor = vColor;\n"
117 "}\n";
118 const GLchar *fragmentShaderStr =
119 "precision mediump float;\n"
120 "varying vec4 vFillColor;\n"
121 "void main() {\n"
122 " gl_FragColor = vFillColor;\n"
123 "}\n";
124 GLint vertexShader, fragmentShader, program, status;
125
126 vertexShader = glCreateShader(GL_VERTEX_SHADER);
127 if (!vertexShader) {
128 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
129 return;
130 }
131 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
132 glCompileShader(vertexShader);
133 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
134 if (!status) {
135 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
136 return;
137 }
138
139 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
140 if (!fragmentShader) {
141 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
142 return;
143 }
144 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
145 glCompileShader(fragmentShader);
146 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
147 if (!status) {
148 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
149 return;
150 }
151
152
153 program = glCreateProgram();
154 if (!program) {
155 fprintf(stderr, "Failed to create program.\n");
156 return;
157 }
158 glAttachShader(program, vertexShader);
159 glAttachShader(program, fragmentShader);
160 glBindAttribLocation(program, 0, "vPosition");
161 glBindAttribLocation(program, 1, "vColor");
162 glLinkProgram(program);
163 glGetShaderiv(program, GL_LINK_STATUS, &status);
164 if (!status) {
165 fprintf(stderr, "Failed to link program.\n");
166 return;
167 }
168
169
170 glViewport(0, 0,(GLint) ctx->width,
171 (GLint) ctx->height);
172
173 for (i = 0; i <= 500; i++) {
174 GLfloat verts[] = {
175 0.0f, -0.5f, 0.0f,
176 -0.5f, 0.5f, 0.0f,
177 0.5f, 0.5f, 0.0f
178 };
179 GLfloat colors[] = {
180 1.0f, 0.0f, 0.0f, 1.0f,
181 0.0f, 1.0f, 0.0f, 1.0f,
182 0.0f, 0.0f, 1.0f, 1.0f
183 };
184
185 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
186 glClear(GL_COLOR_BUFFER_BIT);
187
188 glUseProgram(program);
189 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
190 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
191 glEnableVertexAttribArray(0);
192 glEnableVertexAttribArray(1);
193 glDrawArrays(GL_TRIANGLES, 0, 3);
194
195 usleep(1e6 / 120); /* 120 Hz */
196 glFinish();
197
198 unsigned char pixels[4];
199 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530200 printf("color = %hhu %hhu %hhu %hhu\n",
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800201 pixels[0], pixels[1], pixels[2], pixels[3]);
202 }
203
204 glDeleteProgram(program);
205}
206
207int main(int argc, char ** argv)
208{
209 int ret = 0;
210 struct context ctx;
211 EGLint egl_major, egl_minor;
212 const char * extensions;
213 EGLint num_configs;
214 EGLConfig egl_config;
215
216 ctx.width = 800;
217 ctx.height = 600;
218
219 const EGLint config_attribs[] = {
220 EGL_RED_SIZE, 1,
221 EGL_GREEN_SIZE, 1,
222 EGL_BLUE_SIZE, 1,
223 EGL_DEPTH_SIZE, 1,
224 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
225 EGL_NONE
226 };
227 const EGLint context_attribs[] = {
228 EGL_CONTEXT_CLIENT_VERSION, 2,
229 EGL_NONE
230 };
231
232 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
233 if (ctx.egl_display == EGL_NO_DISPLAY) {
234 fprintf(stderr, "failed to get egl display\n");
235 ret = 1;
236 goto fail;
237 }
238
239 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
240 fprintf(stderr, "failed to initialize egl: %s\n",
241 get_egl_error());
242 ret = 1;
243 goto terminate_display;
244 }
245
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530246 printf("EGL %d.%d\n", egl_major, egl_minor);
247 printf("EGL %s\n",
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800248 eglQueryString(ctx.egl_display, EGL_VERSION));
249
250 extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530251 printf("EGL Extensions: %s\n", extensions);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800252
253 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0,
254 &num_configs)) {
255 fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
256 eglGetError());
257 goto terminate_display;
258 }
259 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1,
260 &num_configs)) {
261 fprintf(stderr, "eglChooseConfig() failed with error: %x\n",
262 eglGetError());
263 goto terminate_display;
264 }
265
266 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
267 fprintf(stderr, "failed to bind OpenGL ES: %s\n",
268 get_egl_error());
269 ret = 1;
270 goto terminate_display;
271 }
272
273 ctx.egl_ctx = eglCreateContext(ctx.egl_display,
274 NULL /* No framebuffer */,
275 EGL_NO_CONTEXT /* No shared context */,
276 context_attribs);
277 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
278 fprintf(stderr, "failed to create OpenGL ES Context: %s\n",
279 get_egl_error());
280 ret = 1;
281 goto terminate_display;
282 }
283
284 if (!eglMakeCurrent(ctx.egl_display,
285 EGL_NO_SURFACE /* No default draw surface */,
286 EGL_NO_SURFACE /* No default draw read */,
287 ctx.egl_ctx)) {
288 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
289 get_egl_error());
290 ret = 1;
291 goto destroy_context;
292 }
293
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530294 printf("GL extensions: %s\n", glGetString(GL_EXTENSIONS));
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800295
296 glGenFramebuffers(1, &ctx.gl_fb);
297 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb);
298 glGenRenderbuffers(1, &ctx.gl_rb);
299 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb);
300 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES,
301 ctx.width, ctx.height);
302 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
303 GL_RENDERBUFFER, ctx.gl_rb);
304
305 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
306 GL_FRAMEBUFFER_COMPLETE) {
307 fprintf(stderr, "failed to create framebuffer: %s\n",
308 get_gl_error());
309 ret = 1;
310 goto delete_gl_buffers;
311 }
312
313 draw(&ctx);
314
315delete_gl_buffers:
316 glBindRenderbuffer(GL_RENDERBUFFER, 0);
317 glBindFramebuffer(GL_FRAMEBUFFER, 0);
318 glDeleteFramebuffers(1, &ctx.gl_fb);
319 glDeleteRenderbuffers(1, &ctx.gl_rb);
320destroy_context:
321 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
322terminate_display:
323 eglTerminate(ctx.egl_display);
324fail:
325 return ret;
326}