ref: 372afde46e7defc9dd2d719a1732b8ace1fa096e
dir: /linux/rw_svgalib.c/
/* ** RW_SVGALBI.C ** ** This file contains ALL Linux specific stuff having to do with the ** software refresh. When a port is being made the following functions ** must be implemented by the port: ** ** SWimp_EndFrame ** SWimp_Init ** SWimp_InitGraphics ** SWimp_SetPalette ** SWimp_Shutdown ** SWimp_SwitchFullscreen */ #include <termios.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <sys/vt.h> #include <stdarg.h> #include <stdio.h> #include <signal.h> #include <sys/mman.h> #include <asm/io.h> #include "vga.h" #include "vgakeyboard.h" #include "vgamouse.h" #include "../ref_soft/r_local.h" #include "../client/keys.h" #include "../linux/rw_linux.h" /*****************************************************************************/ int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; byte *VGA_pagebase; char *framebuffer_ptr; void VGA_UpdatePlanarScreen (void *srcbuffer); int num_modes; vga_modeinfo *modes; int current_mode; // Console variables that we need to access from this module /*****************************************************************************/ void VID_InitModes(void) { int i; // get complete information on all modes num_modes = vga_lastmodenumber()+1; modes = malloc(num_modes * sizeof(vga_modeinfo)); for (i=0 ; i<num_modes ; i++) { if (vga_hasmode(i)) memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo)); else modes[i].width = 0; // means not available } // filter for modes i don't support for (i=0 ; i<num_modes ; i++) { if (modes[i].bytesperpixel != 1 && modes[i].colors != 256) modes[i].width = 0; } for (i = 0; i < num_modes; i++) if (modes[i].width) ri.Con_Printf(PRINT_ALL, "mode %d: %d %d\n", modes[i].width, modes[i].height); } /* ** SWimp_Init ** ** This routine is responsible for initializing the implementation ** specific stuff in a software rendering subsystem. */ int SWimp_Init( void *hInstance, void *wndProc ) { vga_init(); VID_InitModes(); return true; } int get_mode(int width, int height) { int i; int ok, match; for (i=0 ; i<num_modes ; i++) if (modes[i].width && modes[i].width == width && modes[i].height == height) break; if (i==num_modes) return -1; // not found return i; } /* ** SWimp_InitGraphics ** ** This initializes the software refresh's implementation specific ** graphics subsystem. In the case of Windows it creates DIB or ** DDRAW surfaces. ** ** The necessary width and height parameters are grabbed from ** vid.width and vid.height. */ static qboolean SWimp_InitGraphics( qboolean fullscreen ) { int bsize, zsize, tsize; SWimp_Shutdown(); current_mode = get_mode(vid.width, vid.height); if (current_mode < 0) { ri.Con_Printf (PRINT_ALL, "Mode %d %d not found\n", vid.width, vid.height); return false; // mode not found } // let the sound and input subsystems know about the new window ri.Vid_NewWindow (vid.width, vid.height); ri.Con_Printf (PRINT_ALL, "Setting VGAMode: %d\n", current_mode ); // Cvar_SetValue ("vid_mode", (float)modenum); VGA_width = modes[current_mode].width; VGA_height = modes[current_mode].height; VGA_planar = modes[current_mode].bytesperpixel == 0; VGA_rowbytes = modes[current_mode].linewidth; vid.rowbytes = modes[current_mode].linewidth; if (VGA_planar) { VGA_bufferrowbytes = modes[current_mode].linewidth * 4; vid.rowbytes = modes[current_mode].linewidth*4; } // get goin' vga_setmode(current_mode); VGA_pagebase = framebuffer_ptr = (char *) vga_getgraphmem(); // if (vga_setlinearaddressing()>0) // framebuffer_ptr = (char *) vga_getgraphmem(); if (!framebuffer_ptr) Sys_Error("This mode isn't hapnin'\n"); vga_setpage(0); vid.buffer = malloc(vid.rowbytes * vid.height); if (!vid.buffer) Sys_Error("Unabled to alloc vid.buffer!\n"); return true; } /* ** SWimp_EndFrame ** ** This does an implementation specific copy from the backbuffer to the ** front buffer. In the Win32 case it uses BitBlt or BltFast depending ** on whether we're using DIB sections/GDI or DDRAW. */ void SWimp_EndFrame (void) { if (!vga_oktowrite()) return; // can't update screen if it's not active // if (vid_waitforrefresh.value) // vga_waitretrace(); if (VGA_planar) VGA_UpdatePlanarScreen (vid.buffer); else { int total = vid.rowbytes * vid.height; int offset; for (offset=0;offset<total;offset+=0x10000) { vga_setpage(offset/0x10000); memcpy(framebuffer_ptr, vid.buffer + offset, ((total-offset>0x10000)?0x10000:(total-offset))); } } } /* ** SWimp_SetMode */ rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen ) { rserr_t retval = rserr_ok; ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode ); if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) ) { ri.Con_Printf( PRINT_ALL, " invalid mode\n" ); return rserr_invalid_mode; } ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight); if ( !SWimp_InitGraphics( false ) ) { // failed to set a valid mode in windowed mode return rserr_invalid_mode; } R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table ); return retval; } /* ** SWimp_SetPalette ** ** System specific palette setting routine. A NULL palette means ** to use the existing palette. The palette is expected to be in ** a padded 4-byte xRGB format. */ void SWimp_SetPalette( const unsigned char *palette ) { static int tmppal[256*3]; const unsigned char *pal; int *tp; int i; if ( !palette ) palette = ( const unsigned char * ) sw_state.currentpalette; if (vga_getcolors() == 256) { tp = tmppal; pal = palette; for (i=0 ; i < 256 ; i++, pal += 4, tp += 3) { tp[0] = pal[0] >> 2; tp[1] = pal[1] >> 2; tp[2] = pal[2] >> 2; } if (vga_oktowrite()) vga_setpalvec(0, 256, tmppal); } } /* ** SWimp_Shutdown ** ** System specific graphics subsystem shutdown routine. Destroys ** DIBs or DDRAW surfaces as appropriate. */ void SWimp_Shutdown( void ) { if (vid.buffer) { free(vid.buffer); vid.buffer = NULL; } vga_setmode(TEXT); } /* ** SWimp_AppActivate */ void SWimp_AppActivate( qboolean active ) { } //=============================================================================== /* ================ Sys_MakeCodeWriteable ================ */ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) { int r; unsigned long addr; int psize = getpagesize(); addr = (startaddr & ~(psize-1)) - psize; // fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, // addr, startaddr+length, length); r = mprotect((char*)addr, length + startaddr - addr + psize, 7); if (r < 0) Sys_Error("Protection change failed\n"); }