⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplefb.c

📁 linux下的一些小游戏编程
💻 C
字号:
/* A simple framebuffer console example. */#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <asm/page.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <asm/page.h>#include <linux/fb.h>int main(int argc, char *argv[]){    char *fbname;    int fbdev;    struct fb_fix_screeninfo fixed_info;    struct fb_var_screeninfo var_info;    struct fb_cmap colormap;    u_int16_t r, g, b;    u_int8_t pixel_r = 0, pixel_g = 0, pixel_b = 0;    int x, y;    u_int32_t pixel_value;    void *framebuffer;    int framebuffer_size;    int ppc_fix;    /* Let the user specify an alternate framebuffer       device on the command line. Default to       /dev/fb0. */    if (argc >= 2)	fbname = argv[1];    else	fbname = "/dev/fb0";    printf("Using framebuffer device %s.\n", fbname);    /* Open the framebuffer device. */    fbdev = open(fbname, O_RDWR);    if (fbdev < 0) {	printf("Error opening %s.\n", fbname);	return 1;    }    /* Retrieve fixed screen info.       This is information that never changes for       this particular display. */    if (ioctl(fbdev, FBIOGET_FSCREENINFO, &fixed_info) < 0) {	printf("Unable to retrieve fixed screen info: %s\n",	       strerror(errno));	close(fbdev);	return 1;    }    /* Print out some of the fixed info. */    printf("Framebuffer ID:     %s\n", fixed_info.id);    printf("Framebuffer type:   ");    switch (fixed_info.type) {    case FB_TYPE_PACKED_PIXELS: printf("packed pixels\n"); break;    case FB_TYPE_PLANES: printf("planar (non-interleaved)\n"); break;    case FB_TYPE_INTERLEAVED_PLANES: printf("planar (interleaved)\n"); break;    case FB_TYPE_TEXT: printf("text (not a framebuffer)\n"); break;    case FB_TYPE_VGA_PLANES: printf("planar (EGA/VGA)\n"); break;    default: printf("no idea what this is\n");    }    printf("Bytes per scanline: %i\n", fixed_info.line_length);    printf("Visual type:        ");    switch (fixed_info.visual) {    case FB_VISUAL_TRUECOLOR: printf("truecolor\n"); break;    case FB_VISUAL_PSEUDOCOLOR: printf("pseudocolor\n"); break;    case FB_VISUAL_DIRECTCOLOR: printf("directcolor\n"); break;    case FB_VISUAL_STATIC_PSEUDOCOLOR: printf("fixed pseudocolor\n"); break;    default: printf("other (mono perhaps)\n");    }        /* Now get the variable screen info.       This contains more info about the current video mode.       (Note that this is effectively fixed on some framebuffer       devices -- many don't support mode switching.) */    if (ioctl(fbdev, FBIOGET_VSCREENINFO, &var_info) < 0) {	printf("Unable to retrieve variable screen info: %s\n",	       strerror(errno));	close(fbdev);	return 1;    }    /* Print out some info. */    printf("Bits per pixel:     %i\n", var_info.bits_per_pixel);    printf("Resolution:         %ix%i (virtual %ix%i)\n",	   var_info.xres, var_info.yres,	   var_info.xres_virtual, var_info.yres_virtual);    printf("Scrolling offset:   (%i,%i)\n",	   var_info.xoffset, var_info.yoffset);    printf("Red channel:        %i bits at offset %i\n",	   var_info.red.length, var_info.red.offset);    printf("Green channel:      %i bits at offset %i\n",	   var_info.red.length, var_info.green.offset);    printf("Blue channel:       %i bits at offset %i\n",	   var_info.red.length, var_info.blue.offset);    /* Now memory map the framebuffer.       According to the SDL source code, it's necessary to       compensate for a buggy mmap implementation on the       PowerPC. This should not be a problem for other       architectures. (This fix is lifted from SDL_fbvideo.c) */    ppc_fix = (((long)fixed_info.smem_start) -	       ((long) fixed_info.smem_start & ~(PAGE_SIZE-1)));    framebuffer_size = fixed_info.smem_len + ppc_fix;    framebuffer = mmap(NULL,		       framebuffer_size,		       PROT_READ | PROT_WRITE,		       MAP_SHARED,		       fbdev,		       0);    if (framebuffer == NULL) {	printf("Unable to mmap framebuffer: %s\n",	       strerror(errno));	close(fbdev);	return 1;    }    printf("Mapped framebuffer.\n");    /* Ok, now we'll get ready to plot the pixel.       We have several possible situations:       a) The current mode is indexed (pseudocolor).       We'll need to set a palette entry.       b) The current mode is truecolor (packed pixel).       No need to mess with the palette; there is none.       c) The current mode is directcolor (per-channel palettes).       We'll need to set a palette entry.       d) The current mode is static pseudocolor       (indexed, but with a fixed palette that we can't change).       This might be found on VGA adapters in 16-color mode.       We will IGNORE this case (gaming on 16-color devices       leaves much to be desired, and it's a hassle). */    /* Take the appropriate action based on the visual type. */    if ((fixed_info.visual == FB_VISUAL_PSEUDOCOLOR) ||	(fixed_info.visual == FB_VISUAL_DIRECTCOLOR)) {	/* We want a white pixel.	   Palette values are 16 bits each. */	r = 0xFFFF;	g = 0xFFFF;	b = 0xFFFF;	/* Set a single palette entry.	   Hijack color 255. */	colormap.start = 255;	colormap.len = 1;	colormap.red = &r;	colormap.green = &g;	colormap.blue = &b;	colormap.transp = NULL;	if (ioctl(fbdev, FBIOPUTCMAP, &colormap) < 0) {	    printf("WARNING: unable to set colormap.\n");	    /* This isn't really fatal, but our pixel	       probably won't show up correctly. */	}	pixel_r = 255;	pixel_g = 255;	pixel_b = 255;			/* This will work in both pseudocolor and	   directcolor modes. */	pixel_value = 0xFFFFFFFF;		    } else if (fixed_info.visual == FB_VISUAL_TRUECOLOR) {	/* White pixel. */	pixel_r = 0xFF;	pixel_g = 0xFF;	pixel_b = 0xFF;	/* We used this same pixel packing technique	   back when we were working with SDL. */	pixel_value = (((pixel_r >> (8-var_info.red.length)) <<			var_info.red.offset) +		       ((pixel_g >> (8-var_info.green.length)) <<			var_info.green.offset) +		       ((pixel_b >> (8-var_info.blue.length)) <<			var_info.blue.offset));    } else {	printf("Unsupported visual.\n");	pixel_value = 0;    }	    /* Now plot the pixel. The framebuffer interface allows       some modes to use a larger framebuffer than the       monitor's resolution (this is called a virtual resolution).       In this case some of the framebuffer isn't visible. We       can retrieve the starting coordinates of the visible       rectangle from the variable info structure. */	    x = var_info.xres / 2 + var_info.xoffset;    y = var_info.yres / 2 + var_info.yoffset;    switch (var_info.bits_per_pixel) {    case 8:	*((u_int8_t *)framebuffer +	  fixed_info.line_length * y + x) = (u_int8_t)pixel_value;	break;    case 16:	*((u_int16_t *)framebuffer +	  fixed_info.line_length/2 * y + x) = (u_int16_t)pixel_value;	break;    case 24:	/* 24-bit modes are generally slower than others because	   pixels are not aligned on word boundaries. This is why	   32-bit modes often outperform 24-bit modes. */	*((u_int8_t *)framebuffer +	  (fixed_info.line_length * y + 3 * x)) = (u_int8_t)pixel_r;	*((u_int8_t *)framebuffer +	  (fixed_info.line_length * y + 3 * x) + 1) = (u_int8_t)pixel_g;	*((u_int8_t *)framebuffer +	  (fixed_info.line_length * y + 3 * x) + 2) = (u_int8_t)pixel_b;	break;    case 32:	*((u_int32_t *)framebuffer +	  fixed_info.line_length/4 * y + x) = (u_int32_t)pixel_value;    default:	printf("Unsupported depth.\n");    }    /* Close the fbdev. */    munmap(framebuffer, framebuffer_size);    close(fbdev);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -