1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20
21 #include <EGL/egl.h>
22 #include <GLES2/gl2.h>
23
24 #include <system/graphics.h>
25
26 #include "util.h"
27
matrix_init_ortho(GLfloat * m,float w,float h)28 void matrix_init_ortho(GLfloat *m, float w, float h) {
29 m[0] = 2.0 / w;
30 m[1] = 0.0;
31 m[2] = 0.0;
32 m[3] = -1.0;
33 m[4] = 0.0;
34 m[5] = 2.0 / h;
35 m[6] = 0.0;
36 m[7] = -1.0;
37 m[8] = 0.0;
38 m[9] = 0.0;
39 m[10] = -1.0;
40 m[11] = 0.0;
41 m[12] = 0.0;
42 m[13] = 0.0;
43 m[14] = 0.0;
44 m[15] = 1.0;
45 }
46
load_shader(GLenum shaderType,const char * src)47 static GLuint load_shader(GLenum shaderType, const char *src) {
48 GLint status = 0, len = 0;
49 GLuint shader;
50
51 if (!(shader = glCreateShader(shaderType)))
52 return 0;
53
54 glShaderSource(shader, 1, &src, NULL);
55 glCompileShader(shader);
56 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
57
58 if (status)
59 return shader;
60
61 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
62 if (len) {
63 char *msg = malloc(len);
64 if (msg) {
65 glGetShaderInfoLog(shader, len, NULL, msg);
66 msg[len-1] = 0;
67 fprintf(stderr, "error compiling shader:\n%s\n", msg);
68 free(msg);
69 }
70 }
71 glDeleteShader(shader);
72 return 0;
73 }
74
load_program(const char * vert_src,const char * frag_src)75 GLuint load_program(const char *vert_src, const char *frag_src) {
76 GLuint vert, frag, prog;
77 GLint status = 0, len = 0;
78
79 if (!(vert = load_shader(GL_VERTEX_SHADER, vert_src)))
80 return 0;
81 if (!(frag = load_shader(GL_FRAGMENT_SHADER, frag_src)))
82 goto fail_frag;
83 if (!(prog = glCreateProgram()))
84 goto fail_prog;
85
86 glAttachShader(prog, vert);
87 glAttachShader(prog, frag);
88 glLinkProgram(prog);
89
90 glGetProgramiv(prog, GL_LINK_STATUS, &status);
91 if (status)
92 return prog;
93
94 glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
95 if (len) {
96 char *buf = (char*) malloc(len);
97 if (buf) {
98 glGetProgramInfoLog(prog, len, NULL, buf);
99 buf[len-1] = 0;
100 fprintf(stderr, "error linking program:\n%s\n", buf);
101 free(buf);
102 }
103 }
104 glDeleteProgram(prog);
105 fail_prog:
106 glDeleteShader(frag);
107 fail_frag:
108 glDeleteShader(vert);
109 return 0;
110 }
111
select_config_for_window(EGLDisplay dpy,EGLint * attr,unsigned format,EGLConfig * config)112 int select_config_for_window(EGLDisplay dpy, EGLint *attr,
113 unsigned format, EGLConfig *config) {
114 EGLint R,G,B,A;
115 EGLint i, n, max;
116 EGLConfig *cfg;
117
118 switch (format) {
119 case HAL_PIXEL_FORMAT_RGBA_8888:
120 case HAL_PIXEL_FORMAT_BGRA_8888:
121 R = G = B = A = 8;
122 break;
123 case HAL_PIXEL_FORMAT_RGB_565:
124 R = 5; G = 6; B = 5; A = 0;
125 break;
126 default:
127 fprintf(stderr, "unknown fb pixel format %d\n", format);
128 return -1;
129 }
130
131 if (eglGetConfigs(dpy, NULL, 0, &max) == EGL_FALSE) {
132 fprintf(stderr, "no EGL configurations available?!\n");
133 return -1;
134 }
135
136 cfg = (EGLConfig*) malloc(sizeof(EGLConfig) * max);
137 if (!cfg)
138 return -1;
139
140 if (eglChooseConfig(dpy, attr, cfg, max, &n) == EGL_FALSE) {
141 fprintf(stderr, "eglChooseConfig failed\n");
142 return -1;
143 }
144
145 for (i = 0; i < n; i++) {
146 EGLint r,g,b,a;
147 eglGetConfigAttrib(dpy, cfg[i], EGL_RED_SIZE, &r);
148 eglGetConfigAttrib(dpy, cfg[i], EGL_GREEN_SIZE, &g);
149 eglGetConfigAttrib(dpy, cfg[i], EGL_BLUE_SIZE, &b);
150 eglGetConfigAttrib(dpy, cfg[i], EGL_ALPHA_SIZE, &a);
151 if (r == R && g == G && b == B && a == A) {
152 *config = cfg[i];
153 free(cfg);
154 return 0;
155 }
156 }
157
158 fprintf(stderr, "cannot find matching config\n");
159 free(cfg);
160 return -1;
161 }
162
163 static struct CNativeWindow *_cnw = 0;
164
egl_create(EGLDisplay * _display,EGLSurface * _surface,int * _w,int * _h)165 int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h) {
166 EGLBoolean res;
167 EGLConfig config = { 0 };
168 EGLint context_attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
169 EGLint config_attrs[] = {
170 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
171 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
172 EGL_NONE };
173 EGLint major, minor;
174 EGLContext context;
175 EGLSurface surface;
176 EGLint w, h;
177 EGLDisplay display;
178 EGLNativeWindowType window;
179 unsigned width, height, format;
180 struct CNativeWindow *cnw;
181
182 display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
183 if (display == EGL_NO_DISPLAY)
184 return -1;
185
186 if (!(res = eglInitialize(display, &major, &minor)))
187 return -1;
188
189 fprintf(stderr, "egl version: %d.%d\n", major, minor);
190
191 if ((cnw = cnw_create()) == 0)
192 return -1;
193
194 cnw_info(cnw, &width, &height, &format);
195 window = (EGLNativeWindowType) cnw;
196
197 if ((res = select_config_for_window(display, config_attrs, format, &config)))
198 goto fail;
199
200 surface = eglCreateWindowSurface(display, config, window, NULL);
201 if (surface == EGL_NO_SURFACE)
202 goto fail;
203
204 context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs);
205 if (context == EGL_NO_CONTEXT)
206 goto fail;
207
208 if (!(res = eglMakeCurrent(display, surface, surface, context)))
209 goto fail;
210
211 eglQuerySurface(display, surface, EGL_WIDTH, &w);
212 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
213
214 fprintf(stderr, "window: %d x %d\n", w, h);
215
216 *_display = display;
217 *_surface = surface;
218 *_w = w;
219 *_h = h;
220
221 _cnw = cnw;
222 return 0;
223
224 fail:
225 cnw_destroy(cnw);
226 return -1;
227 }
228
egl_destroy(EGLDisplay display,EGLSurface surface)229 void egl_destroy(EGLDisplay display, EGLSurface surface) {
230 if (_cnw) {
231 eglDestroySurface(display, surface);
232 eglTerminate(display);
233 cnw_destroy(_cnw);
234 _cnw = 0;
235 }
236 }
237