그래픽 & 멀티미디어
이번 시간부터 리눅스 그래픽 라이브러리 gx를 만들어 가도록 하겠습니다. 혹, 좋은 아이디어나 지적 사항이 있으시면 말씀 주시고, 그래픽 라이브러리를 위한 참고 자료를 알려 주신다면 감사하겠습니다.
gx 라이브러리 기본 구조
함수 및 변수 명명법
gx 라이브러리(이하 gx) 에서의 함수명은 모두 gx_ 로 시작합니다. 변수는 gx_ 접두사 사용을 원칙으로 하지만 특성에 따라, 또는 사용 편의에 따라 다른 접두사를 사용할 수 있습니다.
Device Context 개념
gx는 그래픽 함수를 다양하게 사용할 수 있도록 Device Context, 그래픽 출력의 기본 단위 개념을 사용하려 합니다.
이렇게 하는 이유는 점이나 도형 그리기 함수를 화면뿐만 아니라 이미지나 가상 그래픽 장치에도 같은 방법으로 사용할 수 있기 때문입니다.
자세한 내용은 가상 그래픽 장치를 소개할 때 말씀을 올리겠습니다.
함수 포인터 사용
gx는 다양한 칼라 깊이에서 사용될 수 있도록 하려 합니다. 이렇게 환경에 따라 칼라 값을 계산하는 것부터 화면에 출력하는 방법까지 모두 지원해야 해야 합니다.
이것을 하나의 함수로 구현한다는 것은 너무 어렵고, 함수 실행만 느려지게할 뿐입니다.
이와 같은 요구와 문제를 해결하기 위해 칼라 깊이에 관계된 함수를 포인터 함수로 선언하고, 그래픽 함수를 초기화하는 루틴에서 해상도에 따라 포인터 함수를 지정 하도록 하겠습니다.
즉,
switch( bits_per_pixel) { 15 : gx_color = gx15_color; gx_clear = gx15_clear; gx_dot = gx15_dot; 32 : gx_color = gx32_color; gx_clear = gx32_clear; gx_dot = gx32_dot; default : gx_color = gx16_color; gx_clear = gx16_clear; gx_dot = gx16_dot; }이와 같이 라이브러리를 초기화할 때, 그래픽 환경에 맞추어 함수를 설정해 놓으면, 이후로는 칼라 깊이가 다르더라도 같은 함수로 처리가 가능합니다.
gx.h
#ifndef _GX_H_ #define _GX_H_ #define GXERR_NONE 0 // 에러 없음 #define GXERR_NO_DEVICE -1 // 장치가 없음 #define GXERR_ACCESS_DEVICE -2 // 접근 권한이 없음 #define GXERR_VSCREENINFO -3 #define GXERR_FSCREENINFO -4 #define GXERR_MEMORYMAPPING -5 #define clr_clear 0x8000000 #define clr_black 0x00 extern int clr_white; extern int clr_magenta; extern int clr_green; extern int clr_olive; extern int clr_navy; extern int clr_purple; extern int clr_teal; extern int clr_gray; extern int clr_silver; extern int clr_red; extern int clr_lime; extern int clr_yellow; extern int clr_blue; extern int clr_fuchsia; extern int clr_aqua; typedef struct rgb_bit_t_ rgb_bit_t; struct rgb_bit_t_ { int offset; int bit_value; }; typedef struct framebuffer_t_ framebuffer_t; struct framebuffer_t_ { int fd; // 프레임 버퍼에 대한 파일 디스크립터 int size; // 메모리 전체 크기 rgb_bit_t red; rgb_bit_t green; rgb_bit_t blue; unsigned short *mapped; // 메모리 매핑된 포인터 }; typedef struct dc_t_ dc_t; struct dc_t_ { int width; int height; int size; int coor_x; int coor_y; int pen_color; int brush_color; unsigned short *mapped; // 메모리 매핑된 포인터 }; extern framebuffer_t gxfb; extern dc_t dc_screen; extern int gx_init( char *dev_name); extern void gx_close( void); extern int (*gx_color)( int red, int green, int blue); extern void (*gx_clear)( dc_t *dc, int color); extern void (*gx_dot )( dc_t *dc, int coor_x, int coor_y, int color); #endif
gx.c
#include#include #include // abs #include // open/close #include // O_RDWR #include // ioctl #include // mmap PROT_ #include #include #include int clr_white; // 자주 사용하는 칼라 변수 int clr_magenta; int clr_green; int clr_olive; int clr_navy; int clr_purple; int clr_teal; int clr_gray; int clr_silver; int clr_red; int clr_lime; int clr_yellow; int clr_blue; int clr_fuchsia; int clr_aqua; framebuffer_t gx_fb; dc_t dc_screen; int (*gx_color)( int red, int green, int blue); void (*gx_clear)( dc_t *dc, int color); void (*gx_dot )( dc_t *dc, int coor_x, int coor_y, int color); //-------------------------------------------------------------------- // 설명: 그래픽 라이브러리 종료 // 참고: 메모리 매핑 포인터와 프레임 버퍼 디스크립터를 소멸하고, // 변수를 초기화 한다. //-------------------------------------------------------------------- void gx_close( void) { if ( 0 <= gx_fb.mapped) // 메모리가 메핑 되어 있다면 { munmap( gx_fb.mapped, gx_fb.size); // 메모리 메핑 자원 반환 gx_fb.mapped = MAP_FAILED; } if ( 0 <= gx_fb.fd) // 파일 디스크립터가 만들어 졌다면 { close( gx_fb.fd); // 파일 디스크립터 자원 반환 gx_fb.fd = -1; } } //-------------------------------------------------------------------- // 설명: 그래픽 라이브러리를 초기화 // 인수: dev_name 장치 이름 // 반환: 0 = 에러 없음 // 0 > 에러 발생 //-------------------------------------------------------------------- int gx_init( char *dev_name) { struct fb_var_screeninfo fbvar; struct fb_fix_screeninfo fbfix; int bits_per_pixel; int bytes_per_line; gx_fb.fd = -1; // 초기값을 대입 gx_fb.mapped = MAP_FAILED; // 초기값을 대입 if ( access( dev_name, F_OK)) return GXERR_NO_DEVICE; if ( 0 > ( gx_fb.fd = open( dev_name, O_RDWR)) ) return GXERR_ACCESS_DEVICE; if ( ioctl( gx_fb.fd, FBIOGET_VSCREENINFO, &fbvar)) { gx_close(); return GXERR_VSCREENINFO; } if ( ioctl( gx_fb.fd, FBIOGET_FSCREENINFO, &fbfix)) { gx_close(); return GXERR_FSCREENINFO; } dc_screen.width = fbvar.xres; // 스크린의 픽셀 폭 dc_screen.height = fbvar.yres; // 스크린의 픽셀 높이 dc_screen.size = dc_screen.width * dc_screen.height; // 스크린 도트 개수 bits_per_pixel = fbvar.bits_per_pixel; bytes_per_line = fbfix.line_length; // 한개 라인 당 바이트 개수 gx_fb.size = bytes_per_line * dc_screen.height; gx_fb.mapped = ( unsigned short *)mmap( 0, gx_fb.size, PROT_READ|PROT_WRITE, MAP_SHARED, gx_fb.fd, 0); if ( 0 > gx_fb.mapped) { gx_close(); return GXERR_MEMORYMAPPING; } dc_screen.mapped = gx_fb.mapped; switch( bits_per_pixel) { default : gx_color = gx16_color; gx_clear = gx16_clear; gx_dot = gx16_dot; } // 자주 사용하는 칼라 값을 생성 clr_white = gx_color( 255, 255, 255); clr_magenta = gx_color( 128, 0, 0); clr_green = gx_color( 0, 128, 0); clr_olive = gx_color( 128, 128, 0); clr_navy = gx_color( 0, 0, 128); clr_purple = gx_color( 128, 0, 128); clr_teal = gx_color( 0, 128, 128); clr_gray = gx_color( 128, 128, 128); clr_silver = gx_color( 192, 192, 192); clr_red = gx_color( 255, 0, 0); clr_lime = gx_color( 0, 255, 0); clr_yellow = gx_color( 255, 255, 0); clr_blue = gx_color( 0, 0, 255); clr_fuchsia = gx_color( 255, 0, 255); clr_aqua = gx_color( 0, 255, 255); return GXERR_NONE; }
sample.c
sample.c 는 라이브러리의 사용 예를 보여 줍니다.
- gx_init( "/dev/fb") 로 그래픽 라이브러리를 초기화하고,
- 자동으로 생성된 화면 출력용 Device Context 인 dc_screen을 이용하여 그래픽을 출려합니다.
int main( void) { switch( gx_init( "/dev/fb") ) { case GXERR_NO_DEVICE : printf( "프레임 버퍼 장치가 없습니다.n" ); return -1; case GXERR_ACCESS_DEVICE : printf( "프레임 버퍼 장치 접근 권한이 없습니다.n" ); return -1; case GXERR_VSCREENINFO : printf( "FBIOGET_VSCREENINFO를 실행하지 못했습니다.n"); return -1; case GXERR_FSCREENINFO : printf( "FBIOGET_FSCREENINFO를 실행하지 못했습니다.n"); return -1; case GXERR_MEMORYMAPPING : printf( "메모리 메핑을 못했습니다.n" ); return -1; default : test(); } gx_close(); return 0; }
에러없이 gx_init()가 완료되었다면 dc_screen을 이용하여 그래픽을 출력합니다.
gx_clear( &dc_screen, clr_black); gx_dot( &dc_screen, ndx, ndx, clr_yellow);
gx_clear()는 인수로 받은 Device Context에 대해 전체를 지정한 색으로 칠하고, gx_dot()는 인수로 받은 색으로 점을 찍습니다.
실행하게되면 아래와 같이 출력됩니다.
태그: *그래픽 *라이브러리 *그래픽라이브러리