raspberry pi port

This commit is contained in:
Dave
2013-03-04 22:28:03 +01:00
committed by notaz
parent 6a298de481
commit ffa573f880
15 changed files with 1218 additions and 32 deletions

44
raspberrypi/Makefile Normal file
View File

@@ -0,0 +1,44 @@
# gpSP makefile
# Gilead Kutnick - Exophase
# pandora port - notaz
# respberry pi - DPR
# Global definitions
CC = gcc
OBJS = rpi.o main.o cpu.o memory.o video.o input.o sound.o gui.o \
cheats.o zip.o arm_stub.o warm.o cpu_threaded.o\
gles_video.o video_blend.o
BIN = gpsp
# Platform specific definitions
VPATH += .. ../arm
CFLAGS += -DARM_ARCH -DRPI_BUILD -Wall
CFLAGS += -O3 -mfpu=vfp
CFLAGS += `sdl-config --cflags`
CFLAGS += -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
# expecting to have PATH set up to get correct sdl-config first
LIBS += `sdl-config --libs`
LIBS += -ldl -lpthread -lz
LIBS += -L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lrt
# Compilation:
all: $(BIN)
%.o: %.S
$(CC) $(CFLAGS) -c -o $@ $<
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
$(BIN): $(OBJS)
$(CC) $(OBJS) $(LIBS) -o $(BIN)
clean:
rm -f *.o $(BIN)

393
raspberrypi/gles_video.c Normal file
View File

