blob: 4917d4d1c317e9964c8604e1bd11b362721ea42a [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
Gurchetan Singhfee57f02017-02-22 13:42:37 -08006#include "bs_drm.h"
Zach Reiznere60ae5d2014-12-03 15:55:53 -08007
Gurchetan Singh90192282017-02-22 15:05:06 -08008const char *get_gl_error()
Zach Reiznere60ae5d2014-12-03 15:55:53 -08009{
10 switch (glGetError()) {
Gurchetan Singh90192282017-02-22 15:05:06 -080011 case GL_NO_ERROR:
12 return "No error has been recorded.";
13 case GL_INVALID_ENUM:
14 return "An unacceptable value is specified for an enumerated argument. The "
15 "offending command is ignored and has no other side effect than to "
16 "set the error flag.";
17 case GL_INVALID_VALUE:
18 return "A numeric argument is out of range. The offending command is "
19 "ignored and has no other side effect than to set the error flag.";
20 case GL_INVALID_OPERATION:
21 return "The specified operation is not allowed in the current state. The "
22 "offending command is ignored and has no other side effect than to "
23 "set the error flag.";
24 case GL_INVALID_FRAMEBUFFER_OPERATION:
25 return "The command is trying to render to or read from the framebuffer "
26 "while the currently bound framebuffer is not framebuffer complete "
27 "(i.e. the return value from glCheckFramebufferStatus is not "
28 "GL_FRAMEBUFFER_COMPLETE). The offending command is ignored and has "
29 "no other side effect than to set the error flag.";
30 case GL_OUT_OF_MEMORY:
31 return "There is not enough memory left to execute the command. The state "
32 "of the GL is undefined, except for the state of the error flags, "
33 "after this error is recorded.";
34 default:
35 return "Unknown error";
Zach Reiznere60ae5d2014-12-03 15:55:53 -080036 }
37}
38
Gurchetan Singh90192282017-02-22 15:05:06 -080039const char *get_egl_error()
Zach Reiznere60ae5d2014-12-03 15:55:53 -080040{
41 switch (eglGetError()) {
Gurchetan Singh90192282017-02-22 15:05:06 -080042 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 "
46 "specified EGL display connection.";
47 case EGL_BAD_ACCESS:
48 return "EGL cannot access a requested resource (for example a context is "
49 "bound in another thread).";
50 case EGL_BAD_ALLOC:
51 return "EGL failed to allocate resources for the requested operation.";
52 case EGL_BAD_ATTRIBUTE:
53 return "An unrecognized attribute or attribute value was passed in the "
54 "attribute list.";
55 case EGL_BAD_CONTEXT:
56 return "An EGLContext argument does not name a valid EGL rendering "
57 "context.";
58 case EGL_BAD_CONFIG:
59 return "An EGLConfig argument does not name a valid EGL frame buffer "
60 "configuration.";
61 case EGL_BAD_CURRENT_SURFACE:
62 return "The current surface of the calling thread is a window, pixel "
63 "buffer or pixmap that is no longer valid.";
64 case EGL_BAD_DISPLAY:
65 return "An EGLDisplay argument does not name a valid EGL display "
66 "connection.";
67 case EGL_BAD_SURFACE:
68 return "An EGLSurface argument does not name a valid surface (window, "
69 "pixel buffer or pixmap) configured for GL rendering.";
70 case EGL_BAD_MATCH:
71 return "Arguments are inconsistent (for example, a valid context requires "
72 "buffers not supplied by a valid surface).";
73 case EGL_BAD_PARAMETER:
74 return "One or more argument values are invalid.";
75 case EGL_BAD_NATIVE_PIXMAP:
76 return "A NativePixmapType argument does not refer to a valid native "
77 "pixmap.";
78 case EGL_BAD_NATIVE_WINDOW:
79 return "A NativeWindowType argument does not refer to a valid native "
80 "window.";
81 case EGL_CONTEXT_LOST:
82 return "A power management event has occurred. The application must "
83 "destroy all contexts and reinitialise OpenGL ES state and objects "
84 "to continue rendering.";
85 default:
86 return "Unknown error";
Zach Reiznere60ae5d2014-12-03 15:55:53 -080087 }
88}
89
90struct context {
91 unsigned width;
92 unsigned height;
93 EGLDisplay egl_display;
94 EGLContext egl_ctx;
95
96 unsigned gl_fb;
97 unsigned gl_rb;
Zach Reiznere60ae5d2014-12-03 15:55:53 -080098};
99
Gurchetan Singh90192282017-02-22 15:05:06 -0800100float f(int i)
101{
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800102 int a = i % 40;
103 int b = (i / 40) % 6;
104 switch (b) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800105 case 0:
106 case 1:
107 return 0.0f;
108 case 3:
109 case 4:
110 return 1.0f;
111 case 2:
112 return (a / 40.0f);
113 case 5:
114 return 1.0f - (a / 40.0f);
115 default:
116 return 0.0f;
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800117 }
118}
119
Gurchetan Singh90192282017-02-22 15:05:06 -0800120void draw(struct context *ctx)
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800121{
122 int i;
123 const GLchar *vertexShaderStr =
Gurchetan Singh90192282017-02-22 15:05:06 -0800124 "attribute vec4 vPosition;\n"
125 "attribute vec4 vColor;\n"
126 "varying vec4 vFillColor;\n"
127 "void main() {\n"
128 " gl_Position = vPosition;\n"
129 " vFillColor = vColor;\n"
130 "}\n";
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800131 const GLchar *fragmentShaderStr =
Gurchetan Singh90192282017-02-22 15:05:06 -0800132 "precision mediump float;\n"
133 "varying vec4 vFillColor;\n"
134 "void main() {\n"
135 " gl_FragColor = vFillColor;\n"
136 "}\n";
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800137 GLint vertexShader, fragmentShader, program, status;
138
139 vertexShader = glCreateShader(GL_VERTEX_SHADER);
140 if (!vertexShader) {
141 fprintf(stderr, "Failed to create vertex shader. Error=0x%x\n", glGetError());
142 return;
143 }
144 glShaderSource(vertexShader, 1, &vertexShaderStr, NULL);
145 glCompileShader(vertexShader);
146 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
147 if (!status) {
148 fprintf(stderr, "Failed to compile vertex shader. Error=0x%x\n", glGetError());
149 return;
150 }
151
152 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
153 if (!fragmentShader) {
154 fprintf(stderr, "Failed to create fragment shader. Error=0x%x\n", glGetError());
155 return;
156 }
157 glShaderSource(fragmentShader, 1, &fragmentShaderStr, NULL);
158 glCompileShader(fragmentShader);
159 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
160 if (!status) {
161 fprintf(stderr, "Failed to compile fragment shader. Error=0x%x\n", glGetError());
162 return;
163 }
164
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800165 program = glCreateProgram();
166 if (!program) {
167 fprintf(stderr, "Failed to create program.\n");
168 return;
169 }
170 glAttachShader(program, vertexShader);
171 glAttachShader(program, fragmentShader);
172 glBindAttribLocation(program, 0, "vPosition");
173 glBindAttribLocation(program, 1, "vColor");
174 glLinkProgram(program);
175 glGetShaderiv(program, GL_LINK_STATUS, &status);
176 if (!status) {
177 fprintf(stderr, "Failed to link program.\n");
178 return;
179 }
180
Gurchetan Singh90192282017-02-22 15:05:06 -0800181 glViewport(0, 0, (GLint)ctx->width, (GLint)ctx->height);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800182
183 for (i = 0; i <= 500; i++) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800184 GLfloat verts[] = { 0.0f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 0.0f };
185 GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
186 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f };
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800187
188 glClearColor(f(i), f(i + 80), f(i + 160), 0.0f);
189 glClear(GL_COLOR_BUFFER_BIT);
190
191 glUseProgram(program);
192 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, verts);
193 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
194 glEnableVertexAttribArray(0);
195 glEnableVertexAttribArray(1);
196 glDrawArrays(GL_TRIANGLES, 0, 3);
197
198 usleep(1e6 / 120); /* 120 Hz */
199 glFinish();
200
201 unsigned char pixels[4];
202 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
Gurchetan Singh90192282017-02-22 15:05:06 -0800203 printf("color = %hhu %hhu %hhu %hhu\n", pixels[0], pixels[1], pixels[2], pixels[3]);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800204 }
205
206 glDeleteProgram(program);
207}
208
Gurchetan Singh90192282017-02-22 15:05:06 -0800209int main(int argc, char **argv)
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800210{
211 int ret = 0;
212 struct context ctx;
213 EGLint egl_major, egl_minor;
Gurchetan Singh90192282017-02-22 15:05:06 -0800214 const char *extensions;
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800215 EGLint num_configs;
216 EGLConfig egl_config;
217
218 ctx.width = 800;
219 ctx.height = 600;
220
Gurchetan Singh90192282017-02-22 15:05:06 -0800221 const EGLint config_attribs[] = { EGL_RED_SIZE,
222 1,
223 EGL_GREEN_SIZE,
224 1,
225 EGL_BLUE_SIZE,
226 1,
227 EGL_DEPTH_SIZE,
228 1,
229 EGL_RENDERABLE_TYPE,
230 EGL_OPENGL_ES2_BIT,
231 EGL_NONE };
232 const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800233
234 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
235 if (ctx.egl_display == EGL_NO_DISPLAY) {
236 fprintf(stderr, "failed to get egl display\n");
237 ret = 1;
238 goto fail;
239 }
240
241 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800242 fprintf(stderr, "failed to initialize egl: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800243 ret = 1;
244 goto terminate_display;
245 }
246
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530247 printf("EGL %d.%d\n", egl_major, egl_minor);
Gurchetan Singh90192282017-02-22 15:05:06 -0800248 printf("EGL %s\n", eglQueryString(ctx.egl_display, EGL_VERSION));
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800249
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
Gurchetan Singh90192282017-02-22 15:05:06 -0800253 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0, &num_configs)) {
254 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800255 goto terminate_display;
256 }
Gurchetan Singh90192282017-02-22 15:05:06 -0800257 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1, &num_configs)) {
258 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800259 goto terminate_display;
260 }
261
262 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800263 fprintf(stderr, "failed to bind OpenGL ES: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800264 ret = 1;
265 goto terminate_display;
266 }
267
Gurchetan Singh9a1cf162017-03-07 14:19:06 -0800268 if (bs_egl_has_extension("EGL_KHR_no_config_context", extensions)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800269 ctx.egl_ctx =
270 eglCreateContext(ctx.egl_display, NULL /* No Config */,
271 EGL_NO_CONTEXT /* No shared context */, context_attribs);
Gurchetan Singhfee57f02017-02-22 13:42:37 -0800272 } else {
Gurchetan Singh90192282017-02-22 15:05:06 -0800273 ctx.egl_ctx =
274 eglCreateContext(ctx.egl_display, egl_config,
275 EGL_NO_CONTEXT /* No shared context */, context_attribs);
Gurchetan Singhfee57f02017-02-22 13:42:37 -0800276 }
277
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800278 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800279 fprintf(stderr, "failed to create OpenGL ES Context: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800280 ret = 1;
281 goto terminate_display;
282 }
283
Gurchetan Singh90192282017-02-22 15:05:06 -0800284 if (!eglMakeCurrent(ctx.egl_display, EGL_NO_SURFACE /* No default draw surface */,
285 EGL_NO_SURFACE /* No default draw read */, ctx.egl_ctx)) {
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800286 fprintf(stderr, "failed to make the OpenGL ES Context current: %s\n",
287 get_egl_error());
288 ret = 1;
289 goto destroy_context;
290 }
291
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530292 printf("GL extensions: %s\n", glGetString(GL_EXTENSIONS));
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800293
294 glGenFramebuffers(1, &ctx.gl_fb);
295 glBindFramebuffer(GL_FRAMEBUFFER, ctx.gl_fb);
296 glGenRenderbuffers(1, &ctx.gl_rb);
297 glBindRenderbuffer(GL_RENDERBUFFER, ctx.gl_rb);
Gurchetan Singh90192282017-02-22 15:05:06 -0800298 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, ctx.width, ctx.height);
299 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ctx.gl_rb);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800300
Gurchetan Singh90192282017-02-22 15:05:06 -0800301 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
302 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800303 ret = 1;
304 goto delete_gl_buffers;
305 }
306
307 draw(&ctx);
308
309delete_gl_buffers:
310 glBindRenderbuffer(GL_RENDERBUFFER, 0);
311 glBindFramebuffer(GL_FRAMEBUFFER, 0);
312 glDeleteFramebuffers(1, &ctx.gl_fb);
313 glDeleteRenderbuffers(1, &ctx.gl_rb);
314destroy_context:
315 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
316terminate_display:
317 eglTerminate(ctx.egl_display);
318fail:
319 return ret;
320}