Hi
The complete code lools something like this
graphics.cpp
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h>
#include <iostream>
#include "bcm_host.h"
#include "graphics.h"
#define W_dst 1280
#define H_dst 720
#define check() assert(glGetError() == 0)
uint32_t GScreenWidth;
uint32_t GScreenHeight;
EGLDisplay GDisplay;
EGLSurface GSurface;
EGLContext GContext;
GfxShader GSimpleVS;
GfxShader GSimpleFS;
GfxShader GYUVFS;
GfxProgram GSimpleProg;
GfxProgram GYUVProg;
GLuint GQuadVertexBuffer;
void InitGraphics()
{
bcm_host_init();
int32_t success = 0;
EGLBoolean result;
EGLint num_config;
static EGL_DISPMANX_WINDOW_T nativewindow;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
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
};
static const EGLint context_attributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
EGLConfig config;
// get an EGL display connection
GDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert(GDisplay!=EGL_NO_DISPLAY);
check();
// initialize the EGL display connection
result = eglInitialize(GDisplay, NULL, NULL);
assert(EGL_FALSE != result);
check();
// get an appropriate EGL frame buffer configuration
result = eglChooseConfig(GDisplay, attribute_list, &config, 1, &num_config);
assert(EGL_FALSE != result);
check();
// get an appropriate EGL frame buffer configuration
result = eglBindAPI(EGL_OPENGL_ES_API);
assert(EGL_FALSE != result);
check();
// create an EGL rendering context
GContext = eglCreateContext(GDisplay, config, EGL_NO_CONTEXT, context_attributes);
assert(GContext!=EGL_NO_CONTEXT);
check();
// create an EGL window surface
success = graphics_get_display_size(0 /* LCD */, &GScreenWidth, &GScreenHeight);
assert( success >= 0 );
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = W_dst;
dst_rect.height = H_dst;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = W_dst ;
src_rect.height = H_dst;
dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
dispman_update = vc_dispmanx_update_start( 0 );
dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
0/*layer*/, &dst_rect, 0/*src*/,
&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, (DISPMANX_TRANSFORM_T)0/*transform*/);
nativewindow.element = dispman_element;
nativewindow.width = W_dst;
nativewindow.height = H_dst;
vc_dispmanx_update_submit_sync( dispman_update );
check();
GSurface = eglCreateWindowSurface( GDisplay, config, &nativewindow, NULL );
assert(GSurface != EGL_NO_SURFACE);
check();
// connect the context to the surface
result = eglMakeCurrent(GDisplay, GSurface, GSurface, GContext);
assert(EGL_FALSE != result);
check();
// Set background color and clear buffers
glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
glClear( GL_COLOR_BUFFER_BIT );
//load the test shaders
GSimpleVS.LoadVertexShader("shaders/simplevertshader.glsl");
GSimpleFS.LoadFragmentShader("shaders/simplefragshader.glsl");
GYUVFS.LoadFragmentShader("shaders/yuvfragshader.glsl");
GSimpleProg.Create(&GSimpleVS,&GSimpleFS);
GYUVProg.Create(&GSimpleVS,&GYUVFS);
check();
//create an ickle vertex buffer
static const GLfloat quad_vertex_positions[] = {
0.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
glGenBuffers(1, &GQuadVertexBuffer);
check();
glBindBuffer(GL_ARRAY_BUFFER, GQuadVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad_vertex_positions), quad_vertex_positions, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
check();
}
void BeginFrame()
{
// Prepare viewport
glViewport ( 0, 0, W_dst, H_dst );
check();
// Clear the background
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
check();
}
void EndFrame()
{
eglSwapBuffers(GDisplay,GSurface);
check();
}
void ReleaseGraphics()
{
}
// printShaderInfoLog
// From OpenGL Shading Language 3rd Edition, p215-216
// Display (hopefully) useful error messages if shader fails to compile
void printShaderInfoLog(GLint shader)
{
int infoLogLen = 0;
int charsWritten = 0;
GLchar *infoLog;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
if (infoLogLen > 0)
{
infoLog = new GLchar[infoLogLen];
// error check for fail to allocate memory omitted
glGetShaderInfoLog(shader, infoLogLen, &charsWritten, infoLog);
std::cout << "InfoLog : " << std::endl << infoLog << std::endl;
delete [] infoLog;
}
}
bool GfxShader::LoadVertexShader(const char* filename)
{
//cheeky bit of code to read the whole file into memory
assert(!Src);
FILE* f = fopen(filename, "rb");
assert(f);
fseek(f,0,SEEK_END);
int sz = ftell(f);
fseek(f,0,SEEK_SET);
Src = new GLchar[sz+1];
fread(Src,1,sz,f);
Src[sz] = 0; //null terminate it!
fclose(f);
//now create and compile the shader
GlShaderType = GL_VERTEX_SHADER;
Id = glCreateShader(GlShaderType);
glShaderSource(Id, 1, (const GLchar**)&Src, 0);
glCompileShader(Id);
check();
//compilation check
GLint compiled;
glGetShaderiv(Id, GL_COMPILE_STATUS, &compiled);
if(compiled==0)
{
printf("Failed to compile vertex shader %s:
%s
", filename, Src);
printShaderInfoLog(Id);
glDeleteShader(Id);
return false;
}
else
{
//printf("Compiled vertex shader %s:
%s
", filename, Src);
printf("Compiled vertex shader %s:
", filename);
}
return true;
}
bool GfxShader::LoadFragmentShader(const char* filename)
{
//cheeky bit of code to read the whole file into memory
assert(!Src);
FILE* f = fopen(filename, "rb");
assert(f);
fseek(f,0,SEEK_END);
int sz = ftell(f);
fseek(f,0,SEEK_SET);
Src = new GLchar[sz+1];
fread(Src,1,sz,f);
Src[sz] = 0; //null terminate it!
fclose(f);
//now create and compile the shader
GlShaderType = GL_FRAGMENT_SHADER;
Id = glCreateShader(GlShaderType);
glShaderSource(Id, 1, (const GLchar**)&Src, 0);
glCompileShader(Id);
check();
//compilation check
GLint compiled;
glGetShaderiv(Id, GL_COMPILE_STATUS, &compiled);
if(compiled==0)
{
printf("Failed to compile fragment shader %s:
%s
", filename, Src);
printShaderInfoLog(Id);
glDeleteShader(Id);
return false;
}
else
{
//printf("Compiled fragment shader %s:
%s
", filename, Src);
printf("Compiled fragment shader %s:
", filename);
}
return true;
}
bool GfxProgram::Create(GfxShader* vertex_shader, GfxShader* fragment_shader)
{
VertexShader = vertex_shader;
FragmentShader = fragment_shader;
Id = glCreateProgram();
glAttachShader(Id, VertexShader->GetId());
glAttachShader(Id, FragmentShader->GetId());
glLinkProgram(Id);
check();
printf("Created program id %d from vs %d and fs %d
", GetId(), VertexShader->GetId(), FragmentShader->GetId());
// Prints the information log for a program object
char log[1024];
glGetProgramInfoLog(Id,sizeof log,NULL,log);
printf("%d:program:
%s
", Id, log);
return true;
}
void DrawTextureRect(GfxTexture* texture, float x0, float y0, float x1, float y1)
{
glUseProgram(GSimpleProg.GetId());
check();
//float scale_mat[4]={x1-x0,y1-y0,y1-y0,x1-x0};
glUniform2f(glGetUniformLocation(GSimpleProg.GetId(),"offset"),x0,y0);
glUniform2f(glGetUniformLocation(GSimpleProg.GetId(),"scale"),x1-x0,y1-y0);
//glUniformMatrix2fv(glGetUniformLocation(GSimpleProg.GetId(),"scale"),1,false,scale_mat);
glUniform1i(glGetUniformLocation(GSimpleProg.GetId(),"tex"), 0);
check();
glBindBuffer(GL_ARRAY_BUFFER, GQuadVertexBuffer);
check();
glBindTexture(GL_TEXTURE_2D,texture->GetId());
check();
GLuint loc = glGetAttribLocation(GSimpleProg.GetId(),"vertex");
check();
glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 16, 0);
check();
glEnableVertexAttribArray(loc);
check();
glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 );
check();
glFinish();
check();
glFlush();
check();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void DrawTextureRect(GfxTexture* texture, float x0, float y0, float x1, float y1, GfxTexture* render_target)
{
if(render_target)
{
glBindFramebuffer(GL_FRAMEBUFFER,render_target->GetFramebufferId());
glViewport ( 0, 0, render_target->GetWidth(), render_target->GetHeight() );
check();
}
glUseProgram(GSimpleProg.GetId()); check();
glUniform2f(glGetUniformLocation(GSimpleProg.GetId(),"offset"),x0,y0);
glUniform2f(glGetUniformLocation(GSimpleProg.GetId(),"scale"),x1-x0,y1-y0);
glUniform1i(glGetUniformLocation(GSimpleProg.GetId(),"tex"), 0);
check();
glBindBuffer(GL_ARRAY_BUFFER, GQuadVertexBuffer); check();
glBindTexture(GL_TEXTURE_2D,texture->GetId()); check();
GLuint loc = glGetAttribLocation(GSimpleProg.GetId(),"vertex");
glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 16, 0); check();
glEnableVertexAttribArray(loc); check();
glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); check();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
if(render_target)
{
//glFinish(); check();
//glFlush(); check();
glBindFramebuffer(GL_FRAMEBUFFER,0);
glViewport ( 0, 0, W_dst, H_dst );
}
}
void DrawYUVTextureRect(GfxTexture* ytexture, GfxTexture* utexture, GfxTexture* vtexture, GfxTexture* render_target)
{
if(render_target)
{
glBindFramebuffer(GL_FRAMEBUFFER,render_target->GetFramebufferId());
glViewport ( 0, 0, render_target->GetWidth(), render_target->GetHeight() );
check();
}
glUseProgram(GYUVProg.GetId()); check();
glUniform2f(glGetUniformLocation(GYUVProg.GetId(),"offset"),-1,-1);
glUniform2f(glGetUniformLocation(GYUVProg.GetId(),"scale"),2,2);
glUniform1i(glGetUniformLocation(GYUVProg.GetId(),"tex0"), 0);
glUniform1i(glGetUniformLocation(GYUVProg.GetId(),"tex1"), 1);
glUniform1i(glGetUniformLocation(GYUVProg.GetId(),"tex2"), 2);
check();
glBindBuffer(GL_ARRAY_BUFFER, GQuadVertexBuffer); check();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,ytexture->GetId()); check();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D,utexture->GetId()); check();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D,vtexture->GetId()); check();
glActiveTexture(GL_TEXTURE0);
GLuint loc = glGetAttribLocation(GYUVProg.GetId(),"vertex");
glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 16, 0); check();
glEnableVertexAttribArray(loc); check();
glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); check();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
if(render_target)
{
//glFinish(); check();
//glFlush(); check();
glBindFramebuffer(GL_FRAMEBUFFER,0);
glViewport ( 0, 0, W_dst, H_dst );
}
}
bool GfxTexture::CreateRGBA(int width, int height, const void* data)
{
Width = width;
Height = height;
glGenTextures(1, &Id);
check();
glBindTexture(GL_TEXTURE_2D, Id);
check();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
check();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
check();
glBindTexture(GL_TEXTURE_2D, 0);
IsRGBA = true;
return true;
}
bool GfxTexture::CreateGreyScale(int width, int height, const void* data)
{
Width = width;
Height = height;
glGenTextures(1, &Id);
check();
glBindTexture(GL_TEXTURE_2D, Id);
check();
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, Width, Height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
check();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
check();
glBindTexture(GL_TEXTURE_2D, 0);
IsRGBA = false;
return true;
}
bool GfxTexture::GenerateFrameBuffer()
{
//Create a frame buffer that points to this texture
glGenFramebuffers(1,&FramebufferId);
check();
glBindFramebuffer(GL_FRAMEBUFFER,FramebufferId);
check();
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,Id,0);
check();
glBindFramebuffer(GL_FRAMEBUFFER,0);
check();
return true;
}
void GfxTexture::SetPixels(const void* data)
{
glBindTexture(GL_TEXTURE_2D, Id);
check();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Width, Height, IsRGBA ? GL_RGBA : GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
check();
glBindTexture(GL_TEXTURE_2D, 0);
check();
}
main.cpp
// <------------------------------------------------ Common Libraries ---------------------------------------------->
#include <stdio.h>
#include <unistd.h>
#include <curses.h>
#include <iostream>
#include <fstream>
// <------------------------------------------------ Camera Libraries ---------------------------------------------->
#include "camera.h"
#include "graphics.h"
// <------------------------------------------------ Eigen Libraries ---------------------------------------------->
#include <eigen3/Eigen/Dense>
// <------------------------------------------------ OpenCV Libraries ---------------------------------------------->
#include <opencv2/opencv.hpp>
// <------------------------------------------------ SO3 Functions ---------------------------------------------->
#include "so3.h"
// <------------------------------------------------ Include Namespaces ---------------------------------------------->
using namespace std;
using namespace cv;
using namespace Eigen;
// <------------------------------------------------ Camera Properties ---------------------------------------------->
#define MAIN_TEXTURE_WIDTH 1280
#define MAIN_TEXTURE_HEIGHT 720
#define W_img 1280
#define H_img 720
// <------------------------------------------------ Variables ---------------------------------------------->
// <-----------OpenGL Tex Variables ------------->
int frame_sz;
int ypitch, ysize, uvpitch, uvsize, upos, vpos;
float tdiff;
// <-----------Loop Variables------------->
int i=0,j=0;
int img_cnt=0;
// <------------------------------------------------ Main Function ---------------------------------------------->
int main(int argc, const char **argv)
{
// <------------------------------------------------ Initialize SO3 Functions ---------------------------------------------->
init_SO3();
// <------------------------------------------------ Initialize Camera and graphics ---------------------------------------------->
InitGraphics();
CCamera* cam = StartCamera(MAIN_TEXTURE_WIDTH, MAIN_TEXTURE_HEIGHT,10,1,false);
// <------------------------------------------------ Generate textures for image processing in OpenGL ---------------------------------------------->
GfxTexture ytexture,utexture,vtexture,tex, gray, hsv;
ytexture.CreateGreyScale(MAIN_TEXTURE_WIDTH,MAIN_TEXTURE_HEIGHT);
utexture.CreateGreyScale(MAIN_TEXTURE_WIDTH/2,MAIN_TEXTURE_HEIGHT/2);
vtexture.CreateGreyScale(MAIN_TEXTURE_WIDTH/2,MAIN_TEXTURE_HEIGHT/2);
tex.CreateRGBA(MAIN_TEXTURE_WIDTH/2,MAIN_TEXTURE_HEIGHT/2);
tex.GenerateFrameBuffer();
printf("Running frame loop
");
const void* frame_data;
const uint8_t* data;
// <------------------------------------------------ Run program till user presses ESC ---------------------------------------------->
while(img_cnt<300)
{
img_cnt++;
// <------------------------------------------------ Wait for new image to appear ---------------------------------------------->
while(!cam->BeginReadFrame(0,frame_data,frame_sz)) {};
// <----------------lock the chosen frame buffer, and copy it directly into the corresponding open gl texture ---------------->
{
data = (const uint8_t*)frame_data;
ypitch = MAIN_TEXTURE_WIDTH;
ysize = ypitch*MAIN_TEXTURE_HEIGHT;
uvpitch = MAIN_TEXTURE_WIDTH/2;
uvsize = uvpitch*MAIN_TEXTURE_HEIGHT/2;
upos = ysize;
vpos = upos+uvsize;
ytexture.SetPixels(data);
utexture.SetPixels(data+upos);
vtexture.SetPixels(data+vpos);
cam->EndReadFrame(0);
}
// <----------------Image Processing in GPU using OpenGL---------------->
BeginFrame();
DrawYUVTextureRect(&ytexture,&utexture,&vtexture,&tex);
DrawTextureRect(&tex,-1.f,-1.f,1.f,1.f,NULL);
EndFrame();
}
// <------------------------------------------------ Finish Program ---------------------------------------------->
StopCamera();
endwin();
}
Thanks
Chandra