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