blob: 9cce1adc4a7e521ca663b1fd968eb9e9d8f061eb [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,
Gurchetan Singhfcac8002017-04-26 10:29:28 -0700231 EGL_SURFACE_TYPE,
232 EGL_DONT_CARE,
Gurchetan Singh90192282017-02-22 15:05:06 -0800233 EGL_NONE };
234 const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800235
236 ctx.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
237 if (ctx.egl_display == EGL_NO_DISPLAY) {
238 fprintf(stderr, "failed to get egl display\n");
239 ret = 1;
240 goto fail;
241 }
242
243 if (!eglInitialize(ctx.egl_display, &egl_major, &egl_minor)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800244 fprintf(stderr, "failed to initialize egl: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800245 ret = 1;
246 goto terminate_display;
247 }
248
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530249 printf("EGL %d.%d\n", egl_major, egl_minor);
Gurchetan Singh90192282017-02-22 15:05:06 -0800250 printf("EGL %s\n", eglQueryString(ctx.egl_display, EGL_VERSION));
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800251
252 extensions = eglQueryString(ctx.egl_display, EGL_EXTENSIONS);
Pratik Vishwakarma24020562016-12-12 14:18:04 +0530253 printf("EGL Extensions: %s\n", extensions);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800254
Gurchetan Singh90192282017-02-22 15:05:06 -0800255 if (!eglChooseConfig(ctx.egl_display, config_attribs, NULL, 0, &num_configs)) {
256 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800257 goto terminate_display;
258 }
Gurchetan Singh90192282017-02-22 15:05:06 -0800259 if (!eglChooseConfig(ctx.egl_display, config_attribs, &egl_config, 1, &num_configs)) {
260 fprintf(stderr, "eglChooseConfig() failed with error: %x\n", eglGetError());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800261 goto terminate_display;
262 }
263
264 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800265 fprintf(stderr, "failed to bind OpenGL ES: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800266 ret = 1;
267 goto terminate_display;
268 }
269
Gurchetan Singh9a1cf162017-03-07 14:19:06 -0800270 if (bs_egl_has_extension("EGL_KHR_no_config_context", extensions)) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800271 ctx.egl_ctx =
272 eglCreateContext(ctx.egl_display, NULL /* No Config */,
273 EGL_NO_CONTEXT /* No shared context */, context_attribs);
Gurchetan Singhfee57f02017-02-22 13:42:37 -0800274 } else {
Gurchetan Singh90192282017-02-22 15:05:06 -0800275 ctx.egl_ctx =
276 eglCreateContext(ctx.egl_display, egl_config,
277 EGL_NO_CONTEXT /* No shared context */, context_attribs);
Gurchetan Singhfee57f02017-02-22 13:42:37 -0800278 }
279
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800280 if (ctx.egl_ctx == EGL_NO_CONTEXT) {
Gurchetan Singh90192282017-02-22 15:05:06 -0800281 fprintf(stderr, "failed to create OpenGL ES Context: %s\n", get_egl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800282 ret = 1;
283 goto terminate_display;
284 }
285
Gurchetan Singh90192282017-02-22 15:05:06 -0800286 if (!eglMakeCurrent(ctx.egl_display, EGL_NO_SURFACE /* No default draw surface */,
287 EGL_NO_SURFACE /* No default draw read */, ctx.egl_ctx)) {
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800288 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);
Gurchetan Singh90192282017-02-22 15:05:06 -0800300 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, ctx.width, ctx.height);
301 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ctx.gl_rb);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800302
Gurchetan Singh90192282017-02-22 15:05:06 -0800303 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
304 fprintf(stderr, "failed to create framebuffer: %s\n", get_gl_error());
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800305 ret = 1;
306 goto delete_gl_buffers;
307 }
308
309 draw(&ctx);
310
311delete_gl_buffers:
312 glBindRenderbuffer(GL_RENDERBUFFER, 0);
313 glBindFramebuffer(GL_FRAMEBUFFER, 0);
314 glDeleteFramebuffers(1, &ctx.gl_fb);
315 glDeleteRenderbuffers(1, &ctx.gl_rb);
316destroy_context:
Gurchetan Singh5cd9c8b2017-03-09 10:42:01 -0800317 eglMakeCurrent(ctx.egl_display, NULL, NULL, NULL);
Zach Reiznere60ae5d2014-12-03 15:55:53 -0800318 eglDestroyContext(ctx.egl_display, ctx.egl_ctx);
319terminate_display:
320 eglTerminate(ctx.egl_display);
321fail:
322 return ret;
323}