2013-03-07 02:16:31 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include <EGL/egl.h>
|
|
|
|
#include <GLES2/gl2.h>
|
|
|
|
|
|
|
|
#include <system/graphics.h>
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
void matrix_init_ortho(GLfloat *m, float w, float h) {
|
|
|
|
m[0] = 2.0 / w;
|
|
|
|
m[1] = 0.0;
|
|
|
|
m[2] = 0.0;
|
|
|
|
m[3] = -1.0;
|
|
|
|
m[4] = 0.0;
|
|
|
|
m[5] = 2.0 / h;
|
|
|
|
m[6] = 0.0;
|
|
|
|
m[7] = -1.0;
|
|
|
|
m[8] = 0.0;
|
|
|
|
m[9] = 0.0;
|
2017-12-01 20:28:37 +01:00
|
|
|
m[10] = -1.0;
|
2013-03-07 02:16:31 +01:00
|
|
|
m[11] = 0.0;
|
|
|
|
m[12] = 0.0;
|
|
|
|
m[13] = 0.0;
|
|
|
|
m[14] = 0.0;
|
|
|
|
m[15] = 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GLuint load_shader(GLenum shaderType, const char *src) {
|
|
|
|
GLint status = 0, len = 0;
|
|
|
|
GLuint shader;
|
|
|
|
|
|
|
|
if (!(shader = glCreateShader(shaderType)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
glShaderSource(shader, 1, &src, NULL);
|
|
|
|
glCompileShader(shader);
|
|
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
|
|
|
|
|
|
if (status)
|
|
|
|
return shader;
|
|
|
|
|
|
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
|
|
|
|
if (len) {
|
|
|
|
char *msg = malloc(len);
|
|
|
|
if (msg) {
|
|
|
|
glGetShaderInfoLog(shader, len, NULL, msg);
|
|
|
|
msg[len-1] = 0;
|
|
|
|
fprintf(stderr, "error compiling shader:\n%s\n", msg);
|
|
|
|
free(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glDeleteShader(shader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLuint load_program(const char *vert_src, const char *frag_src) {
|
|
|
|
GLuint vert, frag, prog;
|
|
|
|
GLint status = 0, len = 0;
|
|
|
|
|
|
|
|
if (!(vert = load_shader(GL_VERTEX_SHADER, vert_src)))
|
|
|
|
return 0;
|
|
|
|
if (!(frag = load_shader(GL_FRAGMENT_SHADER, frag_src)))
|
|
|
|
goto fail_frag;
|
|
|
|
if (!(prog = glCreateProgram()))
|
|
|
|
goto fail_prog;
|
|
|
|
|
|
|
|
glAttachShader(prog, vert);
|
|
|
|
glAttachShader(prog, frag);
|
|
|
|
glLinkProgram(prog);
|
|
|
|
|
|
|
|
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
|
|
|
if (status)
|
|
|
|
return prog;
|
|
|
|
|
|
|
|
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
|
|
|
|
if (len) {
|
|
|
|
char *buf = (char*) malloc(len);
|
|
|
|
if (buf) {
|
|
|
|
glGetProgramInfoLog(prog, len, NULL, buf);
|
|
|
|
buf[len-1] = 0;
|
|
|
|
fprintf(stderr, "error linking program:\n%s\n", buf);
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
glDeleteProgram(prog);
|
|
|
|
fail_prog:
|
|
|
|
glDeleteShader(frag);
|
|
|
|
fail_frag:
|
|
|
|
glDeleteShader(vert);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int select_config_for_window(EGLDisplay dpy, EGLint *attr,
|
|
|
|
unsigned format, EGLConfig *config) {
|
2017-12-01 20:28:37 +01:00
|
|
|
EGLint R,G,B,A;
|
2013-03-07 02:16:31 +01:00
|
|
|
EGLint i, n, max;
|
|
|
|
EGLConfig *cfg;
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case HAL_PIXEL_FORMAT_RGBA_8888:
|
|
|
|
case HAL_PIXEL_FORMAT_BGRA_8888:
|
|
|
|
R = G = B = A = 8;
|
|
|
|
break;
|
|
|
|
case HAL_PIXEL_FORMAT_RGB_565:
|
|
|
|
R = 5; G = 6; B = 5; A = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "unknown fb pixel format %d\n", format);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eglGetConfigs(dpy, NULL, 0, &max) == EGL_FALSE) {
|
|
|
|
fprintf(stderr, "no EGL configurations available?!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg = (EGLConfig*) malloc(sizeof(EGLConfig) * max);
|
|
|
|
if (!cfg)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (eglChooseConfig(dpy, attr, cfg, max, &n) == EGL_FALSE) {
|
|
|
|
fprintf(stderr, "eglChooseConfig failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
EGLint r,g,b,a;
|
|
|
|
eglGetConfigAttrib(dpy, cfg[i], EGL_RED_SIZE, &r);
|
|
|
|
eglGetConfigAttrib(dpy, cfg[i], EGL_GREEN_SIZE, &g);
|
|
|
|
eglGetConfigAttrib(dpy, cfg[i], EGL_BLUE_SIZE, &b);
|
|
|
|
eglGetConfigAttrib(dpy, cfg[i], EGL_ALPHA_SIZE, &a);
|
|
|
|
if (r == R && g == G && b == B && a == A) {
|
|
|
|
*config = cfg[i];
|
|
|
|
free(cfg);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "cannot find matching config\n");
|
|
|
|
free(cfg);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct CNativeWindow *_cnw = 0;
|
|
|
|
|
|
|
|
int egl_create(EGLDisplay *_display, EGLSurface *_surface, int *_w, int *_h) {
|
|
|
|
EGLBoolean res;
|
|
|
|
EGLConfig config = { 0 };
|
|
|
|
EGLint context_attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
|
|
|
EGLint config_attrs[] = {
|
|
|
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
|
|
EGL_NONE };
|
|
|
|
EGLint major, minor;
|
|
|
|
EGLContext context;
|
|
|
|
EGLSurface surface;
|
|
|
|
EGLint w, h;
|
|
|
|
EGLDisplay display;
|
|
|
|
EGLNativeWindowType window;
|
|
|
|
unsigned width, height, format;
|
|
|
|
struct CNativeWindow *cnw;
|
|
|
|
|
|
|
|
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
|
|
if (display == EGL_NO_DISPLAY)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!(res = eglInitialize(display, &major, &minor)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
fprintf(stderr, "egl version: %d.%d\n", major, minor);
|
|
|
|
|
|
|
|
if ((cnw = cnw_create()) == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
cnw_info(cnw, &width, &height, &format);
|
|
|
|
window = (EGLNativeWindowType) cnw;
|
|
|
|
|
|
|
|
if ((res = select_config_for_window(display, config_attrs, format, &config)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
surface = eglCreateWindowSurface(display, config, window, NULL);
|
|
|
|
if (surface == EGL_NO_SURFACE)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attrs);
|
|
|
|
if (context == EGL_NO_CONTEXT)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (!(res = eglMakeCurrent(display, surface, surface, context)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
|
|
|
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
|
|
|
|
|
|
|
fprintf(stderr, "window: %d x %d\n", w, h);
|
|
|
|
|
|
|
|
*_display = display;
|
|
|
|
*_surface = surface;
|
|
|
|
*_w = w;
|
|
|
|
*_h = h;
|
|
|
|
|
|
|
|
_cnw = cnw;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
cnw_destroy(cnw);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void egl_destroy(EGLDisplay display, EGLSurface surface) {
|
|
|
|
if (_cnw) {
|
|
|
|
eglDestroySurface(display, surface);
|
|
|
|
eglTerminate(display);
|
|
|
|
cnw_destroy(_cnw);
|
|
|
|
_cnw = 0;
|
|
|
|
}
|
|
|
|
}
|