4 #include "EGL/eglext.h"
11 static uint32_t frame_width = 0;
12 static uint32_t frame_height = 0;
15 #define SHOW_ERROR gles_show_error();
17 static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y);
19 static const char* vertex_shader =
20 "uniform mat4 u_vp_matrix; \n"
21 "attribute vec4 a_position; \n"
22 "attribute vec2 a_texcoord; \n"
23 "varying mediump vec2 v_texcoord; \n"
26 " v_texcoord = a_texcoord; \n"
27 " gl_Position = u_vp_matrix * a_position; \n"
30 static const char* fragment_shader =
31 "varying mediump vec2 v_texcoord; \n"
32 "uniform sampler2D u_texture; \n"
35 " gl_FragColor = texture2D(u_texture, v_texcoord); \n"
38 static const GLfloat vertices[] =
46 #define TEX_WIDTH 1024
47 #define TEX_HEIGHT 512
49 static const GLfloat uvs[8];
51 static const GLushort indices[] =
57 static const int kVertexCount = 4;
58 static const int kIndexCount = 6;
61 void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
62 memset(matrix,0,sizeof(GLfloat)*8);
70 void gles_show_error()
72 GLenum error = GL_NO_ERROR;
74 if (GL_NO_ERROR != error)
75 printf("GL Error %x encountered!\n", error);
78 static GLuint CreateShader(GLenum type, const char *shader_src)
80 GLuint shader = glCreateShader(type);
84 // Load and compile the shader source
85 glShaderSource(shader, 1, &shader_src, NULL);
86 glCompileShader(shader);
88 // Check the compile status
90 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
94 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
97 char* info_log = (char *)malloc(sizeof(char) * info_len);
98 glGetShaderInfoLog(shader, info_len, NULL, info_log);
99 // TODO(dspringer): We could really use a logging API.
100 printf("Error compiling shader:\n%s\n", info_log);
103 glDeleteShader(shader);
109 static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
111 GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
114 GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
117 glDeleteShader(vertex_shader);
121 GLuint program_object = glCreateProgram();
124 glAttachShader(program_object, vertex_shader);
125 glAttachShader(program_object, fragment_shader);
128 glLinkProgram(program_object);
130 // Check the link status
132 glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
136 glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
139 char* info_log = (char *)malloc(info_len);
140 glGetProgramInfoLog(program_object, info_len, NULL, info_log);
141 // TODO(dspringer): We could really use a logging API.
142 printf("Error linking program:\n%s\n", info_log);
145 glDeleteProgram(program_object);
148 // Delete these here because they are attached to the program object.
149 glDeleteShader(vertex_shader);
150 glDeleteShader(fragment_shader);
151 return program_object;
154 typedef struct ShaderInfo {
162 static ShaderInfo shader;
163 static ShaderInfo shader_filtering;
164 static GLuint buffers[3];
165 static GLuint textures[2];
168 static void gles2_create()
170 memset(&shader, 0, sizeof(ShaderInfo));
171 shader.program = CreateProgram(vertex_shader, fragment_shader);
174 shader.a_position = glGetAttribLocation(shader.program, "a_position");
175 shader.a_texcoord = glGetAttribLocation(shader.program, "a_texcoord");
176 shader.u_vp_matrix = glGetUniformLocation(shader.program, "u_vp_matrix");
177 shader.u_texture = glGetUniformLocation(shader.program, "u_texture");
179 glGenTextures(1, textures);
180 glBindTexture(GL_TEXTURE_2D, textures[0]);
181 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
183 Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
185 glGenBuffers(3, buffers);
186 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
187 glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
188 glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
189 glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
190 glBindBuffer(GL_ARRAY_BUFFER, 0);
191 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
192 glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
193 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
195 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
196 glDisable(GL_DEPTH_TEST);
198 glDisable(GL_DITHER);
201 static uint32_t screen_width = 0;
202 static uint32_t screen_height = 0;
204 static EGLDisplay display = NULL;
205 static EGLSurface surface = NULL;
206 static EGLContext context = NULL;
207 static EGL_DISPMANX_WINDOW_T nativewindow;
209 static GLfloat proj[4][4];
210 static GLint filter_min;
211 static GLint filter_mag;
213 void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
215 if ((_width==0)||(_height==0))
218 frame_width = _width;
219 frame_height = _height;
223 // get an EGL display connection
224 display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
225 assert(display != EGL_NO_DISPLAY);
227 // initialize the EGL display connection
228 EGLBoolean result = eglInitialize(display, NULL, NULL);
229 assert(EGL_FALSE != result);
231 // get an appropriate EGL frame buffer configuration
234 static const EGLint attribute_list[] =
240 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
243 result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
244 assert(EGL_FALSE != result);
246 result = eglBindAPI(EGL_OPENGL_ES_API);
247 assert(EGL_FALSE != result);
249 // create an EGL rendering context
250 static const EGLint context_attributes[] =
252 EGL_CONTEXT_CLIENT_VERSION, 2,
255 context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
256 assert(context != EGL_NO_CONTEXT);
258 // create an EGL window surface
259 int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
260 assert(success >= 0);
265 dst_rect.width = screen_width;
266 dst_rect.height = screen_height;
271 src_rect.width = screen_width << 16;
272 src_rect.height = screen_height << 16;
274 DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
275 DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
276 DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
277 0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
279 nativewindow.element = dispman_element;
280 nativewindow.width = screen_width;
281 nativewindow.height = screen_height;
282 vc_dispmanx_update_submit_sync(dispman_update);
284 surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
285 assert(surface != EGL_NO_SURFACE);
287 // connect the context to the surface
288 result = eglMakeCurrent(display, surface, surface, context);
289 assert(EGL_FALSE != result);
293 int r=(screen_height*10/frame_height);
294 int h = (frame_height*r)/10;
295 int w = (frame_width*r)/10;
297 glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
298 SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
300 filter_min = GL_NEAREST;
301 filter_mag = GL_NEAREST;
302 } else if (filter==1) {
303 filter_min = GL_LINEAR_MIPMAP_LINEAR;
304 filter_mag = GL_LINEAR;
305 } else if (filter==2) {
306 filter_min = GL_LINEAR_MIPMAP_NEAREST;
307 filter_mag = GL_LINEAR;
313 static void gles2_destroy()
317 glDeleteBuffers(3, buffers); SHOW_ERROR
318 glDeleteProgram(shader.program); SHOW_ERROR
321 static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y)
323 memset(m, 0, 4*4*sizeof(GLfloat));
324 m[0][0] = 2.0f/(right - left)*scale_x;
325 m[1][1] = 2.0f/(top - bottom)*scale_y;
326 m[2][2] = -2.0f/(far - near);
327 m[3][0] = -(right + left)/(right - left);
328 m[3][1] = -(top + bottom)/(top - bottom);
329 m[3][2] = -(far + near)/(far - near);
332 #define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
334 static void gles2_Draw( uint16_t *pixels)
339 glClear(GL_COLOR_BUFFER_BIT);
341 glUseProgram(shader.program);
343 glBindTexture(GL_TEXTURE_2D, textures[0]);
344 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
345 glActiveTexture(GL_TEXTURE0);
346 glUniform1i(shader.u_texture, 0);
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
350 glGenerateMipmap(GL_TEXTURE_2D);
352 glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
353 glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
354 glEnableVertexAttribArray(shader.a_position);
356 glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
357 glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
358 glEnableVertexAttribArray(shader.a_texcoord);
360 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
361 glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
362 glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
364 glBindBuffer(GL_ARRAY_BUFFER, 0);
365 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
372 // Release OpenGL resources
373 eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
374 eglDestroySurface( display, surface );
375 eglDestroyContext( display, context );
376 eglTerminate( display );
379 void video_draw(uint16_t *pixels)
382 eglSwapBuffers(display, surface);