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