@@ -0,0 +1,393 @@
#include "bcm_host.h"
#include "GLES/gl.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"
#include "GLES2/gl2.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
static uint32_t frame_width = 0;
static uint32_t frame_height = 0;
#define SHOW_ERROR gles_show_error();
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);
static const char* vertex_shader =
"uniform mat4 u_vp_matrix; \n"
"attribute vec4 a_position; \n"
"attribute vec2 a_texcoord; \n"
"varying mediump vec2 v_texcoord; \n"
"void main() \n"
"{ \n"
" v_texcoord = a_texcoord; \n"
" gl_Position = u_vp_matrix * a_position; \n"
"} \n";
static const char* fragment_shader =
"varying mediump vec2 v_texcoord; \n"
"uniform sampler2D u_texture; \n"
"void main() \n"
"{ \n"
" gl_FragColor = texture2D(u_texture, v_texcoord); \n"
"} \n";
/*
static const GLfloat vertices[] =
{
-0.5f, -0.5f, 0.0f,
+0.5f, -0.5f, 0.0f,
+0.5f, +0.5f, 0.0f,
-0.5f, +0.5f, 0.0f,
};
*/
static const GLfloat vertices[] =
{
-0.5f, -0.5f, 0.0f,
-0.5f, +0.5f, 0.0f,
+0.5f, +0.5f, 0.0f,
+0.5f, -0.5f, 0.0f,
};
#define TEX_WIDTH 1024
#define TEX_HEIGHT 512
static const GLfloat uvs[8];
static const GLushort indices[] =
{
0, 1, 2,
0, 2, 3,
};
static const int kVertexCount = 4;
static const int kIndexCount = 6;
void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
memset(matrix,0,sizeof(GLfloat)*8);
matrix[3]=max_v;
matrix[4]=max_u;
matrix[5]=max_v;
matrix[6]=max_u;
}
void gles_show_error()
{
GLenum error = GL_NO_ERROR;
error = glGetError();
if (GL_NO_ERROR != error)
printf("GL Error %x encountered!\n", error);
}
static GLuint CreateShader(GLenum type, const char *shader_src)
{
GLuint shader = glCreateShader(type);
if(!shader)
return 0;
// Load and compile the shader source
glShaderSource(shader, 1, &shader_src, NULL);
glCompileShader(shader);
// Check the compile status
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint info_len = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1)
{
char* info_log = (char *)malloc(sizeof(char) * info_len);
glGetShaderInfoLog(shader, info_len, NULL, info_log);
// TODO(dspringer): We could really use a logging API.
printf("Error compiling shader:\n%s\n", info_log);
free(info_log);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
{
GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
if(!vertex_shader)
return 0;
GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
if(!fragment_shader)
{
glDeleteShader(vertex_shader);
return 0;
}
GLuint program_object = glCreateProgram();
if(!program_object)
return 0;
glAttachShader(program_object, vertex_shader);
glAttachShader(program_object, fragment_shader);
// Link the program
glLinkProgram(program_object);
// Check the link status
GLint linked = 0;
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint info_len = 0;
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1)
{
char* info_log = (char *)malloc(info_len);
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
// TODO(dspringer): We could really use a logging API.
printf("Error linking program:\n%s\n", info_log);
free(info_log);
}
glDeleteProgram(program_object);
return 0;
}
// Delete these here because they are attached to the program object.
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program_object;
}
typedef struct ShaderInfo {
GLuint program;
GLint a_position;
GLint a_texcoord;
GLint u_vp_matrix;
GLint u_texture;
} ShaderInfo;
static ShaderInfo shader;
static ShaderInfo shader_filtering;
static GLuint buffers[3];
static GLuint textures[2];
static void gles2_create()
{
memset(&shader, 0, sizeof(ShaderInfo));
shader.program = CreateProgram(vertex_shader, fragment_shader);
if(shader.program)
{
shader.a_position = glGetAttribLocation(shader.program, "a_position");
shader.a_texcoord = glGetAttribLocation(shader.program, "a_texcoord");
shader.u_vp_matrix = glGetUniformLocation(shader.program, "u_vp_matrix");
shader.u_texture = glGetUniformLocation(shader.program, "u_texture");
}
glGenTextures(1, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
glGenBuffers(3, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
}
static uint32_t screen_width = 0;
static uint32_t screen_height = 0;
static EGLDisplay display = NULL;
static EGLSurface surface = NULL;
static EGLContext context = NULL;
static EGL_DISPMANX_WINDOW_T nativewindow;
static GLfloat proj[4][4];
static GLint filter_min;
static GLint filter_mag;
void video_set_filter(uint32_t filter) {
if (filter==0) {
filter_min = GL_NEAREST;
filter_mag = GL_NEAREST;
} else {
filter_min = GL_LINEAR;
filter_mag = GL_LINEAR;
}
}
void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
{
if ((_width==0)||(_height==0))
return;
frame_width = _width;
frame_height = _height;
//bcm_host_init();
// get an EGL display connection
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(display != EGL_NO_DISPLAY);
// initialize the EGL display connection
EGLBoolean result = eglInitialize(display, NULL, NULL);
assert(EGL_FALSE != result);
// get an appropriate EGL frame buffer configuration
EGLint num_config;
EGLConfig config;
static const EGLint attribute_list[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
assert(EGL_FALSE != result);
result = eglBindAPI(EGL_OPENGL_ES_API);
assert(EGL_FALSE != result);
// create an EGL rendering context
static const EGLint context_attributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
assert(context != EGL_NO_CONTEXT);
// create an EGL window surface
int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
assert(success >= 0);
VC_RECT_T dst_rect;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = screen_width;
dst_rect.height = screen_height;
VC_RECT_T src_rect;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = screen_width << 16;
src_rect.height = screen_height << 16;
DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
1, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
nativewindow.element = dispman_element;
nativewindow.width = screen_width;
nativewindow.height = screen_height;
vc_dispmanx_update_submit_sync(dispman_update);
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
assert(surface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(display, surface, surface, context);
assert(EGL_FALSE != result);
gles2_create();
int r=(screen_height*10/frame_height);
int h = (frame_height*r)/10;
int w = (frame_width*r)/10;
if (w>screen_width) {
r = (screen_width*10/frame_width);
h = (frame_height*r)/10;
w = (frame_width*r)/10;
}
glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
video_set_filter(filter);
}
static void gles2_destroy()
{
if(!shader.program)
return;
glDeleteBuffers(3, buffers); SHOW_ERROR
glDeleteProgram(shader.program); SHOW_ERROR
}
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)
{
memset(m, 0, 4*4*sizeof(GLfloat));
m[0][0] = 2.0f/(right - left)*scale_x;
m[1][1] = 2.0f/(top - bottom)*scale_y;
m[2][2] = -2.0f/(far - near);
m[3][0] = -(right + left)/(right - left);
m[3][1] = -(top + bottom)/(top - bottom);
m[3][2] = -(far + near)/(far - near);
m[3][3] = 1;
}
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
static void gles2_Draw( uint16_t *pixels)
{
if(!shader.program)
return;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader.program);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
glActiveTexture(GL_TEXTURE0);
glUniform1i(shader.u_texture, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
glGenerateMipmap(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(shader.a_position);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(shader.a_texcoord);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//glFlush();
}
void video_close()
{
gles2_destroy();
// Release OpenGL resources
eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
eglDestroySurface( display, surface );
eglDestroyContext( display, context );
eglTerminate( display );
}
void video_draw(uint16_t *pixels)
{
gles2_Draw (pixels);
eglSwapBuffers(display, surface);
}

4
raspberrypi/gles_video.h Normal file
View File

@@ -0,0 +1,4 @@
void video_init(uint32_t width,uint32_t height,uint32_t filter);
void video_close();
void video_draw(uint16_t *pixels);

33
raspberrypi/keys.txt Normal file
View File

@@ -0,0 +1,33 @@
gpsp raspberry pi
CONTROL KEYS
============
KEYBOARD
---------
Up Up Arrow
Down Down Arrow
Left Left Arrow
Right Right Arrow
A Z
B X
Start Enter
Select Backspace
L A
R S
Exit Esc
Menu F10
GAMEPAD
-------
Up XAsix -
Down XAsix +
Left YAsix -
Right YAsix +
A Button 1
B Button 2
Start Button 3
Select Button 4
L Button 5
R Button 6

111
raspberrypi/rpi.c Normal file
View File

@@ -0,0 +1,111 @@
/* gameplaySP - raspberry backend
*
* Copyright (C) 2013 DPR <pribyl.email@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../common.h"
#include <sys/types.h>
#include <sys/stat.h>
#include "gles_video.h"
#include "rpi.h"
#include "bcm_host.h"
u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
{
BUTTON_ID_UP, // Up
BUTTON_ID_LEFT, // Left
BUTTON_ID_DOWN, // Down
BUTTON_ID_RIGHT, // Right
BUTTON_ID_START, // Start
BUTTON_ID_SELECT, // Select
BUTTON_ID_L, // Ltrigger
BUTTON_ID_R, // Rtrigger
BUTTON_ID_FPS, // A
BUTTON_ID_A, // B
BUTTON_ID_B, // X
BUTTON_ID_MENU, // Y
BUTTON_ID_SAVESTATE, // 1
BUTTON_ID_LOADSTATE, // 2
BUTTON_ID_FASTFORWARD, // 3
BUTTON_ID_NONE, // 4
BUTTON_ID_MENU // Space
};
#define MAX_VIDEO_MEM (480*270*2)
static int video_started=0;
static uint16_t * video_buff;
void gpsp_plat_init(void)
{
int ret, w, h, fd;
//const char *layer_fb_name;
SDL_Surface* myVideoSurface;
bcm_host_init();
ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
if (ret != 0) {
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
exit(1);
}
myVideoSurface = SDL_SetVideoMode( 0, 0, 16, SDL_SWSURFACE);
// Print out some information about the video surface
if (myVideoSurface == NULL) {
fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
exit(1);
}
SDL_ShowCursor(0);
fb_set_mode(240, 160, 0, 0, 0, 0);
screen_scale = 3;
}
void gpsp_plat_quit(void)
{
if (video_started) {
video_close();
free(video_buff);
video_started=0;
}
SDL_Quit();
}
void *fb_flip_screen(void)
{
video_draw(video_buff);
return video_buff;
}
void fb_wait_vsync(void)
{
}
void fb_set_mode(int w, int h, int buffers, int scale,int filter, int filter2)
{
if (video_started) {
video_close();
free(video_buff);
}
video_buff=malloc(w*h*sizeof(uint16_t));
memset(video_buff,0,w*h*sizeof(uint16_t));
video_init(w,h,filter);
video_started=1;
}
// vim:shiftwidth=2:expandtab

9
raspberrypi/rpi.h Normal file
View File

@@ -0,0 +1,9 @@
void gpsp_plat_init(void);
void gpsp_plat_quit(void);
#define PLAT_BUTTON_COUNT 17
extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
void *fb_flip_screen(void);
void fb_set_mode(int w, int h, int buffers, int scale, int filter, int filter2);
void fb_wait_vsync(void);

30
raspberrypi/test/Makefile Normal file
View File

@@ -0,0 +1,30 @@
# glestest makefile
# Global definitions
CC = gcc
OBJS = gles_video.o test.o
BIN = glestest
# Platform specific definitions
CFLAGS+=-D_LINUX
LIBS +=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt
INCLUDES+=-I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
# Compilation:
all: $(BIN)
%.o: %.c
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
$(BIN): $(OBJS)
$(CC) $(OBJS) $(LIBS) -o $(BIN)
clean:
rm -f *.o $(BIN)

View File

@@ -0,0 +1,383 @@
#include "bcm_host.h"
#include "GLES/gl.h"
#include "EGL/egl.h"
#include "EGL/eglext.h"
#include "GLES2/gl2.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
static uint32_t frame_width = 0;
static uint32_t frame_height = 0;
#define SHOW_ERROR gles_show_error();
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);
static const char* vertex_shader =
"uniform mat4 u_vp_matrix; \n"
"attribute vec4 a_position; \n"
"attribute vec2 a_texcoord; \n"
"varying mediump vec2 v_texcoord; \n"
"void main() \n"
"{ \n"
" v_texcoord = a_texcoord; \n"
" gl_Position = u_vp_matrix * a_position; \n"
"} \n";
static const char* fragment_shader =
"varying mediump vec2 v_texcoord; \n"
"uniform sampler2D u_texture; \n"
"void main() \n"
"{ \n"
" gl_FragColor = texture2D(u_texture, v_texcoord); \n"
"} \n";
static const GLfloat vertices[] =
{
-0.5f, -0.5f, 0.0f,
+0.5f, -0.5f, 0.0f,
+0.5f, +0.5f, 0.0f,
-0.5f, +0.5f, 0.0f,
};
#define TEX_WIDTH 1024
#define TEX_HEIGHT 512
static const GLfloat uvs[8];
static const GLushort indices[] =
{
0, 1, 2,
0, 2, 3,
};
static const int kVertexCount = 4;
static const int kIndexCount = 6;
void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
memset(matrix,0,sizeof(GLfloat)*8);
matrix[3]=max_v;
matrix[4]=max_u;
matrix[5]=max_v;
matrix[6]=max_u;
}
void gles_show_error()
{
GLenum error = GL_NO_ERROR;
error = glGetError();
if (GL_NO_ERROR != error)
printf("GL Error %x encountered!\n", error);
}
static GLuint CreateShader(GLenum type, const char *shader_src)
{
GLuint shader = glCreateShader(type);
if(!shader)
return 0;
// Load and compile the shader source
glShaderSource(shader, 1, &shader_src, NULL);
glCompileShader(shader);
// Check the compile status
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint info_len = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1)
{
char* info_log = (char *)malloc(sizeof(char) * info_len);
glGetShaderInfoLog(shader, info_len, NULL, info_log);
// TODO(dspringer): We could really use a logging API.
printf("Error compiling shader:\n%s\n", info_log);
free(info_log);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
{
GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
if(!vertex_shader)
return 0;
GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
if(!fragment_shader)
{
glDeleteShader(vertex_shader);
return 0;
}
GLuint program_object = glCreateProgram();
if(!program_object)
return 0;
glAttachShader(program_object, vertex_shader);
glAttachShader(program_object, fragment_shader);
// Link the program
glLinkProgram(program_object);
// Check the link status
GLint linked = 0;
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint info_len = 0;
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1)
{
char* info_log = (char *)malloc(info_len);
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
// TODO(dspringer): We could really use a logging API.
printf("Error linking program:\n%s\n", info_log);
free(info_log);
}
glDeleteProgram(program_object);
return 0;
}
// Delete these here because they are attached to the program object.
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program_object;
}
typedef struct ShaderInfo {
GLuint program;
GLint a_position;
GLint a_texcoord;
GLint u_vp_matrix;
GLint u_texture;
} ShaderInfo;
static ShaderInfo shader;
static ShaderInfo shader_filtering;
static GLuint buffers[3];
static GLuint textures[2];
static void gles2_create()
{
memset(&shader, 0, sizeof(ShaderInfo));
shader.program = CreateProgram(vertex_shader, fragment_shader);
if(shader.program)
{
shader.a_position = glGetAttribLocation(shader.program, "a_position");
shader.a_texcoord = glGetAttribLocation(shader.program, "a_texcoord");
shader.u_vp_matrix = glGetUniformLocation(shader.program, "u_vp_matrix");
shader.u_texture = glGetUniformLocation(shader.program, "u_texture");
}
glGenTextures(1, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
glGenBuffers(3, buffers);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_DITHER);
}
static uint32_t screen_width = 0;
static uint32_t screen_height = 0;
static EGLDisplay display = NULL;
static EGLSurface surface = NULL;
static EGLContext context = NULL;
static EGL_DISPMANX_WINDOW_T nativewindow;
static GLfloat proj[4][4];
static GLint filter_min;
static GLint filter_mag;
void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
{
if ((_width==0)||(_height==0))
return;
frame_width = _width;
frame_height = _height;
bcm_host_init();
// get an EGL display connection
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(display != EGL_NO_DISPLAY);
// initialize the EGL display connection
EGLBoolean result = eglInitialize(display, NULL, NULL);
assert(EGL_FALSE != result);
// get an appropriate EGL frame buffer configuration
EGLint num_config;
EGLConfig config;
static const EGLint attribute_list[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
assert(EGL_FALSE != result);
result = eglBindAPI(EGL_OPENGL_ES_API);
assert(EGL_FALSE != result);
// create an EGL rendering context
static const EGLint context_attributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
assert(context != EGL_NO_CONTEXT);
// create an EGL window surface
int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
assert(success >= 0);
VC_RECT_T dst_rect;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = screen_width;
dst_rect.height = screen_height;
VC_RECT_T src_rect;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = screen_width << 16;
src_rect.height = screen_height << 16;
DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
nativewindow.element = dispman_element;
nativewindow.width = screen_width;
nativewindow.height = screen_height;
vc_dispmanx_update_submit_sync(dispman_update);
surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
assert(surface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(display, surface, surface, context);
assert(EGL_FALSE != result);
gles2_create();
int r=(screen_height*10/frame_height);
int h = (frame_height*r)/10;
int w = (frame_width*r)/10;
glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
if (filter==0) {
filter_min = GL_NEAREST;
filter_mag = GL_NEAREST;
} else if (filter==1) {
filter_min = GL_LINEAR_MIPMAP_LINEAR;
filter_mag = GL_LINEAR;
} else if (filter==2) {
filter_min = GL_LINEAR_MIPMAP_NEAREST;
filter_mag = GL_LINEAR;
}
}
static void gles2_destroy()
{
if(!shader.program)
return;
glDeleteBuffers(3, buffers); SHOW_ERROR
glDeleteProgram(shader.program); SHOW_ERROR
}
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)
{
memset(m, 0, 4*4*sizeof(GLfloat));
m[0][0] = 2.0f/(right - left)*scale_x;
m[1][1] = 2.0f/(top - bottom)*scale_y;
m[2][2] = -2.0f/(far - near);
m[3][0] = -(right + left)/(right - left);
m[3][1] = -(top + bottom)/(top - bottom);
m[3][2] = -(far + near)/(far - near);
m[3][3] = 1;
}
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
static void gles2_Draw( uint16_t *pixels)
{
if(!shader.program)
return;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader.program);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
glActiveTexture(GL_TEXTURE0);
glUniform1i(shader.u_texture, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
glGenerateMipmap(GL_TEXTURE_2D);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(shader.a_position);
glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(shader.a_texcoord);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//glFlush();
}
void video_close()
{
gles2_destroy();
// Release OpenGL resources
eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
eglDestroySurface( display, surface );
eglDestroyContext( display, context );
eglTerminate( display );
}
void video_draw(uint16_t *pixels)
{
gles2_Draw (pixels);
eglSwapBuffers(display, surface);
}

48
raspberrypi/test/test.c Normal file
View File

@@ -0,0 +1,48 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#define RGB15(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
void video_init(uint32_t width,uint32_t height, uint32_t f);
void video_close();
void video_draw(uint16_t *pixels);
void showbitmap( uint32_t wd, uint32_t ht, uint32_t f) {
int index;
uint16_t j,k;
uint8_t r,g,b;
uint16_t * bitmap;
bitmap=malloc(wd*ht*sizeof(uint16_t));
b=16;
index=0;
for (j=0;j<ht;j++) {
r=(j*31)/(ht-1);
for (k=0; k<wd ; k++) {
g=(k*31)/(wd-1);
bitmap[index++]=RGB15(r,g,b);
}
}
bitmap[0]=0;
video_init(wd,ht,f);
video_draw(bitmap);
sleep(5);
video_close();
free(bitmap);
}
int main(void) {
showbitmap( 320, 240,0);
showbitmap( 320, 240,1);
showbitmap( 320, 240,2);
showbitmap( 240, 160,0);
showbitmap( 400, 272,0);
return 0;
}