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