scrdrv.c
来自「Genode FX is a composition of hardware a」· C语言 代码 · 共 371 行
C
371 行
/* * \brief DOpE screen driver module * \date 2002-11-13 * \author Norman Feske <norman.feske@genode-labs.com> * * This component is the screen output interface of * DOpE. It handles two frame buffers: the physically * visible frame buffer and a background buffer. All * graphics operations are applied to the background * buffer and transfered to the physical frame buffer * afterwards. This component is also responsible for * drawing the mouse cursor. * It uses SDL for accessing the screen under linux. *//* * Copyright (C) 2002-2008 Norman Feske <norman.feske@genode-labs.com> * Genode Labs, Feske & Helmuth Systementwicklung GbR * * This file is part of the DOpE-embedded package, which is distributed * under the terms of the GNU General Public License version 2. *//* general includes */#include <signal.h>#include <stdio.h>/* SDL includes */#include <SDL/SDL.h>/* local includes */#include "dopestd.h"#include "scrdrv.h"#include "clipping.h"#ifndef SDL_DISABLE#define SDL_DISABLE 0#endif#define SCR_DEBUG 0static long scr_width,scr_height,scr_depth;static void *scr_adr;static long curr_mx = 100,curr_my = 100;static SDL_Surface *screen;static struct clipping_services *clip;int init_scrdrv(struct dope_services *d);static void draw_cursor(short *data,long x,long y){ static int i,j; short *dst = (short *)scr_adr + y*scr_width + x; short *d; short *s = data; int w = *(data++), h = *(data++); int linelen = w; if (x >= scr_width) return; if (y >= scr_height) return; if (x >= scr_width - 16) linelen = scr_width - x; if (y >= scr_height - 16) h = scr_height - y; for (j = 0; j < h; j++) { d = dst; s = data; for (i = 0; i < linelen; i++) { if (*s) *d = *s; d++; s++; } dst += scr_width; data += w; }}static short bg_buffer[20][16];static void save_background(long x, long y){ short *src = (short *)scr_adr + y*scr_width + x; short *dst = (short *)&bg_buffer; short *s; static int i, j; int h = 16; if (y >= scr_height - 16) h = scr_height - y; for (j = 0; j < h; j++) { s = src; for (i = 0; i < 16; i++) { *(dst++) = *(s++); } src += scr_width; }}static void restore_background(long x, long y){ short *src = (short *)&bg_buffer; short *dst = (short *)scr_adr + y*scr_width + x; short *d; static int i, j; int h = 16; if (y >= scr_height - 16) h = scr_height - y; for (j = 0; j < h; j++) { d = dst; for (i = 0; i < 16; i++) { *(d++) = *(src++); } dst += scr_width; }}extern short smallmouse_trp;extern short bigmouse_trp;/*********************** ** Service functions ** ***********************//** * Set up screen */static long set_screen(long width, long height, long depth){ scr_width = width; scr_height = height; scr_depth = depth; if (SCR_DEBUG) { screen = SDL_SetVideoMode(scr_width, scr_height*2 + 100, scr_depth, SDL_SWSURFACE); } else { screen = SDL_SetVideoMode(scr_width, scr_height + 20, scr_depth, SDL_SWSURFACE); } if (!screen) return 0; scr_adr = screen->pixels; SDL_ShowCursor(SDL_DISABLE); return 1;}/** * Deinitialisation */static void restore_screen(void){ /* nothing to restore - sdl is too good */}/** * Provide information about the screen */static long get_scr_width (void) {return scr_width;}static long get_scr_height (void) {return scr_height;}static long get_scr_depth (void) {return scr_depth;}static void *get_scr_adr (void) {return scr_adr;}static void *get_buf_adr (void) {return scr_adr;}#if (SCR_DEBUG)static void shade_area(long x1, long y1, long x2, long y2){ u16 *dst = scr_adr; u16 i; if (!SCR_DEBUG) return; if (y1 < 0) y1 = 0; if (y2 < 0) y2 = 0; if (y1 >= scr_height) y1 = scr_height - 1; if (y2 >= scr_height) y2 = scr_height - 1; dst += scr_width*scr_height; dst += y1*scr_width; for (; y1 < y2; y1++) { for (i = x1; i < x2; i++) dst[i] += 12; dst += scr_width; }}#endif/*static void scr_reset_shade(void){ u32 i = scr_width*scr_height; u16 *d = scr_adr; if (!SCR_DEBUG) return; d += scr_width*scr_height; while (i--) *(d++) = 0; SDL_UpdateRect(screen, 0, scr_height, scr_width, scr_height);}*/#ifdef FILTER_PIXELS/** * Filter pixels to emulate low color depth */static void filter_area(long x1, long y1, long x2, long y2){ long dx; long dy; long v; long i, j; u16 *src, *dst; u16 *s, *d; /* apply clipping to specified area */ if (x1 < (v = clip->get_x1())) x1 = v; if (y1 < (v = clip->get_y1())) y1 = v; if (x2 > (v = clip->get_x2())) x2 = v; if (y2 > (v = clip->get_y2())) y2 = v; dx = x2 - x1; dy = y2 - y1; if (dx >= 0 && dy >= 0) { /* determine offset of left top corner of the area to update */ src = (u16 *)scr_adr + y1*scr_width + x1; dst = (u16 *)scr_adr + y1*scr_width + x1; for (j = dy + 1; j--; ) { /* copy and filter line */ d = (u16 *)dst; s = (u16 *)src; for (i = (dx); i--; ) *(d++) = *(s++) & (0xf000 | 0x07c0 | 0x1e); src += scr_width; dst += scr_width; } }}#endif /* FILTER_PIXELS *//** * Make changes on the screen visible (buffered output) */static void update_area(long x1, long y1, long x2, long y2){ long dx, dy, d; int cursor_visible = 0;#ifdef FILTER_PIXELS filter_area(x1, y1, x2, y2);#endif if ((curr_mx < x2) && (curr_mx + 16 > x1) && (curr_my < y2) && (curr_my + 16 > y1)) { save_background(curr_mx, curr_my); draw_cursor(&bigmouse_trp, curr_mx, curr_my); cursor_visible = 1; } /* apply clipping to specified area */ if (x1 < (d = clip->get_x1())) x1 = d; if (y1 < (d = clip->get_y1())) y1 = d; if (x2 > (d = clip->get_x2())) x2 = d; if (y2 > (d = clip->get_y2())) y2 = d; dx = x2 - x1; dy = y2 - y1; if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; SDL_UpdateRect(screen, x1, y1, dx + 1, dy + 1);#if (SCR_DEBUG) shade_area(x1, y1, x1 + dx + 1, y1 + dy + 1); SDL_UpdateRect(screen, x1, y1 + scr_height, dx + 1, dy + 1);#endif if (cursor_visible) restore_background(curr_mx, curr_my);}/** * Set mouse cursor to the specified position */static void set_mouse_pos(long mx, long my){ int old_mx = curr_mx, old_my = curr_my; /* check if position really changed */ if ((curr_mx == mx) && (curr_my == my)) return; curr_mx = mx; curr_my = my; update_area(curr_mx, curr_my, curr_mx + 16, curr_my + 16); update_area(old_mx, old_my, old_mx + 16, old_my + 16);}/** * Set new mouse shape */static void set_mouse_shape(void *new_shape){ /* not built in yet... */}/************************************** ** Service structure of this module ** **************************************/static struct scrdrv_services services = { set_screen, restore_screen, get_scr_width, get_scr_height, get_scr_depth, get_scr_adr, get_buf_adr, update_area, set_mouse_pos, set_mouse_shape,};/********************* ** Screenshot hook ** *********************//** * Signal handler for usr1: dump screenshot */static void catch_usr1_signal(int signum){ char *scr_fname = "screen.pnm"; FILE *fh; int i, j; u16 *s; /* pixel source address */ signal(SIGUSR1, catch_usr1_signal); fh = fopen(scr_fname, "w"); printf("dumping screen to file %s\n", scr_fname); /* write header */ fprintf(fh, "P3\n# CREATOR: DOpE\n%d %d\n255\n", (int)scr_width, (int)scr_height); /* write pixel data */ s = (u16 *)scr_adr; for (j = 0; j < scr_height; j++) for (i = 0; i < scr_width; i++, s++) { fprintf(fh, "%d\n", (*s & 0xf800) >> 8); fprintf(fh, "%d\n", (*s & 0x07e0) >> 3); fprintf(fh, "%d\n", (*s & 0x001f) << 3); } /* close file */ fclose(fh);}/************************ ** Module entry point ** ************************/int init_scrdrv(struct dope_services *d){ if (SDL_Init(SDL_INIT_VIDEO) < 0) return 0; signal(SIGSEGV, SIG_DFL); /* install signal handler to take screenshots */ signal(SIGUSR1, catch_usr1_signal); clip = d->get_module("Clipping 1.0"); d->register_module("ScreenDriver 1.0", &services); return 1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?