#define USE_CAMERA
#include <GL/glew.h>
#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <cutil.h>
#include <cutil_gl_error.h>
#include <cuda_gl_interop.h>
#ifdef USE_CAMERA
#include <openvidia/openvidia32.h>
#else
#include <GL/glut.h>
#endif
using namespace std;
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
int width = 640;
int height = 480;
int texSize;
GLuint bufferObj;
GLuint texObj;
unsigned int *GPU_PBOPtr = NULL;
unsigned char *Img = NULL;
cudaArray *a_Src;
texture<uchar2, 2, cudaReadModeNormalizedFloat> texImage;
cudaChannelFormatDesc uchar2tex = cudaCreateChannelDesc<uchar2>();
#ifdef USE_CAMERA
V4L2 *CamSource;
#endif
void showstats() {
static int lasttime;
static int fpscounter;
static int fps;
int curtime;
curtime = time(NULL);
if( lasttime != curtime) {
fps=fpscounter;
fpscounter=1;
lasttime = curtime;
fprintf(stderr, "fps = %d, %f msecs\n",fps,1.0/((float)fps)*1000);
} else {
fpscounter++;
}
}
static GLenum errCode;
const GLubyte *errString;
void errcheck() {
if ((errCode = glGetError()) != GL_NO_ERROR) {
errString = gluErrorString(errCode);
fprintf (stderr, "OpenGL Error: %s\n", errString);
exit(1);
}
}
void reshape(int w, int h)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(0.0, 1.0, 0.0, 1.0, 1.0, 100.0);
gluLookAt(0.0,0.0,0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glutPostRedisplay();
}
void myIdle(){
glutPostRedisplay();
}
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 27:
cudaGLUnregisterBufferObject( bufferObj );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glDeleteBuffers(1, &bufferObj );
glDeleteTextures(1, &texObj );
cudaFreeArray( a_Src );
exit(0);
break;
default:
break;
}
}
void MouseFunc( int button, int state, int x, int y)
{
switch(button) {
case GLUT_LEFT_BUTTON :
break;
case GLUT_RIGHT_BUTTON :
break;
}
}
#define BLOCKDIM_X 8
#define BLOCKDIM_Y 8
__device__ unsigned int make_color(float r, float g, float b, float a){
return
((int)(r * 255.0f) << 24) |
((int)(r * 255.0f) << 16) |
((int)(r * 255.0f) << 8) |
((int)(r * 255.0f) << 0);
}
__device__ unsigned int make_luminance(float y){
return
((int)(y * 255.0f) << 24) |
((int)(y * 255.0f) << 16) |
((int)(y * 255.0f) << 8) |
((int)(y * 255.0f) << 0);
}
__device__ unsigned int make_rgb32(float y, float u, float v){
float l = 1.164 * ( y - 16.0f/255.0f );
float m = v - 0.5;
float n = u - 0.5;
float b = l + 2.018 * n;
float g = l - 0.813 * m - 0.391 * n;
float r = l + 1.596 * m;
r = min( r, 1.0);
g = min( g, 1.0);
b = min( b, 1.0);
r = max( r, 0.0);
g = max( g, 0.0);
b = max( b, 0.0);
return
((int)(1.0 * 255.0f) << 24) |
((int)(b * 255.0f) << 16) |
((int)(g * 255.0f) << 8) |
((int)(r * 255.0f) << 0);
}
__global__ void AddConst( unsigned int *dst, int imageW, int imageH )
{
const int ix = blockDim.x * blockIdx.x + threadIdx.x;
const int iy = blockDim.y * blockIdx.y + threadIdx.y;
//Add half of a texel to always address exact texel centers
const float x = (float)ix + 0.5f;
const float y = (float)iy + 0.5f;
if(ix < imageW && iy < imageH){
float2 fresultYU;
float2 fresultYV;
if( ix % 2 == 0 ) {
fresultYU = tex2D(texImage, x, y);
fresultYV = tex2D(texImage, x+1, y);
dst[imageW * iy + ix] = make_rgb32( fresultYU.x,
fresultYU.y,
fresultYV.y );
} else {
fresultYU = tex2D(texImage, x-1, y);
fresultYV = tex2D(texImage, x, y);
dst[imageW * iy + ix] = make_rgb32( fresultYV.x,
fresultYU.y,
fresultYV.y );
}
}
}
int iDivUp(int a, int b){
return ((a % b) != 0) ? (a / b + 1) : (a / b);
}
void render_redirect() {
float d = -1.0;
cudaMemcpyToArray(
a_Src, 0, 0,
CamSource->ptr(), width * height * sizeof(uchar2),
cudaMemcpyHostToDevice
);
cudaGLMapBufferObject( (void **)&GPU_PBOPtr, bufferObj );
cudaBindTextureToArray( texImage, a_Src );
dim3 threads(BLOCKDIM_X, BLOCKDIM_Y);
dim3 grid(iDivUp(width, BLOCKDIM_X), iDivUp(height, BLOCKDIM_Y));
AddConst<<<grid,threads>>>( GPU_PBOPtr, width, height );
cudaUnbindTexture(texImage);
cudaGLUnmapBufferObject( bufferObj );
glTexSubImage2D( GL_TEXTURE_RECTANGLE_NV, 0, 0, 0, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
glBegin(GL_QUADS);
glTexCoord2f(0, height);
glVertex3f(0.0, 0.0,d );
glTexCoord2f(0, 0);
glVertex3f(0.0, 1.0, d);
glTexCoord2f(width, 0);
glVertex3f(1.0,1.0, d);
glTexCoord2f(width,height);
glVertex3f(1.0, 0.0, d );
glEnd();
glutSwapBuffers();
showstats();
}
#ifdef USE_CAMERA
void init_camera() {
CamSource = new V4L2( 640, 480 );
}
#endif
unsigned char *makeImage( int w, int h, int n )
{
unsigned char *d;
cudaMallocHost((void **)&d, w*h*n);
unsigned char *p = d;
for( int i=0; i<h ; i++ ) {
for( int j=0; j<w ; j++ ) {
*p++ = 128;
*p++ = 228;
*p++ = 228;
*p++ = 228;
}
}
return d;
}
int main(int argc, char *argv[] ) {
cerr<<"Actual window created : "<<width<<"x"<<height<<endl;
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ALPHA );
glutInitWindowSize(width, height );
glutCreateWindow(argv[0]);
glewInit();
#ifdef USE_CAMERA
init_camera();
#endif
glutReshapeWindow( width, height );
Img = makeImage( width, height, 4 );
cerr<<" Making texture "<<endl;
glEnable(GL_TEXTURE_RECTANGLE_NV);
glGenTextures(1, &texObj);
glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA8, width,height, 0,
GL_RGBA, GL_UNSIGNED_BYTE,Img);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
cerr<<" PBO "<<endl;
texSize = width*height*4;
glGenBuffers( 1, &bufferObj ); errcheck();
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_EXT, bufferObj); errcheck();
glBufferData(GL_PIXEL_UNPACK_BUFFER_EXT, width*height*4, NULL, GL_STREAM_COPY); errcheck();
cerr<<"Registering buffer"<<endl;
cudaGLRegisterBufferObject( bufferObj );
cerr<<" PBO OK "<<endl;
cerr<<" CUDA array "<<endl;
cudaMallocArray(&a_Src, &uchar2tex, width, height) ;
cerr<<" malloc ok "<<endl;
cudaMemcpyToArray(
a_Src, 0, 0,
Img, width * height * sizeof(uchar2),
cudaMemcpyHostToDevice );
cerr<<"memcpy ok"<<endl;
cerr<<"array OK "<<endl;
fprintf(stderr, "any errors?: %s\n", cudaGetErrorString( cudaGetLastError() )) ;
cerr<<"register ok "<<endl;
errcheck();
glutDisplayFunc(render_redirect);
glutIdleFunc(myIdle);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMouseFunc(MouseFunc);
cerr<<" init ok"<<endl;
glutMainLoop();
return 0;
}