Home | History | Annotate | Download | only in hwc
      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 
     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 
     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 
     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 
    112 int select_config_for_window(EGLDisplay dpy, EGLint *attr,
    113 	unsigned format, EGLConfig *config) {
    114 	EGLint R,G,B,A,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 
    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 
    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