▶ cpu_bitmap.h
#ifndef __CPU_BITMAP_H__
#define __CPU_BITMAP_H__ #include "gl_helper.h" struct CPUBitmap
{
unsigned char *pixels;
int x, y;
void *dataBlock;
void (*bitmapExit)(void*); CPUBitmap( int width, int height, void *d = NULL )
{
pixels = new unsigned char[width * height * ];
x = width;
y = height;
dataBlock = d;
} ~CPUBitmap()
{
delete [] pixels;
} unsigned char* get_ptr( void ) const { return pixels; }
long image_size( void ) const { return x * y * ; } void display_and_exit( void(*e)(void*) = NULL )
{
CPUBitmap** bitmap = get_bitmap_ptr();
*bitmap = this;
bitmapExit = e;
// a bug in the Windows GLUT implementation prevents us from
// passing zero arguments to glutInit()
int c=;
char* dummy = "";
glutInit( &c, &dummy );
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGBA );
glutInitWindowSize( x, y );
glutCreateWindow( "bitmap" );
glutKeyboardFunc(Key);
glutDisplayFunc(Draw);
glutMainLoop();
} // static method used for glut callbacks
static CPUBitmap** get_bitmap_ptr( void )
{
static CPUBitmap *gBitmap;
return &gBitmap;
} // static method used for glut callbacks
static void Key(unsigned char key, int x, int y)
{
switch (key)
{
case :
CPUBitmap* bitmap = *(get_bitmap_ptr());
if (bitmap->dataBlock != NULL && bitmap->bitmapExit != NULL)
bitmap->bitmapExit( bitmap->dataBlock );
exit();
}
} // static method used for glut callbacks
static void Draw( void )
{
CPUBitmap* bitmap = *(get_bitmap_ptr());
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glDrawPixels( bitmap->x, bitmap->y, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->pixels );
glFlush();
}
}; #endif // __CPU_BITMAP_H__
▶ cpu_anim.h
#ifndef __CPU_ANIM_H__
#define __CPU_ANIM_H__ #include "D:\Code\CUDA\book\common\gl_helper.h"
#include <iostream> struct CPUAnimBitmap
{
unsigned char *pixels;
int width, height;
void *dataBlock;
void (*fAnim)(void*,int);
void (*animExit)(void*);
void (*clickDrag)(void*,int,int,int,int);
int dragStartX, dragStartY; CPUAnimBitmap( int w, int h, void *d = NULL )
{
width = w;
height = h;
pixels = new unsigned char[width * height * ];
dataBlock = d;
clickDrag = NULL;
} ~CPUAnimBitmap()
{
delete [] pixels;
} unsigned char* get_ptr( void ) const { return pixels; }
long image_size( void ) const { return width * height * ; } void click_drag(void(*f)(void*, int, int, int, int))
{
clickDrag = f;
} void anim_and_exit(void(*f)(void*, int), void(*e)(void*))
{
CPUAnimBitmap** bitmap = get_bitmap_ptr();
*bitmap = this;
fAnim = f;
animExit = e;
// a bug in the Windows GLUT implementation prevents us from
// passing zero arguments to glutInit()
int c=;
char* dummy = "";
glutInit( &c, &dummy );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize( width, height );
glutCreateWindow( "bitmap" );
glutKeyboardFunc(Key);
glutDisplayFunc(Draw);
if (clickDrag != NULL)
glutMouseFunc( mouse_func );
glutIdleFunc( idle_func );
glutMainLoop();
} // static method used for glut callbacks
static CPUAnimBitmap** get_bitmap_ptr(void)
{
static CPUAnimBitmap* gBitmap;
return &gBitmap;
} // static method used for glut callbacks
static void mouse_func(int button, int state, int mx, int my)
{
if (button == GLUT_LEFT_BUTTON)
{
CPUAnimBitmap* bitmap = *(get_bitmap_ptr());
if (state == GLUT_DOWN)
{
bitmap->dragStartX = mx;
bitmap->dragStartY = my;
}
else if (state == GLUT_UP)
bitmap->clickDrag( bitmap->dataBlock,bitmap->dragStartX,bitmap->dragStartY,mx, my );
}
} // static method used for glut callbacks
static void idle_func( void )
{
static int ticks = ;
CPUAnimBitmap* bitmap = *(get_bitmap_ptr());
bitmap->fAnim( bitmap->dataBlock, ticks++ );
glutPostRedisplay();
} // static method used for glut callbacks
static void Key(unsigned char key, int x, int y)
{
switch (key)
{
case :
CPUAnimBitmap* bitmap = *(get_bitmap_ptr());
bitmap->animExit( bitmap->dataBlock );
//delete bitmap;
exit();
}
} // static method used for glut callbacks
static void Draw( void )
{
CPUAnimBitmap* bitmap = *(get_bitmap_ptr());
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glDrawPixels( bitmap->width, bitmap->height, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->pixels );
glutSwapBuffers();
}
}; #endif // __CPU_ANIM_H__
▶ gpu_anim.h
#ifndef __GPU_ANIM_H__
#define __GPU_ANIM_H__
#include "D:\Code\CUDA\book\common\gl_helper.h"
#include "cuda.h"
#include "cuda_gl_interop.h"
#include <iostream> PFNGLBINDBUFFERARBPROC glBindBuffer = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers = NULL;
PFNGLGENBUFFERSARBPROC glGenBuffers = NULL;
PFNGLBUFFERDATAARBPROC glBufferData = NULL; struct GPUAnimBitmap
{
GLuint bufferObj;
cudaGraphicsResource *resource;
int width, height;
void *dataBlock;
void (*fAnim)(uchar4*,void*,int);
void (*animExit)(void*);
void (*clickDrag)(void*,int,int,int,int);
int dragStartX, dragStartY; GPUAnimBitmap( int w, int h, void *d = NULL )
{
width = w;
height = h;
dataBlock = d;
clickDrag = NULL; // first, find a CUDA device and set it to graphic interop
cudaDeviceProp prop;
int dev;
memset( &prop, , sizeof( cudaDeviceProp ) );
prop.major = ;
prop.minor = ;
cudaChooseDevice( &dev, &prop ) );
cudaGLSetGLDevice( dev ); // a bug in the Windows GLUT implementation prevents us from
// passing zero arguments to glutInit()
int c=;
char* dummy = "";
glutInit( &c, &dummy );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize( width, height );
glutCreateWindow( "bitmap" ); glBindBuffer = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
glGenBuffers = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
glBufferData = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData"); glGenBuffers( , &bufferObj );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj );
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * , NULL, GL_DYNAMIC_DRAW_ARB); cudaGraphicsGLRegisterBuffer(&resource, bufferObj, cudaGraphicsMapFlagsNone);
} ~GPUAnimBitmap()
{
free_resources();
} void free_resources( void )
{
cudaGraphicsUnregisterResource( resource ) );
glBindBuffer( GL_PIXEL_UNPACK_BUFFER_ARB, );
glDeleteBuffers( , &bufferObj );
} long image_size( void ) const { return width * height * ; } void click_drag(void(*f)(void*, int, int, int, int))
{
clickDrag = f;
} void anim_and_exit(void(*f)(uchar4*, void*, int), void(*e)(void*))
{
GPUAnimBitmap** bitmap = get_bitmap_ptr();
*bitmap = this;
fAnim = f;
animExit = e; glutKeyboardFunc( Key );
glutDisplayFunc( Draw );
if (clickDrag != NULL)
glutMouseFunc( mouse_func );
glutIdleFunc( idle_func );
glutMainLoop();
} // static method used for glut callbacks
static GPUAnimBitmap** get_bitmap_ptr( void )
{
static GPUAnimBitmap* gBitmap;
return &gBitmap;
} // static method used for glut callbacks
static void mouse_func( int button, int state,int mx, int my )
{
if (button == GLUT_LEFT_BUTTON)
{
GPUAnimBitmap* bitmap = *(get_bitmap_ptr());
if (state == GLUT_DOWN)
{
bitmap->dragStartX = mx;
bitmap->dragStartY = my;
}
else if (state == GLUT_UP)
bitmap->clickDrag(bitmap->dataBlock, bitmap->dragStartX, bitmap->dragStartY, mx, my);
}
} // static method used for glut callbacks
static void idle_func( void )
{
static int ticks = ;
GPUAnimBitmap* bitmap = *(get_bitmap_ptr());
uchar4* devPtr;
size_t size; cudaGraphicsMapResources(, &(bitmap->resource), NULL);
cudaGraphicsResourceGetMappedPointer((void**)&devPtr, &size, bitmap->resource); bitmap->fAnim(devPtr, bitmap->dataBlock, ticks++); cudaGraphicsUnmapResources(, &(bitmap->resource), NULL); glutPostRedisplay();
} // static method used for glut callbacks
static void Key(unsigned char key, int x, int y)
{
switch (key)
{
case :
GPUAnimBitmap* bitmap = *(get_bitmap_ptr();
if (bitmap->animExit)
bitmap->animExit( bitmap->dataBlock );
bitmap->free_resources();
exit();
}
} // static method used for glut callbacks
static void Draw( void )
{
GPUAnimBitmap* bitmap = *(get_bitmap_ptr();
glClearColor( 0.0, 0.0, 0.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glDrawPixels( bitmap->width, bitmap->height, GL_RGBA,
GL_UNSIGNED_BYTE, );
glutSwapBuffers();
}
}; #endif // __GPU_ANIM_H__
▶ gl_helper.h
#ifndef __GL_HELPER_H__
#define __GL_HELPER_H__ /*
On 64-bit Windows, we need to prevent GLUT from automatically linking against
glut32. We do this by defining GLUT_NO_LIB_PRAGMA. This means that we need to
manually add opengl32.lib and glut64.lib back to the link using pragmas.
Alternatively, this could be done on the compilation/link command-line, but
we chose this so that compilation is identical between 32- and 64-bit Windows.
*/
#ifdef _WIN64
#define GLUT_NO_LIB_PRAGMA
#pragma comment (lib, "opengl32.lib") /* link with Microsoft OpenGL lib */
#pragma comment (lib, "glut64.lib") /* link with Win64 GLUT lib */
#endif //_WIN64 #ifdef _WIN32
/* On Windows, include the local copy of glut.h and glext.h */
#include "GL/glut.h"
#include "GL/glext.h" #define GET_PROC_ADDRESS( str ) wglGetProcAddress( str ) #else /* On Linux, include the system's copy of glut.h, glext.h, and glx.h */
#include <GL/glut.h>
#include <GL/glext.h>
#include <GL/glx.h> #define GET_PROC_ADDRESS( str ) glXGetProcAddress( (const GLubyte *)str ) #endif //_WIN32 #endif //__GL_HELPER_H__'